Merge "TaskManager API first pass."
diff --git a/Android.mk b/Android.mk
index 9994373..966c64d 100644
--- a/Android.mk
+++ b/Android.mk
@@ -157,6 +157,7 @@
 	core/java/android/net/INetworkManagementEventObserver.aidl \
 	core/java/android/net/INetworkPolicyListener.aidl \
 	core/java/android/net/INetworkPolicyManager.aidl \
+	core/java/android/net/INetworkScoreService.aidl \
 	core/java/android/net/INetworkStatsService.aidl \
 	core/java/android/net/INetworkStatsSession.aidl \
 	core/java/android/net/nsd/INsdManager.aidl \
@@ -181,6 +182,8 @@
 	core/java/android/os/IUserManager.aidl \
 	core/java/android/os/IVibratorService.aidl \
 	core/java/android/service/notification/INotificationListener.aidl \
+	core/java/android/service/notification/IConditionListener.aidl \
+	core/java/android/service/notification/IConditionProvider.aidl \
 	core/java/android/print/ILayoutResultCallback.aidl \
 	core/java/android/print/IPrinterDiscoveryObserver.aidl \
 	core/java/android/print/IPrintDocumentAdapter.aidl \
@@ -198,6 +201,9 @@
 	core/java/android/service/dreams/IDreamService.aidl \
 	core/java/android/service/trust/ITrustAgentService.aidl \
 	core/java/android/service/trust/ITrustAgentServiceCallback.aidl \
+	core/java/android/service/voice/IVoiceInteractionService.aidl \
+	core/java/android/service/voice/IVoiceInteractionSession.aidl \
+	core/java/android/service/voice/IVoiceInteractionSessionService.aidl \
 	core/java/android/service/wallpaper/IWallpaperConnection.aidl \
 	core/java/android/service/wallpaper/IWallpaperEngine.aidl \
 	core/java/android/service/wallpaper/IWallpaperService.aidl \
@@ -231,6 +237,10 @@
 	core/java/com/android/internal/app/IBatteryStats.aidl \
 	core/java/com/android/internal/app/IProcessStats.aidl \
 	core/java/com/android/internal/app/IUsageStats.aidl \
+	core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl \
+	core/java/com/android/internal/app/IVoiceInteractor.aidl \
+	core/java/com/android/internal/app/IVoiceInteractorCallback.aidl \
+	core/java/com/android/internal/app/IVoiceInteractorRequest.aidl \
 	core/java/com/android/internal/app/IMediaContainerService.aidl \
 	core/java/com/android/internal/appwidget/IAppWidgetService.aidl \
 	core/java/com/android/internal/appwidget/IAppWidgetHost.aidl \
@@ -290,11 +300,14 @@
 	media/java/android/media/IRemoteDisplayProvider.aidl \
 	media/java/android/media/IRemoteVolumeObserver.aidl \
 	media/java/android/media/IRingtonePlayer.aidl \
-	media/java/android/media/session/IMediaController.aidl \
-	media/java/android/media/session/IMediaControllerCallback.aidl \
-	media/java/android/media/session/IMediaSession.aidl \
-	media/java/android/media/session/IMediaSessionCallback.aidl \
-	media/java/android/media/session/IMediaSessionManager.aidl \
+	media/java/android/media/routeprovider/IRouteConnection.aidl \
+	media/java/android/media/routeprovider/IRouteProvider.aidl \
+	media/java/android/media/routeprovider/IRouteProviderCallback.aidl \
+	media/java/android/media/session/ISessionController.aidl \
+	media/java/android/media/session/ISessionControllerCallback.aidl \
+	media/java/android/media/session/ISession.aidl \
+	media/java/android/media/session/ISessionCallback.aidl \
+	media/java/android/media/session/ISessionManager.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl \
 	telephony/java/com/android/internal/telephony/IPhoneSubInfo.aidl \
 	telephony/java/com/android/internal/telephony/ITelephony.aidl \
@@ -422,6 +435,8 @@
 	frameworks/base/core/java/android/view/MotionEvent.aidl \
 	frameworks/base/core/java/android/view/Surface.aidl \
 	frameworks/base/core/java/android/view/WindowManager.aidl \
+	frameworks/base/core/java/android/view/WindowAnimationFrameStats.aidl \
+	frameworks/base/core/java/android/view/WindowContentFrameStats.aidl \
 	frameworks/base/core/java/android/widget/RemoteViews.aidl \
 	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerService.aidl \
 	frameworks/base/core/java/com/android/internal/textservice/ISpellCheckerSession.aidl \
diff --git a/CleanSpec.mk b/CleanSpec.mk
index ffdac4e..c6f6a62 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -189,6 +189,7 @@
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/IMedia*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/view/IMagnificationCallbacks*)
 $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/core/java/android/tv/)
+$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework-base_intermediates/src/media/java/android/media/)
 
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
diff --git a/api/current.txt b/api/current.txt
index ed6cba7..e206528 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -27,14 +27,17 @@
     field public static final java.lang.String BIND_NOTIFICATION_LISTENER_SERVICE = "android.permission.BIND_NOTIFICATION_LISTENER_SERVICE";
     field public static final java.lang.String BIND_PRINT_SERVICE = "android.permission.BIND_PRINT_SERVICE";
     field public static final java.lang.String BIND_REMOTEVIEWS = "android.permission.BIND_REMOTEVIEWS";
+    field public static final java.lang.String BIND_ROUTE_PROVIDER = "android.permission.BIND_ROUTE_PROVIDER";
     field public static final java.lang.String BIND_TEXT_SERVICE = "android.permission.BIND_TEXT_SERVICE";
     field public static final java.lang.String BIND_TRUST_AGENT_SERVICE = "android.permission.BIND_TRUST_AGENT_SERVICE";
     field public static final java.lang.String BIND_TV_INPUT = "android.permission.BIND_TV_INPUT";
+    field public static final java.lang.String BIND_VOICE_INTERACTION = "android.permission.BIND_VOICE_INTERACTION";
     field public static final java.lang.String BIND_VPN_SERVICE = "android.permission.BIND_VPN_SERVICE";
     field public static final java.lang.String BIND_WALLPAPER = "android.permission.BIND_WALLPAPER";
     field public static final java.lang.String BLUETOOTH = "android.permission.BLUETOOTH";
     field public static final java.lang.String BLUETOOTH_ADMIN = "android.permission.BLUETOOTH_ADMIN";
     field public static final java.lang.String BLUETOOTH_PRIVILEGED = "android.permission.BLUETOOTH_PRIVILEGED";
+    field public static final java.lang.String BODY_SENSORS = "android.permission.BODY_SENSORS";
     field public static final java.lang.String BRICK = "android.permission.BRICK";
     field public static final java.lang.String BROADCAST_PACKAGE_REMOVED = "android.permission.BROADCAST_PACKAGE_REMOVED";
     field public static final java.lang.String BROADCAST_SMS = "android.permission.BROADCAST_SMS";
@@ -282,6 +285,7 @@
     field public static final int allContactsName = 16843468; // 0x10102cc
     field public static final int allowBackup = 16843392; // 0x1010280
     field public static final int allowClearUserData = 16842757; // 0x1010005
+    field public static final int allowEmbedded = 16843765; // 0x10103f5
     field public static final int allowParallelSyncs = 16843570; // 0x1010332
     field public static final int allowSingleTap = 16843353; // 0x1010259
     field public static final int allowTaskReparenting = 16843268; // 0x1010204
@@ -381,6 +385,7 @@
     field public static final int codes = 16843330; // 0x1010242
     field public static final int collapseColumns = 16843083; // 0x101014b
     field public static final int color = 16843173; // 0x10101a5
+    field public static final int colorAccent = 16843842; // 0x1010442
     field public static final int colorActivatedHighlight = 16843664; // 0x1010390
     field public static final int colorBackground = 16842801; // 0x1010031
     field public static final int colorBackgroundCacheHint = 16843435; // 0x10102ab
@@ -396,6 +401,9 @@
     field public static final int colorLongPressedHighlight = 16843662; // 0x101038e
     field public static final int colorMultiSelectHighlight = 16843665; // 0x1010391
     field public static final int colorPressedHighlight = 16843661; // 0x101038d
+    field public static final int colorPrimary = 16843840; // 0x1010440
+    field public static final int colorPrimaryDark = 16843841; // 0x1010441
+    field public static final int colorPrimaryLight = 16843839; // 0x101043f
     field public static final int columnCount = 16843639; // 0x1010377
     field public static final int columnDelay = 16843215; // 0x10101cf
     field public static final int columnOrderPreserved = 16843640; // 0x1010378
@@ -483,6 +491,7 @@
     field public static final int editTextStyle = 16842862; // 0x101006e
     field public static final deprecated int editable = 16843115; // 0x101016b
     field public static final int editorExtras = 16843300; // 0x1010224
+    field public static final int elevation = 16843852; // 0x101044c
     field public static final int ellipsize = 16842923; // 0x10100ab
     field public static final int ems = 16843096; // 0x1010158
     field public static final int enabled = 16842766; // 0x101000e
@@ -492,7 +501,9 @@
     field public static final int entries = 16842930; // 0x10100b2
     field public static final int entryValues = 16843256; // 0x10101f8
     field public static final int eventsInterceptionEnabled = 16843389; // 0x101027d
+    field public static final int excludeClass = 16843854; // 0x101044e
     field public static final int excludeFromRecents = 16842775; // 0x1010017
+    field public static final int excludeId = 16843853; // 0x101044d
     field public static final int exitFadeDuration = 16843533; // 0x101030d
     field public static final int expandableListPreferredChildIndicatorLeft = 16842834; // 0x1010052
     field public static final int expandableListPreferredChildIndicatorRight = 16842835; // 0x1010053
@@ -694,7 +705,6 @@
     field public static final int l_resource_pad25 = 16843768; // 0x10103f8
     field public static final int l_resource_pad26 = 16843767; // 0x10103f7
     field public static final int l_resource_pad27 = 16843766; // 0x10103f6
-    field public static final int l_resource_pad28 = 16843765; // 0x10103f5
     field public static final int l_resource_pad3 = 16843790; // 0x101040e
     field public static final int l_resource_pad4 = 16843789; // 0x101040d
     field public static final int l_resource_pad5 = 16843788; // 0x101040c
@@ -819,6 +829,7 @@
     field public static final int name = 16842755; // 0x1010003
     field public static final int navigationMode = 16843471; // 0x10102cf
     field public static final int negativeButtonText = 16843254; // 0x10101f6
+    field public static final int nestedScrollingEnabled = 16843843; // 0x1010443
     field public static final int nextFocusDown = 16842980; // 0x10100e4
     field public static final int nextFocusForward = 16843580; // 0x101033c
     field public static final int nextFocusLeft = 16842977; // 0x10100e1
@@ -1001,6 +1012,7 @@
     field public static final int selectedDateVerticalBar = 16843591; // 0x1010347
     field public static final int selectedWeekBackgroundColor = 16843586; // 0x1010342
     field public static final int sequence = 16843815; // 0x1010427
+    field public static final int sessionService = 16843850; // 0x101044a
     field public static final int settingsActivity = 16843301; // 0x1010225
     field public static final int shadowColor = 16843105; // 0x1010161
     field public static final int shadowDx = 16843106; // 0x1010162
@@ -1096,6 +1108,7 @@
     field public static final int switchMinWidth = 16843632; // 0x1010370
     field public static final int switchPadding = 16843633; // 0x1010371
     field public static final int switchPreferenceStyle = 16843629; // 0x101036d
+    field public static final int switchStyle = 16843851; // 0x101044b
     field public static final int switchTextAppearance = 16843630; // 0x101036e
     field public static final int switchTextOff = 16843628; // 0x101036c
     field public static final int switchTextOn = 16843627; // 0x101036b
@@ -1132,6 +1145,7 @@
     field public static final int textAppearanceLargeInverse = 16842819; // 0x1010043
     field public static final int textAppearanceLargePopupMenu = 16843521; // 0x1010301
     field public static final int textAppearanceListItem = 16843678; // 0x101039e
+    field public static final int textAppearanceListItemSecondary = 16843838; // 0x101043e
     field public static final int textAppearanceListItemSmall = 16843679; // 0x101039f
     field public static final int textAppearanceMedium = 16842817; // 0x1010041
     field public static final int textAppearanceMediumInverse = 16842820; // 0x1010044
@@ -1278,6 +1292,8 @@
     field public static final int windowActionBar = 16843469; // 0x10102cd
     field public static final int windowActionBarOverlay = 16843492; // 0x10102e4
     field public static final int windowActionModeOverlay = 16843485; // 0x10102dd
+    field public static final int windowAllowEnterTransitionOverlap = 16843849; // 0x1010449
+    field public static final int windowAllowExitTransitionOverlap = 16843848; // 0x1010448
     field public static final int windowAnimationStyle = 16842926; // 0x10100ae
     field public static final int windowBackground = 16842836; // 0x1010054
     field public static final int windowCloseOnTouchOutside = 16843611; // 0x101035b
@@ -1287,7 +1303,9 @@
     field public static final int windowDisablePreview = 16843298; // 0x1010222
     field public static final int windowEnableSplitTouch = 16843543; // 0x1010317
     field public static final int windowEnterAnimation = 16842932; // 0x10100b4
+    field public static final int windowEnterTransition = 16843844; // 0x1010444
     field public static final int windowExitAnimation = 16842933; // 0x10100b5
+    field public static final int windowExitTransition = 16843845; // 0x1010445
     field public static final int windowFrame = 16842837; // 0x1010055
     field public static final int windowFullscreen = 16843277; // 0x101020d
     field public static final int windowHideAnimation = 16842935; // 0x10100b7
@@ -1298,6 +1316,8 @@
     field public static final int windowNoDisplay = 16843294; // 0x101021e
     field public static final int windowNoTitle = 16842838; // 0x1010056
     field public static final int windowOverscan = 16843727; // 0x10103cf
+    field public static final int windowSharedElementEnterTransition = 16843846; // 0x1010446
+    field public static final int windowSharedElementExitTransition = 16843847; // 0x1010447
     field public static final int windowShowAnimation = 16842934; // 0x10100b6
     field public static final int windowShowWallpaper = 16843410; // 0x1010292
     field public static final int windowSoftInputMode = 16843307; // 0x101022b
@@ -1612,6 +1632,7 @@
     field public static final int selectAll = 16908319; // 0x102001f
     field public static final int selectTextMode = 16908333; // 0x102002d
     field public static final int selectedIcon = 16908302; // 0x102000e
+    field public static final int shared_element = 16908355; // 0x1020043
     field public static final int shared_element_name = 16908353; // 0x1020041
     field public static final int startSelectingText = 16908328; // 0x1020028
     field public static final int stopSelectingText = 16908329; // 0x1020029
@@ -1648,7 +1669,14 @@
     field public static final int decelerate_cubic = 17563651; // 0x10c0003
     field public static final int decelerate_quad = 17563649; // 0x10c0001
     field public static final int decelerate_quint = 17563653; // 0x10c0005
+    field public static final int fast_out_linear_in = 17563667; // 0x10c0013
+    field public static final int fast_out_slow_in = 17563665; // 0x10c0011
+    field public static final int l_resource_pad1 = 17563664; // 0x10c0010
+    field public static final int l_resource_pad2 = 17563663; // 0x10c000f
+    field public static final int l_resource_pad3 = 17563662; // 0x10c000e
+    field public static final int l_resource_pad4 = 17563661; // 0x10c000d
     field public static final int linear = 17563659; // 0x10c000b
+    field public static final int linear_out_slow_in = 17563666; // 0x10c0012
     field public static final int overshoot = 17563656; // 0x10c0008
   }
 
@@ -2445,6 +2473,11 @@
     field public static final int l_resource_pad9 = 16974328; // 0x10301f8
   }
 
+  public static final class R.transition {
+    ctor public R.transition();
+    field public static final int no_transition = 17760256; // 0x10f0000
+  }
+
   public static final class R.xml {
     ctor public R.xml();
   }
@@ -2455,6 +2488,7 @@
 
   public abstract class AccessibilityService extends android.app.Service {
     ctor public AccessibilityService();
+    method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
@@ -3153,6 +3187,7 @@
     method public void finishActivity(int);
     method public void finishActivityFromChild(android.app.Activity, int);
     method public void finishAffinity();
+    method public void finishAndRemoveTask();
     method public void finishFromChild(android.app.Activity);
     method public void finishWithTransition();
     method public android.app.ActionBar getActionBar();
@@ -3178,6 +3213,7 @@
     method public int getTaskId();
     method public final java.lang.CharSequence getTitle();
     method public final int getTitleColor();
+    method public android.app.VoiceInteractor getVoiceInteractor();
     method public final int getVolumeControlStream();
     method public android.view.Window getWindow();
     method public android.view.WindowManager getWindowManager();
@@ -3189,6 +3225,7 @@
     method public boolean isFinishing();
     method public boolean isImmersive();
     method public boolean isTaskRoot();
+    method public boolean isVoiceInteraction();
     method public final deprecated android.database.Cursor managedQuery(android.net.Uri, java.lang.String[], java.lang.String, java.lang.String[], java.lang.String);
     method public boolean moveTaskToBack(boolean);
     method public boolean navigateUpTo(android.content.Intent);
@@ -3199,8 +3236,6 @@
     method public void onAttachFragment(android.app.Fragment);
     method public void onAttachedToWindow();
     method public void onBackPressed();
-    method public void onCaptureSharedElementEnd();
-    method public void onCaptureSharedElementStart(android.transition.Transition);
     method protected void onChildTitleChanged(android.app.Activity, java.lang.CharSequence);
     method public void onConfigurationChanged(android.content.res.Configuration);
     method public void onContentChanged();
@@ -3273,6 +3308,7 @@
     method public final void runOnUiThread(java.lang.Runnable);
     method public void setActionBar(android.widget.Toolbar);
     method public void setActivityLabelAndIcon(java.lang.CharSequence, android.graphics.Bitmap);
+    method public void setActivityTransitionListener(android.app.ActivityOptions.ActivityTransitionListener);
     method public void setContentTransitionManager(android.transition.TransitionManager);
     method public void setContentView(int);
     method public void setContentView(android.view.View);
@@ -3490,13 +3526,28 @@
   public class ActivityOptions {
     method public static android.app.ActivityOptions makeCustomAnimation(android.content.Context, int, int);
     method public static android.app.ActivityOptions makeScaleUpAnimation(android.view.View, int, int, int, int);
-    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.view.View, java.lang.String);
-    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.util.Pair<android.view.View, java.lang.String>...);
+    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.view.Window, android.view.View, java.lang.String);
+    method public static android.app.ActivityOptions makeSceneTransitionAnimation(android.view.Window, android.app.ActivityOptions.ActivityTransitionListener);
     method public static android.app.ActivityOptions makeThumbnailScaleUpAnimation(android.view.View, android.graphics.Bitmap, int, int);
     method public android.os.Bundle toBundle();
     method public void update(android.app.ActivityOptions);
   }
 
+  public static class ActivityOptions.ActivityTransitionListener {
+    ctor public ActivityOptions.ActivityTransitionListener();
+    method public android.util.Pair<android.view.View, java.lang.String>[] getSharedElementsMapping();
+    method public boolean handleRejectedSharedElements(java.util.List<android.view.View>);
+    method public void onCaptureSharedElementEnd(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+    method public void onCaptureSharedElementStart(java.util.List<java.lang.String>, java.util.List<android.view.View>, java.util.List<android.view.View>);
+    method public void onEnterReady();
+    method public void onExitTransitionComplete();
+    method public void onRemoteExitComplete();
+    method public void onSharedElementExitTransitionComplete();
+    method public void onSharedElementTransferred(java.util.List<java.lang.String>, java.util.List<android.view.View>);
+    method public void onStartEnterTransition(java.util.List<java.lang.String>, java.util.List<android.view.View>);
+    method public void onStartExitTransition(java.util.List<java.lang.String>, java.util.List<android.view.View>);
+  }
+
   public class AlarmManager {
     method public void cancel(android.app.PendingIntent);
     method public void set(int, long, android.app.PendingIntent);
@@ -4452,6 +4503,7 @@
     ctor public Notification.Builder(android.content.Context);
     method public android.app.Notification.Builder addAction(int, java.lang.CharSequence, android.app.PendingIntent);
     method public android.app.Notification.Builder addExtras(android.os.Bundle);
+    method public android.app.Notification.Builder addPerson(java.lang.String);
     method public android.app.Notification build();
     method public android.os.Bundle getExtras();
     method public deprecated android.app.Notification getNotification();
@@ -4750,9 +4802,14 @@
   }
 
   public final class UiAutomation {
+    method public void clearWindowAnimationFrameStats();
+    method public boolean clearWindowContentFrameStats(int);
     method public android.view.accessibility.AccessibilityEvent executeAndWaitForEvent(java.lang.Runnable, android.app.UiAutomation.AccessibilityEventFilter, long) throws java.util.concurrent.TimeoutException;
+    method public android.view.accessibility.AccessibilityNodeInfo findFocus(int);
     method public android.view.accessibility.AccessibilityNodeInfo getRootInActiveWindow();
     method public final android.accessibilityservice.AccessibilityServiceInfo getServiceInfo();
+    method public android.view.WindowAnimationFrameStats getWindowAnimationFrameStats();
+    method public android.view.WindowContentFrameStats getWindowContentFrameStats(int);
     method public java.util.List<android.view.accessibility.AccessibilityWindowInfo> getWindows();
     method public boolean injectInputEvent(android.view.InputEvent, boolean);
     method public final boolean performGlobalAction(int);
@@ -4795,6 +4852,29 @@
     field public static final int MODE_NIGHT_YES = 2; // 0x2
   }
 
+  public class VoiceInteractor {
+    method public boolean submitRequest(android.app.VoiceInteractor.Request);
+    method public boolean[] supportsCommands(java.lang.String[]);
+  }
+
+  public static class VoiceInteractor.CommandRequest extends android.app.VoiceInteractor.Request {
+    ctor public VoiceInteractor.CommandRequest(java.lang.String, android.os.Bundle);
+    method public void onCommandResult(android.os.Bundle);
+  }
+
+  public static class VoiceInteractor.ConfirmationRequest extends android.app.VoiceInteractor.Request {
+    ctor public VoiceInteractor.ConfirmationRequest(java.lang.CharSequence, android.os.Bundle);
+    method public void onConfirmationResult(boolean, android.os.Bundle);
+  }
+
+  public static abstract class VoiceInteractor.Request {
+    ctor public VoiceInteractor.Request();
+    method public void cancel();
+    method public android.app.Activity getActivity();
+    method public android.content.Context getContext();
+    method public void onCancel();
+  }
+
   public final class WallpaperInfo implements android.os.Parcelable {
     ctor public WallpaperInfo(android.content.Context, android.content.pm.ResolveInfo) throws java.io.IOException, org.xmlpull.v1.XmlPullParserException;
     method public int describeContents();
@@ -4904,8 +4984,13 @@
 
   public class DevicePolicyManager {
     method public void addPersistentPreferredActivity(android.content.ComponentName, android.content.IntentFilter, android.content.ComponentName);
+    method public void addUserRestriction(android.content.ComponentName, java.lang.String);
+    method public void clearForwardingIntentFilters(android.content.ComponentName);
     method public void clearPackagePersistentPreferredActivities(android.content.ComponentName, java.lang.String);
+    method public void clearUserRestriction(android.content.ComponentName, java.lang.String);
+    method public void forwardMatchingIntents(android.content.ComponentName, android.content.IntentFilter, int);
     method public java.util.List<android.content.ComponentName> getActiveAdmins();
+    method public android.os.Bundle getApplicationRestrictions(android.content.ComponentName, java.lang.String);
     method public boolean getCameraDisabled(android.content.ComponentName);
     method public int getCurrentFailedPasswordAttempts();
     method public int getKeyguardDisabledFeatures(android.content.ComponentName);
@@ -4933,6 +5018,7 @@
     method public void lockNow();
     method public void removeActiveAdmin(android.content.ComponentName);
     method public boolean resetPassword(java.lang.String, int);
+    method public void setApplicationRestrictions(android.content.ComponentName, java.lang.String, android.os.Bundle);
     method public void setCameraDisabled(android.content.ComponentName, boolean);
     method public void setKeyguardDisabledFeatures(android.content.ComponentName, int);
     method public void setMaximumFailedPasswordsForWipe(android.content.ComponentName, int);
@@ -4947,6 +5033,7 @@
     method public void setPasswordMinimumSymbols(android.content.ComponentName, int);
     method public void setPasswordMinimumUpperCase(android.content.ComponentName, int);
     method public void setPasswordQuality(android.content.ComponentName, int);
+    method public void setProfileEnabled(android.content.ComponentName);
     method public int setStorageEncryption(android.content.ComponentName, boolean);
     method public void wipeData(int);
     field public static final java.lang.String ACTION_ADD_DEVICE_ADMIN = "android.app.action.ADD_DEVICE_ADMIN";
@@ -4961,9 +5048,14 @@
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
     field public static final java.lang.String EXTRA_PROVISIONING_DEFAULT_MANAGED_PROFILE_NAME = "defaultManagedProfileName";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "deviceAdminPackageName";
+    field public static int FLAG_TO_MANAGED_PROFILE;
+    field public static int FLAG_TO_PRIMARY_USER;
     field public static final int KEYGUARD_DISABLE_FEATURES_ALL = 2147483647; // 0x7fffffff
     field public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0; // 0x0
     field public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 2; // 0x2
+    field public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 4; // 0x4
+    field public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 16; // 0x10
+    field public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 8; // 0x8
     field public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1; // 0x1
     field public static final int PASSWORD_QUALITY_ALPHABETIC = 262144; // 0x40000
     field public static final int PASSWORD_QUALITY_ALPHANUMERIC = 327680; // 0x50000
@@ -6474,6 +6566,7 @@
     field public static final java.lang.String ALARM_SERVICE = "alarm";
     field public static final java.lang.String APP_OPS_SERVICE = "appops";
     field public static final java.lang.String AUDIO_SERVICE = "audio";
+    field public static final java.lang.String BATTERY_SERVICE = "batterymanager";
     field public static final int BIND_ABOVE_CLIENT = 8; // 0x8
     field public static final int BIND_ADJUST_WITH_ACTIVITY = 128; // 0x80
     field public static final int BIND_ALLOW_OOM_MANAGEMENT = 16; // 0x10
@@ -6827,6 +6920,7 @@
     field public static final java.lang.String ACTION_AIRPLANE_MODE_CHANGED = "android.intent.action.AIRPLANE_MODE";
     field public static final java.lang.String ACTION_ALL_APPS = "android.intent.action.ALL_APPS";
     field public static final java.lang.String ACTION_ANSWER = "android.intent.action.ANSWER";
+    field public static final java.lang.String ACTION_APPLICATION_RESTRICTIONS_CHANGED = "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED";
     field public static final java.lang.String ACTION_APP_ERROR = "android.intent.action.APP_ERROR";
     field public static final java.lang.String ACTION_ASSIST = "android.intent.action.ASSIST";
     field public static final java.lang.String ACTION_ATTACH_DATA = "android.intent.action.ATTACH_DATA";
@@ -6901,6 +6995,7 @@
     field public static final java.lang.String ACTION_PASTE = "android.intent.action.PASTE";
     field public static final java.lang.String ACTION_PICK = "android.intent.action.PICK";
     field public static final java.lang.String ACTION_PICK_ACTIVITY = "android.intent.action.PICK_ACTIVITY";
+    field public static final java.lang.String ACTION_PICK_DIRECTORY = "android.intent.action.PICK_DIRECTORY";
     field public static final java.lang.String ACTION_POWER_CONNECTED = "android.intent.action.ACTION_POWER_CONNECTED";
     field public static final java.lang.String ACTION_POWER_DISCONNECTED = "android.intent.action.ACTION_POWER_DISCONNECTED";
     field public static final java.lang.String ACTION_POWER_USAGE_SUMMARY = "android.intent.action.POWER_USAGE_SUMMARY";
@@ -6968,6 +7063,7 @@
     field public static final java.lang.String CATEGORY_TAB = "android.intent.category.TAB";
     field public static final java.lang.String CATEGORY_TEST = "android.intent.category.TEST";
     field public static final java.lang.String CATEGORY_UNIT_TEST = "android.intent.category.UNIT_TEST";
+    field public static final java.lang.String CATEGORY_VOICE = "android.intent.category.VOICE";
     field public static final android.os.Parcelable.Creator CREATOR;
     field public static final java.lang.String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
     field public static final java.lang.String EXTRA_ALLOW_MULTIPLE = "android.intent.extra.ALLOW_MULTIPLE";
@@ -7049,6 +7145,7 @@
     field public static final int FLAG_EXCLUDE_STOPPED_PACKAGES = 16; // 0x10
     field public static final int FLAG_FROM_BACKGROUND = 4; // 0x4
     field public static final int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 64; // 0x40
+    field public static final int FLAG_GRANT_PREFIX_URI_PERMISSION = 128; // 0x80
     field public static final int FLAG_GRANT_READ_URI_PERMISSION = 1; // 0x1
     field public static final int FLAG_GRANT_WRITE_URI_PERMISSION = 2; // 0x2
     field public static final int FLAG_INCLUDE_STOPPED_PACKAGES = 32; // 0x20
@@ -7731,12 +7828,15 @@
     method public long getFirstInstallTime();
     method public android.graphics.drawable.Drawable getIcon(int);
     method public java.lang.CharSequence getLabel();
+    method public java.lang.String getName();
     method public android.os.UserHandle getUser();
   }
 
   public class LauncherApps {
     method public synchronized 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 synchronized 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.graphics.Rect, android.os.Bundle, android.os.UserHandle);
@@ -7844,6 +7944,7 @@
     method public abstract java.lang.String getInstallerPackageName(java.lang.String);
     method public abstract android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public abstract android.content.Intent getLaunchIntentForPackage(java.lang.String);
+    method public abstract android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public abstract java.lang.String getNameForUid(int);
     method public android.content.pm.PackageInfo getPackageArchiveInfo(java.lang.String, int);
     method public abstract int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -9702,8 +9803,8 @@
     method public void drawBitmap(android.graphics.Bitmap, float, float, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.RectF, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Rect, android.graphics.Rect, android.graphics.Paint);
-    method public void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
-    method public void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
+    method public deprecated void drawBitmap(int[], int, int, float, float, int, int, boolean, android.graphics.Paint);
+    method public deprecated void drawBitmap(int[], int, int, int, int, int, int, boolean, android.graphics.Paint);
     method public void drawBitmap(android.graphics.Bitmap, android.graphics.Matrix, android.graphics.Paint);
     method public void drawBitmapMesh(android.graphics.Bitmap, int, int, float[], int, int[], int, android.graphics.Paint);
     method public void drawCircle(float, float, float, android.graphics.Paint);
@@ -9728,6 +9829,7 @@
     method public void drawRect(android.graphics.Rect, android.graphics.Paint);
     method public void drawRect(float, float, float, float, android.graphics.Paint);
     method public void drawRoundRect(android.graphics.RectF, float, float, android.graphics.Paint);
+    method public void drawRoundRect(float, float, float, float, float, float, android.graphics.Paint);
     method public void drawText(char[], int, int, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, float, float, android.graphics.Paint);
     method public void drawText(java.lang.String, int, int, float, float, android.graphics.Paint);
@@ -9758,9 +9860,13 @@
     method public int save();
     method public int save(int);
     method public int saveLayer(android.graphics.RectF, android.graphics.Paint, int);
+    method public int saveLayer(android.graphics.RectF, android.graphics.Paint);
     method public int saveLayer(float, float, float, float, android.graphics.Paint, int);
+    method public int saveLayer(float, float, float, float, android.graphics.Paint);
     method public int saveLayerAlpha(android.graphics.RectF, int, int);
+    method public int saveLayerAlpha(android.graphics.RectF, int);
     method public int saveLayerAlpha(float, float, float, float, int, int);
+    method public int saveLayerAlpha(float, float, float, float, int);
     method public void scale(float, float);
     method public final void scale(float, float, float, float);
     method public void setBitmap(android.graphics.Bitmap);
@@ -10036,11 +10142,18 @@
     method public void setPaint(android.graphics.Paint);
   }
 
-  public class Outline {
+  public final class Outline {
     ctor public Outline();
-    method public final boolean isValid();
+    ctor public Outline(android.graphics.Outline);
+    method public boolean isValid();
     method public void set(android.graphics.Outline);
+    method public void setConvexPath(android.graphics.Path);
+    method public void setOval(int, int, int, int);
+    method public void setOval(android.graphics.Rect);
+    method public void setRect(int, int, int, int);
+    method public void setRect(android.graphics.Rect);
     method public void setRoundRect(int, int, int, int, float);
+    method public void setRoundRect(android.graphics.Rect, float);
   }
 
   public class Paint {
@@ -10090,6 +10203,7 @@
     method public android.graphics.Xfermode getXfermode();
     method public final boolean isAntiAlias();
     method public final boolean isDither();
+    method public boolean isElegantTextHeight();
     method public final boolean isFakeBoldText();
     method public final boolean isFilterBitmap();
     method public final boolean isLinearText();
@@ -10108,6 +10222,7 @@
     method public void setColor(int);
     method public android.graphics.ColorFilter setColorFilter(android.graphics.ColorFilter);
     method public void setDither(boolean);
+    method public void setElegantTextHeight(boolean);
     method public void setFakeBoldText(boolean);
     method public void setFilterBitmap(boolean);
     method public void setFlags(int);
@@ -10207,6 +10322,7 @@
     method public void addArc(android.graphics.RectF, float, float);
     method public void addCircle(float, float, float, android.graphics.Path.Direction);
     method public void addOval(android.graphics.RectF, android.graphics.Path.Direction);
+    method public void addOval(float, float, float, float, android.graphics.Path.Direction);
     method public void addPath(android.graphics.Path, float, float);
     method public void addPath(android.graphics.Path);
     method public void addPath(android.graphics.Path, android.graphics.Matrix);
@@ -10761,7 +10877,7 @@
     method public int getMinimumHeight();
     method public int getMinimumWidth();
     method public abstract int getOpacity();
-    method public android.graphics.Outline getOutline();
+    method public boolean getOutline(android.graphics.Outline);
     method public boolean getPadding(android.graphics.Rect);
     method public int[] getState();
     method public android.graphics.Region getTransparentRegion();
@@ -11094,8 +11210,6 @@
     method public void setAnimationFraction(float);
     method public void setColorFilter(android.graphics.ColorFilter);
     method public void setDuration(long);
-    method public void setIntrinsicHeight(int);
-    method public void setIntrinsicWidth(int);
     method public void setPadding(android.graphics.Rect);
     method public void setPadding(int, int, int, int);
     method public void setRepeatCount(int);
@@ -11136,6 +11250,7 @@
     method public android.graphics.drawable.shapes.Shape clone() throws java.lang.CloneNotSupportedException;
     method public abstract void draw(android.graphics.Canvas, android.graphics.Paint);
     method public final float getHeight();
+    method public boolean getOutline(android.graphics.Outline);
     method public final float getWidth();
     method public boolean hasAlpha();
     method protected void onResize(float, float);
@@ -11459,10 +11574,33 @@
     method public int getMinDelay();
     method public java.lang.String getName();
     method public float getPower();
+    method public java.lang.String getRequiredPermission();
     method public float getResolution();
+    method public java.lang.String getStringType();
     method public int getType();
     method public java.lang.String getVendor();
     method public int getVersion();
+    field public static final java.lang.String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
+    field public static final java.lang.String STRING_TYPE_AMBIENT_TEMPERATURE = "android.sensor.ambient_temperature";
+    field public static final java.lang.String STRING_TYPE_GAME_ROTATION_VECTOR = "android.sensor.game_rotation_vector";
+    field public static final java.lang.String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR = "android.sensor.geomagnetic_rotation_vector";
+    field public static final java.lang.String STRING_TYPE_GRAVITY = "android.sensor.gravity";
+    field public static final java.lang.String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
+    field public static final java.lang.String STRING_TYPE_GYROSCOPE_UNCALIBRATED = "android.sensor.gyroscope_uncalibrated";
+    field public static final java.lang.String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
+    field public static final java.lang.String STRING_TYPE_LIGHT = "android.sensor.light";
+    field public static final java.lang.String STRING_TYPE_LINEAR_ACCELERATION = "android.sensor.linear_acceleration";
+    field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
+    field public static final java.lang.String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED = "android.sensor.magnetic_field_uncalibrated";
+    field public static final deprecated java.lang.String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
+    field public static final java.lang.String STRING_TYPE_PRESSURE = "android.sensor.pressure";
+    field public static final java.lang.String STRING_TYPE_PROXIMITY = "android.sensor.proximity";
+    field public static final java.lang.String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
+    field public static final java.lang.String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
+    field public static final java.lang.String STRING_TYPE_SIGNIFICANT_MOTION = "android.sensor.significant_motion";
+    field public static final java.lang.String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
+    field public static final java.lang.String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
+    field public static final deprecated java.lang.String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
     field public static final int TYPE_ACCELEROMETER = 1; // 0x1
     field public static final int TYPE_ALL = -1; // 0xffffffff
     field public static final int TYPE_AMBIENT_TEMPERATURE = 13; // 0xd
@@ -11471,6 +11609,7 @@
     field public static final int TYPE_GRAVITY = 9; // 0x9
     field public static final int TYPE_GYROSCOPE = 4; // 0x4
     field public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16; // 0x10
+    field public static final int TYPE_HEART_RATE = 21; // 0x15
     field public static final int TYPE_LIGHT = 5; // 0x5
     field public static final int TYPE_LINEAR_ACCELERATION = 10; // 0xa
     field public static final int TYPE_MAGNETIC_FIELD = 2; // 0x2
@@ -11665,6 +11804,12 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_AVAILABLE_TEST_PATTERN_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BASE_GAIN_FACTOR;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_BLACK_LEVEL_PATTERN;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_CALIBRATION_TRANSFORM1;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_CALIBRATION_TRANSFORM2;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_COLOR_TRANSFORM1;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_COLOR_TRANSFORM2;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX1;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX2;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_ACTIVE_ARRAY_SIZE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_COLOR_FILTER_ARRANGEMENT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_INFO_EXPOSURE_TIME_RANGE;
@@ -11676,6 +11821,8 @@
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_MAX_ANALOG_SENSITIVITY;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_ORIENTATION;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_HUE_SAT_MAP_DIMENSIONS;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT1;
+    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT2;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_AVAILABLE_HOT_PIXEL_MAP_MODES;
     field public static final android.hardware.camera2.CameraMetadata.Key STATISTICS_INFO_MAX_FACE_COUNT;
@@ -11795,6 +11942,7 @@
     field public static final int CONTROL_AWB_STATE_LOCKED = 3; // 0x3
     field public static final int CONTROL_AWB_STATE_SEARCHING = 1; // 0x1
     field public static final int CONTROL_CAPTURE_INTENT_CUSTOM = 0; // 0x0
+    field public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6; // 0x6
     field public static final int CONTROL_CAPTURE_INTENT_PREVIEW = 1; // 0x1
     field public static final int CONTROL_CAPTURE_INTENT_STILL_CAPTURE = 2; // 0x2
     field public static final int CONTROL_CAPTURE_INTENT_VIDEO_RECORD = 3; // 0x3
@@ -11868,25 +12016,25 @@
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_GRBG = 1; // 0x1
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4; // 0x4
     field public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGGB = 0; // 0x0
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER = 10; // 0xa
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14; // 0xe
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_D50 = 23; // 0x17
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_D55 = 20; // 0x14
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_D65 = 21; // 0x15
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_D75 = 22; // 0x16
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT = 1; // 0x1
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12; // 0xc
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13; // 0xd
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER = 9; // 0x9
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_FLASH = 4; // 0x4
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT = 2; // 0x2
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24; // 0x18
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_SHADE = 11; // 0xb
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_A = 17; // 0x11
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_B = 18; // 0x12
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_C = 19; // 0x13
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN = 3; // 0x3
-    field public static final int SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT = 15; // 0xf
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10; // 0xa
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14; // 0xe
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_D50 = 23; // 0x17
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_D55 = 20; // 0x14
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_D65 = 21; // 0x15
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_D75 = 22; // 0x16
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1; // 0x1
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12; // 0xc
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13; // 0xd
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9; // 0x9
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4; // 0x4
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2; // 0x2
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24; // 0x18
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11; // 0xb
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17; // 0x11
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18; // 0x12
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19; // 0x13
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3; // 0x3
+    field public static final int SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15; // 0xf
     field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS = 2; // 0x2
     field public static final int SENSOR_TEST_PATTERN_MODE_COLOR_BARS_FADE_TO_GRAY = 3; // 0x3
     field public static final int SENSOR_TEST_PATTERN_MODE_CUSTOM1 = 256; // 0x100
@@ -12036,16 +12184,12 @@
     field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_FRAME_COUNT;
     field public static final android.hardware.camera2.CameraMetadata.Key REQUEST_PIPELINE_DEPTH;
     field public static final android.hardware.camera2.CameraMetadata.Key SCALER_CROP_REGION;
-    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_CALIBRATION_TRANSFORM;
-    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_COLOR_TRANSFORM;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_EXPOSURE_TIME;
-    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FORWARD_MATRIX;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_FRAME_DURATION;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_GREEN_SPLIT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_NEUTRAL_COLOR_POINT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_HUE_SAT_MAP;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_PROFILE_TONE_CURVE;
-    field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_REFERENCE_ILLUMINANT;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_SENSITIVITY;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEMPERATURE;
     field public static final android.hardware.camera2.CameraMetadata.Key SENSOR_TEST_PATTERN_MODE;
@@ -12113,7 +12257,9 @@
 
   public final class VirtualDisplay {
     method public android.view.Display getDisplay();
+    method public android.view.Surface getSurface();
     method public void release();
+    method public void setSurface(android.view.Surface);
   }
 
 }
@@ -12222,6 +12368,7 @@
   public final class HdmiCecClient {
     method public boolean isTvOn();
     method public void sendActiveSource();
+    method public void sendGiveDevicePowerStatus(int);
     method public void sendImageViewOn();
     method public void sendInactiveSource();
     method public void sendTextViewOn();
@@ -13358,6 +13505,18 @@
     ctor public DeniedByServerException(java.lang.String);
   }
 
+  public final class DngCreator {
+    ctor public DngCreator(android.hardware.camera2.CameraCharacteristics, android.hardware.camera2.CaptureResult);
+    method public android.media.DngCreator setDescription(java.lang.String);
+    method public android.media.DngCreator setLocation(android.location.Location);
+    method public android.media.DngCreator setOrientation(int);
+    method public android.media.DngCreator setThumbnail(android.graphics.Bitmap);
+    method public android.media.DngCreator setThumbnail(android.media.Image);
+    method public void writeByteBuffer(java.io.OutputStream, java.nio.ByteBuffer, int, long) throws java.io.IOException;
+    method public void writeImage(java.io.OutputStream, android.media.Image) throws java.io.IOException;
+    method public void writeInputStream(java.io.OutputStream, java.io.InputStream, int, long) throws java.io.IOException;
+  }
+
   public class ExifInterface {
     ctor public ExifInterface(java.lang.String) throws java.io.IOException;
     method public double getAltitude(double);
@@ -14950,25 +15109,70 @@
 
 }
 
+package android.media.routeprovider {
+
+  public final class RouteConnection {
+    ctor public RouteConnection(android.media.routeprovider.RouteProviderService, android.media.session.RouteInfo);
+    method public android.media.routeprovider.RouteInterfaceHandler addRouteInterface(java.lang.String);
+    method public android.media.routeprovider.RouteInterfaceHandler getRouteInterface(java.lang.String);
+    method public void shutDown();
+  }
+
+  public final class RouteInterfaceHandler {
+    method public void addListener(android.media.routeprovider.RouteInterfaceHandler.CommandListener, android.os.Handler);
+    method public java.lang.String getName();
+    method public void removeListener(android.media.routeprovider.RouteInterfaceHandler.CommandListener);
+    method public void sendEvent(java.lang.String, android.os.Bundle);
+    method public static void sendResult(android.os.ResultReceiver, int, android.os.Bundle);
+  }
+
+  public static abstract class RouteInterfaceHandler.CommandListener {
+    ctor public RouteInterfaceHandler.CommandListener();
+    method public abstract boolean onCommand(android.media.routeprovider.RouteInterfaceHandler, java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+  }
+
+  public final class RoutePlaybackControlsHandler {
+    method public void addListener(android.media.routeprovider.RoutePlaybackControlsHandler.Listener);
+    method public void addListener(android.media.routeprovider.RoutePlaybackControlsHandler.Listener, android.os.Handler);
+    method public static android.media.routeprovider.RoutePlaybackControlsHandler addTo(android.media.routeprovider.RouteConnection);
+    method public void removeListener(android.media.routeprovider.RoutePlaybackControlsHandler.Listener);
+    method public void sendPlaybackChangeEvent(int);
+  }
+
+  public static abstract class RoutePlaybackControlsHandler.Listener extends android.media.routeprovider.RouteInterfaceHandler.CommandListener {
+    ctor public RoutePlaybackControlsHandler.Listener();
+    method public boolean fastForward();
+    method public long getCapabilities();
+    method public long getCurrentPosition();
+    method public final boolean onCommand(android.media.routeprovider.RouteInterfaceHandler, java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+    method public boolean pause();
+    method public void playNow(java.lang.String, android.os.ResultReceiver);
+    method public boolean resume();
+  }
+
+  public abstract class RouteProviderService extends android.app.Service {
+    ctor public RouteProviderService();
+    method public abstract android.media.routeprovider.RouteConnection connect(android.media.session.RouteInfo, android.media.routeprovider.RouteRequest);
+    method public abstract java.util.List<android.media.session.RouteInfo> getMatchingRoutes(java.util.List<android.media.routeprovider.RouteRequest>);
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public void updateDiscoveryRequests(java.util.List<android.media.routeprovider.RouteRequest>);
+    field public static final java.lang.String SERVICE_INTERFACE = "com.android.media.session.MediaRouteProvider";
+  }
+
+  public final class RouteRequest implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.media.session.RouteOptions getConnectionOptions();
+    method public android.media.session.SessionInfo getSessionInfo();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+}
+
 package android.media.session {
 
-  public final class MediaController {
-    method public void addCallback(android.media.session.MediaController.Callback);
-    method public void addCallback(android.media.session.MediaController.Callback, android.os.Handler);
-    method public static android.media.session.MediaController fromToken(android.media.session.MediaSessionToken);
-    method public android.media.session.TransportController getTransportController();
-    method public void removeCallback(android.media.session.MediaController.Callback);
-    method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
-    method public void sendMediaButton(int);
-  }
-
-  public static abstract class MediaController.Callback {
-    ctor public MediaController.Callback();
-    method public void onEvent(java.lang.String, android.os.Bundle);
-    method public void onRouteChanged(android.os.Bundle);
-  }
-
   public final class MediaMetadata implements android.os.Parcelable {
+    method public boolean containsKey(java.lang.String);
     method public int describeContents();
     method public android.graphics.Bitmap getBitmap(java.lang.String);
     method public long getLong(java.lang.String);
@@ -14984,6 +15188,7 @@
     field public static final java.lang.String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
     field public static final java.lang.String METADATA_KEY_ART_URI = "android.media.metadata.ART_URI";
     field public static final java.lang.String METADATA_KEY_AUTHOR = "android.media.metadata.AUTHOR";
+    field public static final java.lang.String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
     field public static final java.lang.String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
     field public static final java.lang.String METADATA_KEY_DATE = "android.media.metadata.DATE";
     field public static final java.lang.String METADATA_KEY_DISC_NUMBER = "android.media.metadata.DISC_NUMBER";
@@ -15008,36 +15213,6 @@
     method public android.media.session.MediaMetadata.Builder putString(java.lang.String, java.lang.String);
   }
 
-  public final class MediaSession {
-    method public void addCallback(android.media.session.MediaSession.Callback);
-    method public void addCallback(android.media.session.MediaSession.Callback, android.os.Handler);
-    method public android.media.session.MediaSessionToken getSessionToken();
-    method public android.media.session.TransportPerformer getTransportPerformer();
-    method public void publish();
-    method public void release();
-    method public void removeCallback(android.media.session.MediaSession.Callback);
-    method public void sendEvent(java.lang.String, android.os.Bundle);
-    method public android.media.session.TransportPerformer setTransportPerformerEnabled();
-  }
-
-  public static abstract class MediaSession.Callback {
-    ctor public MediaSession.Callback();
-    method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
-    method public void onMediaButton(android.content.Intent);
-    method public void onRequestRouteChange(android.os.Bundle);
-  }
-
-  public final class MediaSessionManager {
-    method public android.media.session.MediaSession createSession(java.lang.String);
-    method public java.util.List<android.media.session.MediaController> getActiveSessions();
-  }
-
-  public class MediaSessionToken implements android.os.Parcelable {
-    method public int describeContents();
-    method public void writeToParcel(android.os.Parcel, int);
-    field public static final android.os.Parcelable.Creator CREATOR;
-  }
-
   public final class PlaybackState implements android.os.Parcelable {
     ctor public PlaybackState();
     ctor public PlaybackState(android.media.session.PlaybackState);
@@ -15046,40 +15221,76 @@
     method public long getBufferPosition();
     method public java.lang.String getErrorMessage();
     method public long getPosition();
-    method public float getSpeed();
+    method public float getRate();
     method public int getState();
     method public void setActions(long);
     method public void setBufferPosition(long);
     method public void setErrorMessage(java.lang.String);
-    method public void setPosition(long);
-    method public void setSpeed(float);
-    method public void setState(int);
+    method public void setState(int, long, float);
     method public void writeToParcel(android.os.Parcel, int);
     field public static final long ACTION_FASTFORWARD = 64L; // 0x40L
     field public static final long ACTION_NEXT_ITEM = 32L; // 0x20L
     field public static final long ACTION_PAUSE = 2L; // 0x2L
     field public static final long ACTION_PLAY = 4L; // 0x4L
+    field public static final long ACTION_PLAY_PAUSE = 512L; // 0x200L
     field public static final long ACTION_PREVIOUS_ITEM = 16L; // 0x10L
     field public static final long ACTION_RATING = 128L; // 0x80L
     field public static final long ACTION_REWIND = 8L; // 0x8L
     field public static final long ACTION_SEEK_TO = 256L; // 0x100L
     field public static final long ACTION_STOP = 1L; // 0x1L
     field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final long PLAYBACK_POSITION_UNKNOWN = -1L; // 0xffffffffffffffffL
     field public static final int PLAYSTATE_BUFFERING = 6; // 0x6
+    field public static final int PLAYSTATE_CONNECTING = 8; // 0x8
     field public static final int PLAYSTATE_ERROR = 7; // 0x7
     field public static final int PLAYSTATE_FAST_FORWARDING = 4; // 0x4
     field public static final int PLAYSTATE_NONE = 0; // 0x0
     field public static final int PLAYSTATE_PAUSED = 2; // 0x2
     field public static final int PLAYSTATE_PLAYING = 3; // 0x3
     field public static final int PLAYSTATE_REWINDING = 5; // 0x5
+    field public static final int PLAYSTATE_SKIPPING_BACKWARDS = 9; // 0x9
+    field public static final int PLAYSTATE_SKIPPING_FORWARDS = 10; // 0xa
     field public static final int PLAYSTATE_STOPPED = 1; // 0x1
   }
 
+  public final class Route {
+    method public android.media.session.RouteInterface getInterface(java.lang.String);
+    method public android.media.session.RouteOptions getOptions();
+    method public android.media.session.RouteInfo getRouteInfo();
+  }
+
+  public final class RouteInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.util.List<android.media.session.RouteOptions> getConnectionMethods();
+    method public java.lang.String getId();
+    method public java.lang.String getName();
+    method public java.lang.String getProvider();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public static final class RouteInfo.Builder {
+    ctor public RouteInfo.Builder(android.media.session.RouteInfo);
+    ctor public RouteInfo.Builder();
+    method public android.media.session.RouteInfo.Builder addRouteOptions(android.media.session.RouteOptions);
+    method public android.media.session.RouteInfo build();
+    method public android.media.session.RouteInfo.Builder clearRouteOptions();
+    method public int getOptionsSize();
+    method public android.media.session.RouteInfo.Builder setId(java.lang.String);
+    method public android.media.session.RouteInfo.Builder setName(java.lang.String);
+  }
+
   public final class RouteInterface {
     method public void addListener(android.media.session.RouteInterface.EventListener);
     method public void addListener(android.media.session.RouteInterface.EventListener, android.os.Handler);
     method public void removeListener(android.media.session.RouteInterface.EventListener);
-    method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+    method public boolean sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+    field public static final int RESULT_COMMAND_NOT_SUPPORTED = -3; // 0xfffffffd
+    field public static final int RESULT_ERROR = -1; // 0xffffffff
+    field public static final int RESULT_INTERFACE_NOT_SUPPORTED = -2; // 0xfffffffe
+    field public static final int RESULT_NOT_CONNECTED = -5; // 0xfffffffb
+    field public static final int RESULT_ROUTE_IS_STALE = -4; // 0xfffffffc
+    field public static final int RESULT_SUCCESS = 1; // 0x1
   }
 
   public static abstract class RouteInterface.EventListener {
@@ -15087,40 +15298,100 @@
     method public abstract void onEvent(java.lang.String, android.os.Bundle);
   }
 
-  public static abstract class RouteInterface.Stub {
-    ctor public RouteInterface.Stub();
-    method public abstract java.lang.String getName();
-    method public abstract void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
-    method public final void sendEvent(android.media.session.MediaSession, java.lang.String, android.os.Bundle);
+  public final class RouteOptions implements android.os.Parcelable {
+    method public int describeContents();
+    method public android.os.Bundle getConnectionParams();
+    method public java.util.List<java.lang.String> getInterfaceNames();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
-  public final class RouteTransportControls {
-    method public void addListener(android.media.session.RouteTransportControls.Listener);
-    method public void addListener(android.media.session.RouteTransportControls.Listener, android.os.Handler);
-    method public void fastForward(float);
-    method public static android.media.session.RouteTransportControls from(android.media.session.MediaController);
+  public static final class RouteOptions.Builder {
+    ctor public RouteOptions.Builder();
+    method public android.media.session.RouteOptions.Builder addInterface(java.lang.String);
+    method public android.media.session.RouteOptions build();
+    method public android.media.session.RouteOptions.Builder setParameters(android.os.Bundle);
+  }
+
+  public final class RoutePlaybackControls {
+    method public void addListener(android.media.session.RoutePlaybackControls.Listener);
+    method public void addListener(android.media.session.RoutePlaybackControls.Listener, android.os.Handler);
+    method public void fastForward();
+    method public static android.media.session.RoutePlaybackControls from(android.media.session.Route);
     method public void getCapabilities(android.os.ResultReceiver);
     method public void getCurrentPosition(android.os.ResultReceiver);
     method public void pause();
-    method public void play();
-    method public void removeListener(android.media.session.RouteTransportControls.Listener);
-    field public static final java.lang.String NAME = "android.media.session.RouteTransportControls";
+    method public void playNow(java.lang.String);
+    method public void removeListener(android.media.session.RoutePlaybackControls.Listener);
+    method public void resume();
+    field public static final java.lang.String NAME = "android.media.session.RoutePlaybackControls";
   }
 
-  public static abstract class RouteTransportControls.Listener {
-    ctor public RouteTransportControls.Listener();
-    method public void onMetadataUpdate(android.os.Bundle);
+  public static abstract class RoutePlaybackControls.Listener extends android.media.session.RouteInterface.EventListener {
+    ctor public RoutePlaybackControls.Listener();
+    method public final void onEvent(java.lang.String, android.os.Bundle);
+    method public void onMetadataUpdate(android.media.session.MediaMetadata);
     method public void onPlaybackStateChange(int);
   }
 
-  public static abstract class RouteTransportControls.Stub extends android.media.session.RouteInterface.Stub {
-    ctor public RouteTransportControls.Stub(android.media.session.MediaSession);
-    method public void fastForward(float);
-    method public long getCapabilities();
-    method public long getCurrentPosition();
-    method public java.lang.String getName();
+  public final class Session {
+    method public void addCallback(android.media.session.Session.Callback);
+    method public void addCallback(android.media.session.Session.Callback, android.os.Handler);
+    method public void connect(android.media.session.RouteInfo, android.media.session.RouteOptions);
+    method public void disconnect(android.media.session.RouteInfo);
+    method public android.media.session.SessionToken getSessionToken();
+    method public android.media.session.TransportPerformer getTransportPerformer();
+    method public void publish();
+    method public void release();
+    method public void removeCallback(android.media.session.Session.Callback);
+    method public void sendEvent(java.lang.String, android.os.Bundle);
+    method public void setRouteOptions(java.util.List<android.media.session.RouteOptions>);
+    method public android.media.session.TransportPerformer setTransportPerformerEnabled();
+  }
+
+  public static abstract class Session.Callback {
+    ctor public Session.Callback();
     method public void onCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
-    method public final void updatePlaybackState(int);
+    method public void onMediaButton(android.content.Intent);
+    method public void onRequestRouteChange(android.media.session.RouteInfo);
+    method public void onRouteConnected(android.media.session.Route);
+    method public void onRouteDisconnected(android.media.session.Route, int);
+  }
+
+  public final class SessionController {
+    method public void addCallback(android.media.session.SessionController.Callback);
+    method public void addCallback(android.media.session.SessionController.Callback, android.os.Handler);
+    method public static android.media.session.SessionController fromToken(android.media.session.SessionToken);
+    method public android.media.session.TransportController getTransportController();
+    method public void removeCallback(android.media.session.SessionController.Callback);
+    method public void sendCommand(java.lang.String, android.os.Bundle, android.os.ResultReceiver);
+    method public void sendMediaButton(int);
+    method public void showRoutePicker();
+  }
+
+  public static abstract class SessionController.Callback {
+    ctor public SessionController.Callback();
+    method public void onEvent(java.lang.String, android.os.Bundle);
+    method public void onRouteChanged(android.media.session.RouteInfo);
+  }
+
+  public final class SessionInfo implements android.os.Parcelable {
+    method public int describeContents();
+    method public java.lang.String getId();
+    method public java.lang.String getPackageName();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class SessionManager {
+    method public android.media.session.Session createSession(java.lang.String);
+    method public java.util.List<android.media.session.SessionController> getActiveSessions();
+  }
+
+  public class SessionToken implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
   }
 
   public final class TransportController {
@@ -15842,10 +16113,13 @@
   public final class NsdServiceInfo implements android.os.Parcelable {
     ctor public NsdServiceInfo();
     method public int describeContents();
+    method public java.util.Map<java.lang.String, byte[]> getAttributes();
     method public java.net.InetAddress getHost();
     method public int getPort();
     method public java.lang.String getServiceName();
     method public java.lang.String getServiceType();
+    method public void removeAttribute(java.lang.String);
+    method public void setAttribute(java.lang.String, java.lang.String);
     method public void setHost(java.net.InetAddress);
     method public void setPort(int);
     method public void setServiceName(java.lang.String);
@@ -16686,11 +16960,24 @@
 
 package android.nfc.cardemulation {
 
+  public final class AidGroup implements android.os.Parcelable {
+    ctor public AidGroup(java.util.ArrayList<java.lang.String>, java.lang.String);
+    method public int describeContents();
+    method public java.util.ArrayList<java.lang.String> getAids();
+    method public java.lang.String getCategory();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int MAX_NUM_AIDS = 256; // 0x100
+  }
+
   public final class CardEmulation {
+    method public android.nfc.cardemulation.AidGroup getAidGroupForService(android.content.ComponentName, java.lang.String);
     method public static synchronized android.nfc.cardemulation.CardEmulation getInstance(android.nfc.NfcAdapter);
     method public int getSelectionModeForCategory(java.lang.String);
     method public boolean isDefaultServiceForAid(android.content.ComponentName, java.lang.String);
     method public boolean isDefaultServiceForCategory(android.content.ComponentName, java.lang.String);
+    method public boolean registerAidGroupForService(android.content.ComponentName, android.nfc.cardemulation.AidGroup);
+    method public boolean removeAidGroupForService(android.content.ComponentName, java.lang.String);
     field public static final java.lang.String ACTION_CHANGE_DEFAULT = "android.nfc.cardemulation.action.ACTION_CHANGE_DEFAULT";
     field public static final java.lang.String CATEGORY_OTHER = "other";
     field public static final java.lang.String CATEGORY_PAYMENT = "payment";
@@ -19005,6 +19292,7 @@
 
   public class BatteryManager {
     ctor public BatteryManager();
+    method public android.os.BatteryProperty getProperty(int) throws android.os.RemoteException;
     field public static final int BATTERY_HEALTH_COLD = 7; // 0x7
     field public static final int BATTERY_HEALTH_DEAD = 4; // 0x4
     field public static final int BATTERY_HEALTH_GOOD = 2; // 0x2
@@ -19032,6 +19320,18 @@
     field public static final java.lang.String EXTRA_VOLTAGE = "voltage";
   }
 
+  public class BatteryProperty implements android.os.Parcelable {
+    method public int describeContents();
+    method public int getInt();
+    method public void readFromParcel(android.os.Parcel);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final int CAPACITY = 4; // 0x4
+    field public static final int CHARGE_COUNTER = 1; // 0x1
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final int CURRENT_AVERAGE = 3; // 0x3
+    field public static final int CURRENT_NOW = 2; // 0x2
+  }
+
   public class Binder implements android.os.IBinder {
     ctor public Binder();
     method public void attachInterface(android.os.IInterface, java.lang.String);
@@ -19112,14 +19412,16 @@
     field public static final int JELLY_BEAN_MR1 = 17; // 0x11
     field public static final int JELLY_BEAN_MR2 = 18; // 0x12
     field public static final int KITKAT = 19; // 0x13
+    field public static final int KITKAT_WATCH = 10000; // 0x2710
     field public static final int L = 10000; // 0x2710
   }
 
-  public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
+  public final class Bundle extends android.os.CommonBundle {
     ctor public Bundle();
     ctor public Bundle(java.lang.ClassLoader);
     ctor public Bundle(int);
     ctor public Bundle(android.os.Bundle);
+    ctor public Bundle(android.os.PersistableBundle);
     method public void clear();
     method public java.lang.Object clone();
     method public boolean containsKey(java.lang.String);
@@ -19157,6 +19459,7 @@
     method public T getParcelable(java.lang.String);
     method public android.os.Parcelable[] getParcelableArray(java.lang.String);
     method public java.util.ArrayList<T> getParcelableArrayList(java.lang.String);
+    method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
     method public java.io.Serializable getSerializable(java.lang.String);
     method public short getShort(java.lang.String);
     method public short getShort(java.lang.String, short);
@@ -19170,6 +19473,7 @@
     method public boolean isEmpty();
     method public java.util.Set<java.lang.String> keySet();
     method public void putAll(android.os.Bundle);
+    method public void putAll(android.os.PersistableBundle);
     method public void putBinder(java.lang.String, android.os.IBinder);
     method public void putBoolean(java.lang.String, boolean);
     method public void putBooleanArray(java.lang.String, boolean[]);
@@ -19193,6 +19497,7 @@
     method public void putParcelable(java.lang.String, android.os.Parcelable);
     method public void putParcelableArray(java.lang.String, android.os.Parcelable[]);
     method public void putParcelableArrayList(java.lang.String, java.util.ArrayList<? extends android.os.Parcelable>);
+    method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
     method public void putSerializable(java.lang.String, java.io.Serializable);
     method public void putShort(java.lang.String, short);
     method public void putShortArray(java.lang.String, short[]);
@@ -19221,6 +19526,9 @@
     method public abstract void onCancel();
   }
 
+   abstract class CommonBundle implements java.lang.Cloneable android.os.Parcelable {
+  }
+
   public class ConditionVariable {
     ctor public ConditionVariable();
     ctor public ConditionVariable(boolean);
@@ -19647,6 +19955,8 @@
     method public final void readMap(java.util.Map, java.lang.ClassLoader);
     method public final T readParcelable(java.lang.ClassLoader);
     method public final android.os.Parcelable[] readParcelableArray(java.lang.ClassLoader);
+    method public final android.os.PersistableBundle readPersistableBundle();
+    method public final android.os.PersistableBundle readPersistableBundle(java.lang.ClassLoader);
     method public final java.io.Serializable readSerializable();
     method public final android.util.SparseArray readSparseArray(java.lang.ClassLoader);
     method public final android.util.SparseBooleanArray readSparseBooleanArray();
@@ -19687,6 +19997,7 @@
     method public final void writeNoException();
     method public final void writeParcelable(android.os.Parcelable, int);
     method public final void writeParcelableArray(T[], int);
+    method public final void writePersistableBundle(android.os.PersistableBundle);
     method public final void writeSerializable(java.io.Serializable);
     method public final void writeSparseArray(android.util.SparseArray<java.lang.Object>);
     method public final void writeSparseBooleanArray(android.util.SparseBooleanArray);
@@ -19797,9 +20108,55 @@
     field public static final int PATTERN_SIMPLE_GLOB = 2; // 0x2
   }
 
+  public final class PersistableBundle extends android.os.CommonBundle {
+    ctor public PersistableBundle();
+    ctor public PersistableBundle(java.lang.ClassLoader);
+    ctor public PersistableBundle(int);
+    ctor public PersistableBundle(android.os.PersistableBundle);
+    method public void clear();
+    method public java.lang.Object clone();
+    method public boolean containsKey(java.lang.String);
+    method public int describeContents();
+    method public java.lang.Object get(java.lang.String);
+    method public java.lang.ClassLoader getClassLoader();
+    method public double getDouble(java.lang.String);
+    method public double getDouble(java.lang.String, double);
+    method public double[] getDoubleArray(java.lang.String);
+    method public int getInt(java.lang.String);
+    method public int getInt(java.lang.String, int);
+    method public int[] getIntArray(java.lang.String);
+    method public long getLong(java.lang.String);
+    method public long getLong(java.lang.String, long);
+    method public long[] getLongArray(java.lang.String);
+    method public android.os.PersistableBundle getPersistableBundle(java.lang.String);
+    method public java.lang.String getString(java.lang.String);
+    method public java.lang.String getString(java.lang.String, java.lang.String);
+    method public java.lang.String[] getStringArray(java.lang.String);
+    method public boolean isEmpty();
+    method public java.util.Set<java.lang.String> keySet();
+    method public void putAll(android.os.PersistableBundle);
+    method public void putDouble(java.lang.String, double);
+    method public void putDoubleArray(java.lang.String, double[]);
+    method public void putInt(java.lang.String, int);
+    method public void putIntArray(java.lang.String, int[]);
+    method public void putLong(java.lang.String, long);
+    method public void putLongArray(java.lang.String, long[]);
+    method public void putPersistableBundle(java.lang.String, android.os.PersistableBundle);
+    method public void putString(java.lang.String, java.lang.String);
+    method public void putStringArray(java.lang.String, java.lang.String[]);
+    method public void readFromParcel(android.os.Parcel);
+    method public void remove(java.lang.String);
+    method public void setClassLoader(java.lang.ClassLoader);
+    method public int size();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+    field public static final android.os.PersistableBundle EMPTY;
+  }
+
   public final class PowerManager {
     method public void goToSleep(long);
-    method public boolean isScreenOn();
+    method public boolean isInteractive();
+    method public deprecated boolean isScreenOn();
     method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
     method public void reboot(java.lang.String);
     method public void userActivity(long, boolean);
@@ -20011,6 +20368,7 @@
 
   public class UserManager {
     method public android.os.Bundle getApplicationRestrictions(java.lang.String);
+    method public android.graphics.drawable.Drawable getBadgedDrawableForUser(android.graphics.drawable.Drawable, android.os.UserHandle);
     method public long getSerialNumberForUser(android.os.UserHandle);
     method public int getUserCount();
     method public android.os.UserHandle getUserForSerialNumber(long);
@@ -22338,16 +22696,21 @@
 
   public final class DocumentsContract {
     method public static android.net.Uri buildChildDocumentsUri(java.lang.String, java.lang.String);
+    method public static android.net.Uri buildChildDocumentsViaUri(android.net.Uri, java.lang.String);
     method public static android.net.Uri buildDocumentUri(java.lang.String, java.lang.String);
+    method public static android.net.Uri buildDocumentViaUri(android.net.Uri, java.lang.String);
     method public static android.net.Uri buildRecentDocumentsUri(java.lang.String, java.lang.String);
     method public static android.net.Uri buildRootUri(java.lang.String, java.lang.String);
     method public static android.net.Uri buildRootsUri(java.lang.String);
     method public static android.net.Uri buildSearchDocumentsUri(java.lang.String, java.lang.String, java.lang.String);
+    method public static android.net.Uri buildViaUri(java.lang.String, java.lang.String);
+    method public static android.net.Uri createDocument(android.content.ContentResolver, android.net.Uri, java.lang.String, java.lang.String);
     method public static boolean deleteDocument(android.content.ContentResolver, android.net.Uri);
     method public static java.lang.String getDocumentId(android.net.Uri);
     method public static android.graphics.Bitmap getDocumentThumbnail(android.content.ContentResolver, android.net.Uri, android.graphics.Point, android.os.CancellationSignal);
     method public static java.lang.String getRootId(android.net.Uri);
     method public static java.lang.String getSearchDocumentsQuery(android.net.Uri);
+    method public static java.lang.String getViaDocumentId(android.net.Uri);
     method public static boolean isDocumentUri(android.content.Context, android.net.Uri);
     field public static final java.lang.String EXTRA_ERROR = "error";
     field public static final java.lang.String EXTRA_INFO = "info";
@@ -22384,6 +22747,7 @@
     field public static final java.lang.String COLUMN_TITLE = "title";
     field public static final int FLAG_LOCAL_ONLY = 2; // 0x2
     field public static final int FLAG_SUPPORTS_CREATE = 1; // 0x1
+    field public static final int FLAG_SUPPORTS_DIR_SELECTION = 16; // 0x10
     field public static final int FLAG_SUPPORTS_RECENTS = 4; // 0x4
     field public static final int FLAG_SUPPORTS_SEARCH = 8; // 0x8
   }
@@ -22396,6 +22760,9 @@
     method public java.lang.String getDocumentType(java.lang.String) throws java.io.FileNotFoundException;
     method public final java.lang.String getType(android.net.Uri);
     method public final android.net.Uri insert(android.net.Uri, android.content.ContentValues);
+    method public boolean isChildDocument(java.lang.String, java.lang.String);
+    method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
+    method public final android.content.res.AssetFileDescriptor openAssetFile(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public abstract android.os.ParcelFileDescriptor openDocument(java.lang.String, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public android.content.res.AssetFileDescriptor openDocumentThumbnail(java.lang.String, android.graphics.Point, android.os.CancellationSignal) throws java.io.FileNotFoundException;
     method public final android.os.ParcelFileDescriptor openFile(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -22408,6 +22775,7 @@
     method public android.database.Cursor queryRecentDocuments(java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
     method public abstract android.database.Cursor queryRoots(java.lang.String[]) throws java.io.FileNotFoundException;
     method public android.database.Cursor querySearchDocuments(java.lang.String, java.lang.String, java.lang.String[]) throws java.io.FileNotFoundException;
+    method public final void revokeDocumentPermission(java.lang.String);
     method public final int update(android.net.Uri, android.content.ContentValues, java.lang.String, java.lang.String[]);
   }
 
@@ -23384,6 +23752,71 @@
     field public static final java.lang.String TYPE = "type";
   }
 
+  public final class TvContract {
+    method public static final android.net.Uri buildChannelUri(long);
+    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName);
+    method public static final android.net.Uri buildChannelsUriForInput(android.content.ComponentName, boolean);
+    method public static final android.net.Uri buildProgramUri(long);
+    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri);
+    method public static final android.net.Uri buildProgramsUriForChannel(android.net.Uri, long, long);
+    field public static final java.lang.String AUTHORITY = "com.android.tv";
+  }
+
+  public static abstract interface TvContract.BaseTvColumns implements android.provider.BaseColumns {
+    field public static final java.lang.String PACKAGE_NAME = "package_name";
+  }
+
+  public static final class TvContract.Channels implements android.provider.TvContract.BaseTvColumns {
+    field public static final java.lang.String BROWSABLE = "browsable";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.channels";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA = "data";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String DISPLAY_NAME = "display_name";
+    field public static final java.lang.String DISPLAY_NUMBER = "display_number";
+    field public static final java.lang.String SERVICE_NAME = "service_name";
+    field public static final java.lang.String TRANSPORT_STREAM_ID = "transport_stream_id";
+    field public static final java.lang.String TYPE = "type";
+    field public static final int TYPE_1SEG = 263168; // 0x40400
+    field public static final int TYPE_ATSC = 196608; // 0x30000
+    field public static final int TYPE_ATSC_2_0 = 196609; // 0x30001
+    field public static final int TYPE_ATSC_M_H = 196864; // 0x30100
+    field public static final int TYPE_CMMB = 327936; // 0x50100
+    field public static final int TYPE_DTMB = 327680; // 0x50000
+    field public static final int TYPE_DVB_C = 131584; // 0x20200
+    field public static final int TYPE_DVB_C2 = 131585; // 0x20201
+    field public static final int TYPE_DVB_H = 131840; // 0x20300
+    field public static final int TYPE_DVB_S = 131328; // 0x20100
+    field public static final int TYPE_DVB_S2 = 131329; // 0x20101
+    field public static final int TYPE_DVB_SH = 132096; // 0x20400
+    field public static final int TYPE_DVB_T = 131072; // 0x20000
+    field public static final int TYPE_DVB_T2 = 131073; // 0x20001
+    field public static final int TYPE_ISDB_C = 262912; // 0x40300
+    field public static final int TYPE_ISDB_S = 262656; // 0x40200
+    field public static final int TYPE_ISDB_T = 262144; // 0x40000
+    field public static final int TYPE_ISDB_TB = 262400; // 0x40100
+    field public static final int TYPE_OTHER = 0; // 0x0
+    field public static final int TYPE_PASSTHROUGH = 65536; // 0x10000
+    field public static final int TYPE_S_DMB = 393472; // 0x60100
+    field public static final int TYPE_T_DMB = 393216; // 0x60000
+    field public static final java.lang.String VERSION_NUMBER = "version_number";
+  }
+
+  public static final class TvContract.Programs implements android.provider.TvContract.BaseTvColumns {
+    field public static final java.lang.String CHANNEL_ID = "channel_id";
+    field public static final java.lang.String CONTENT_ITEM_TYPE = "vnd.android.cursor.item/vnd.com.android.tv.programs";
+    field public static final java.lang.String CONTENT_TYPE = "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+    field public static final android.net.Uri CONTENT_URI;
+    field public static final java.lang.String DATA = "data";
+    field public static final java.lang.String DESCRIPTION = "description";
+    field public static final java.lang.String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+    field public static final java.lang.String LONG_DESCRIPTION = "long_description";
+    field public static final java.lang.String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+    field public static final java.lang.String TITLE = "title";
+    field public static final java.lang.String VERSION_NUMBER = "version_number";
+  }
+
   public class UserDictionary {
     ctor public UserDictionary();
     field public static final java.lang.String AUTHORITY = "user_dictionary";
@@ -24268,6 +24701,15 @@
     method public void setRed(int, int);
   }
 
+  public final class ScriptIntrinsicResize extends android.renderscript.ScriptIntrinsic {
+    method public static android.renderscript.ScriptIntrinsicResize create(android.renderscript.RenderScript);
+    method public void forEach_bicubic(android.renderscript.Allocation);
+    method public void forEach_bicubic(android.renderscript.Allocation, android.renderscript.Script.LaunchOptions);
+    method public android.renderscript.Script.FieldID getFieldID_Input();
+    method public android.renderscript.Script.KernelID getKernelID_bicubic();
+    method public void setInput(android.renderscript.Allocation);
+  }
+
   public final class ScriptIntrinsicYuvToRGB extends android.renderscript.ScriptIntrinsic {
     method public static android.renderscript.ScriptIntrinsicYuvToRGB create(android.renderscript.RenderScript, android.renderscript.Element);
     method public void forEach(android.renderscript.Allocation);
@@ -24572,6 +25014,42 @@
 
 }
 
+package android.service.voice {
+
+  public class VoiceInteractionService extends android.app.Service {
+    ctor public VoiceInteractionService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public void startVoiceActivity(android.content.Intent, android.os.Bundle);
+    field public static final java.lang.String SERVICE_INTERFACE = "android.service.voice.VoiceInteractionService";
+    field public static final java.lang.String SERVICE_META_DATA = "android.voice_interaction";
+  }
+
+  public abstract class VoiceInteractionSession {
+    ctor public VoiceInteractionSession(android.content.Context);
+    ctor public VoiceInteractionSession(android.content.Context, android.os.Handler);
+    method public abstract void onCancel(android.service.voice.VoiceInteractionSession.Request);
+    method public abstract void onCommand(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+    method public abstract void onConfirm(android.service.voice.VoiceInteractionSession.Caller, android.service.voice.VoiceInteractionSession.Request, java.lang.String, android.os.Bundle);
+    method public abstract boolean[] onGetSupportedCommands(android.service.voice.VoiceInteractionSession.Caller, java.lang.String[]);
+  }
+
+  public static class VoiceInteractionSession.Caller {
+  }
+
+  public static class VoiceInteractionSession.Request {
+    method public void sendCancelResult();
+    method public void sendCommandResult(boolean, android.os.Bundle);
+    method public void sendConfirmResult(boolean, android.os.Bundle);
+  }
+
+  public abstract class VoiceInteractionSessionService extends android.app.Service {
+    ctor public VoiceInteractionSessionService();
+    method public android.os.IBinder onBind(android.content.Intent);
+    method public abstract android.service.voice.VoiceInteractionSession onNewSession(android.os.Bundle);
+  }
+
+}
+
 package android.service.wallpaper {
 
   public abstract class WallpaperService extends android.app.Service {
@@ -24870,7 +25348,7 @@
     method public abstract void onUtteranceCompleted(java.lang.String);
   }
 
-  public final class TextToSpeechClient {
+  public class TextToSpeechClient {
     ctor public TextToSpeechClient(android.content.Context, java.lang.String, boolean, android.speech.tts.TextToSpeechClient.RequestCallbacks, android.speech.tts.TextToSpeechClient.ConnectionCallbacks);
     ctor public TextToSpeechClient(android.content.Context, android.speech.tts.TextToSpeechClient.RequestCallbacks, android.speech.tts.TextToSpeechClient.ConnectionCallbacks);
     method public void connect();
@@ -26064,6 +26542,7 @@
     method public java.lang.String getInstallerPackageName(java.lang.String);
     method public android.content.pm.InstrumentationInfo getInstrumentationInfo(android.content.ComponentName, int) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.Intent getLaunchIntentForPackage(java.lang.String);
+    method public android.content.Intent getLeanbackLaunchIntentForPackage(java.lang.String);
     method public java.lang.String getNameForUid(int);
     method public int[] getPackageGids(java.lang.String) throws android.content.pm.PackageManager.NameNotFoundException;
     method public android.content.pm.PackageInfo getPackageInfo(java.lang.String, int) throws android.content.pm.PackageManager.NameNotFoundException;
@@ -27558,6 +28037,18 @@
     method public void setResizeClip(boolean);
   }
 
+  public class ChangeClipBounds extends android.transition.Transition {
+    ctor public ChangeClipBounds();
+    method public void captureEndValues(android.transition.TransitionValues);
+    method public void captureStartValues(android.transition.TransitionValues);
+  }
+
+  public class ChangeTransform extends android.transition.Transition {
+    ctor public ChangeTransform();
+    method public void captureEndValues(android.transition.TransitionValues);
+    method public void captureStartValues(android.transition.TransitionValues);
+  }
+
   public class CircularPropagation extends android.transition.VisibilityPropagation {
     ctor public CircularPropagation();
     method public long getStartDelay(android.view.ViewGroup, android.transition.Transition, android.transition.TransitionValues, android.transition.TransitionValues);
@@ -27618,6 +28109,7 @@
     ctor public Transition();
     method public android.transition.Transition addListener(android.transition.Transition.TransitionListener);
     method public android.transition.Transition addTarget(int);
+    method public android.transition.Transition addTarget(java.lang.Class);
     method public android.transition.Transition addTarget(android.view.View);
     method public boolean canRemoveViews();
     method public abstract void captureEndValues(android.transition.TransitionValues);
@@ -27676,7 +28168,6 @@
     method public static void beginDelayedTransition(android.view.ViewGroup, android.transition.Transition);
     method public static void go(android.transition.Scene);
     method public static void go(android.transition.Scene, android.transition.Transition);
-    method public void setExitTransition(android.transition.Scene, android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Transition);
     method public void setTransition(android.transition.Scene, android.transition.Scene, android.transition.Transition);
     method public void transitionTo(android.transition.Scene);
@@ -27751,7 +28242,6 @@
 
   public static final class TvInputManager.Session {
     method public void release();
-    method public void setSurface(android.view.Surface);
     method public void setVolume(float);
     method public void tune(android.net.Uri);
   }
@@ -27773,20 +28263,36 @@
     field public static final java.lang.String SERVICE_INTERFACE = "android.tv.TvInputService";
   }
 
-  public static abstract class TvInputService.TvInputSessionImpl {
+  public abstract class TvInputService.TvInputSessionImpl implements android.view.KeyEvent.Callback {
     ctor public TvInputService.TvInputSessionImpl();
+    method public android.view.View onCreateOverlayView();
+    method public boolean onGenericMotionEvent(android.view.MotionEvent);
+    method public boolean onKeyDown(int, android.view.KeyEvent);
+    method public boolean onKeyLongPress(int, android.view.KeyEvent);
+    method public boolean onKeyMultiple(int, int, android.view.KeyEvent);
+    method public boolean onKeyUp(int, android.view.KeyEvent);
     method public abstract void onRelease();
     method public abstract boolean onSetSurface(android.view.Surface);
     method public abstract void onSetVolume(float);
+    method public boolean onTouchEvent(android.view.MotionEvent);
+    method public boolean onTrackballEvent(android.view.MotionEvent);
     method public abstract boolean onTune(android.net.Uri);
+    method public void setOverlayViewEnabled(boolean);
   }
 
-  public abstract class TvInputSession {
-    ctor public TvInputSession();
-    method public void release();
-    method public void setSurface(android.view.Surface);
-    method public void setVolume(float);
-    method public void tune(android.net.Uri);
+  public class TvView extends android.view.SurfaceView {
+    ctor public TvView(android.content.Context);
+    ctor public TvView(android.content.Context, android.util.AttributeSet);
+    ctor public TvView(android.content.Context, android.util.AttributeSet, int);
+    method public void bindTvInput(android.content.ComponentName, android.tv.TvInputManager.SessionCreateCallback);
+    method public boolean dispatchUnhandledInputEvent(android.view.InputEvent);
+    method public boolean onUnhandledInputEvent(android.view.InputEvent);
+    method public void setOnUnhandledInputEventListener(android.tv.TvView.OnUnhandledInputEventListener);
+    method public void unbindTvInput();
+  }
+
+  public static abstract interface TvView.OnUnhandledInputEventListener {
+    method public abstract boolean onUnhandledInputEvent(android.view.InputEvent);
   }
 
 }
@@ -28476,6 +28982,7 @@
     method public float getRefreshRate();
     method public int getRotation();
     method public void getSize(android.graphics.Point);
+    method public int getState();
     method public deprecated int getWidth();
     method public boolean isValid();
     field public static final int DEFAULT_DISPLAY = 0; // 0x0
@@ -28483,6 +28990,10 @@
     field public static final int FLAG_PRIVATE = 4; // 0x4
     field public static final int FLAG_SECURE = 2; // 0x2
     field public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1; // 0x1
+    field public static final int STATE_DOZING = 3; // 0x3
+    field public static final int STATE_OFF = 1; // 0x1
+    field public static final int STATE_ON = 2; // 0x2
+    field public static final int STATE_UNKNOWN = 0; // 0x0
   }
 
   public class DragEvent implements android.os.Parcelable {
@@ -28511,6 +29022,18 @@
     method public static android.view.FocusFinder getInstance();
   }
 
+  public abstract class FrameStats {
+    ctor public FrameStats();
+    method public final long getEndTimeNano();
+    method public final int getFrameCount();
+    method public final long getFramePresentedTimeNano(int);
+    method public final long getRefreshPeriodNano();
+    method public final long getStartTimeNano();
+    field public static final long UNDEFINED_TIME_NANO = -1L; // 0xffffffffffffffffL
+    field protected long[] mFramesPresentedTimeNano;
+    field protected long mRefreshPeriodNano;
+  }
+
   public class GestureDetector {
     ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener, android.os.Handler);
     ctor public deprecated GestureDetector(android.view.GestureDetector.OnGestureListener);
@@ -28816,7 +29339,7 @@
     field public static final int FLAG_SOFT_KEYBOARD = 2; // 0x2
     field public static final int FLAG_TRACKING = 512; // 0x200
     field public static final int FLAG_VIRTUAL_HARD_KEY = 64; // 0x40
-    field public static final int FLAG_WOKE_HERE = 1; // 0x1
+    field public static final deprecated int FLAG_WOKE_HERE = 1; // 0x1
     field public static final int KEYCODE_0 = 7; // 0x7
     field public static final int KEYCODE_1 = 8; // 0x8
     field public static final int KEYCODE_2 = 9; // 0x9
@@ -29661,6 +30184,9 @@
     method public boolean dispatchKeyEvent(android.view.KeyEvent);
     method public boolean dispatchKeyEventPreIme(android.view.KeyEvent);
     method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
+    method public boolean dispatchNestedFling(float, float);
+    method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
+    method public boolean dispatchNestedScroll(int, int, int, int, int[]);
     method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
     method protected void dispatchRestoreInstanceState(android.util.SparseArray<android.os.Parcelable>);
     method protected void dispatchSaveInstanceState(android.util.SparseArray<android.os.Parcelable>);
@@ -29710,6 +30236,7 @@
     method public int getDrawingCacheQuality();
     method public void getDrawingRect(android.graphics.Rect);
     method public long getDrawingTime();
+    method public float getElevation();
     method public boolean getFilterTouchesWhenObscured();
     method public boolean getFitsSystemWindows();
     method public java.util.ArrayList<android.view.View> getFocusables(int);
@@ -29808,8 +30335,10 @@
     method public void getWindowVisibleDisplayFrame(android.graphics.Rect);
     method public float getX();
     method public float getY();
+    method public float getZ();
     method public boolean hasFocus();
     method public boolean hasFocusable();
+    method public boolean hasNestedScrollingParent();
     method public boolean hasOnClickListeners();
     method public boolean hasOverlappingRendering();
     method public boolean hasTransientState();
@@ -29845,6 +30374,7 @@
     method public boolean isLayoutDirectionResolved();
     method public boolean isLayoutRequested();
     method public boolean isLongClickable();
+    method public boolean isNestedScrollingEnabled();
     method public boolean isOpaque();
     method protected boolean isPaddingOffsetRequired();
     method public boolean isPaddingRelative();
@@ -29972,6 +30502,7 @@
     method public void setDrawingCacheEnabled(boolean);
     method public void setDrawingCacheQuality(int);
     method public void setDuplicateParentStateEnabled(boolean);
+    method public void setElevation(float);
     method public void setEnabled(boolean);
     method public void setFadingEdgeLength(int);
     method public void setFilterTouchesWhenObscured(boolean);
@@ -29996,6 +30527,7 @@
     method protected final void setMeasuredDimension(int, int);
     method public void setMinimumHeight(int);
     method public void setMinimumWidth(int);
+    method public void setNestedScrollingEnabled(boolean);
     method public void setNextFocusDownId(int);
     method public void setNextFocusForwardId(int);
     method public void setNextFocusLeftId(int);
@@ -30056,10 +30588,13 @@
     method public void setWillNotDraw(boolean);
     method public void setX(float);
     method public void setY(float);
+    method public void setZ(float);
     method public boolean showContextMenu();
     method public android.view.ActionMode startActionMode(android.view.ActionMode.Callback);
     method public void startAnimation(android.view.animation.Animation);
     method public final boolean startDrag(android.content.ClipData, android.view.View.DragShadowBuilder, java.lang.Object, int);
+    method public boolean startNestedScroll(int);
+    method public void stopNestedScroll();
     method public void unscheduleDrawable(android.graphics.drawable.Drawable, java.lang.Runnable);
     method public void unscheduleDrawable(android.graphics.drawable.Drawable);
     method protected boolean verifyDrawable(android.graphics.drawable.Drawable);
@@ -30148,6 +30683,9 @@
     field public static final int SCROLLBAR_POSITION_DEFAULT = 0; // 0x0
     field public static final int SCROLLBAR_POSITION_LEFT = 1; // 0x1
     field public static final int SCROLLBAR_POSITION_RIGHT = 2; // 0x2
+    field public static final int SCROLL_AXIS_HORIZONTAL = 1; // 0x1
+    field public static final int SCROLL_AXIS_NONE = 0; // 0x0
+    field public static final int SCROLL_AXIS_VERTICAL = 2; // 0x2
     field protected static final int[] SELECTED_STATE_SET;
     field protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
     field public static final int SOUND_EFFECTS_ENABLED = 134217728; // 0x8000000
@@ -30184,6 +30722,7 @@
     field protected static final int[] WINDOW_FOCUSED_STATE_SET;
     field public static final android.util.Property X;
     field public static final android.util.Property Y;
+    field public static final android.util.Property Z;
   }
 
   public static class View.AccessibilityDelegate {
@@ -30417,6 +30956,7 @@
     method public android.view.animation.Animation.AnimationListener getLayoutAnimationListener();
     method public int getLayoutMode();
     method public android.animation.LayoutTransition getLayoutTransition();
+    method public int getNestedScrollAxes();
     method public int getPersistentDrawingCache();
     method public int indexOfChild(android.view.View);
     method public final void invalidateChild(android.view.View, android.graphics.Rect);
@@ -30437,8 +30977,14 @@
     method public boolean onInterceptHoverEvent(android.view.MotionEvent);
     method public boolean onInterceptTouchEvent(android.view.MotionEvent);
     method protected abstract void onLayout(boolean, int, int, int, int);
+    method public boolean onNestedFling(android.view.View, float, float);
+    method public void onNestedPreScroll(android.view.View, int, int, int[]);
+    method public void onNestedScroll(android.view.View, int, int, int, int);
+    method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
     method protected boolean onRequestFocusInDescendants(int, android.graphics.Rect);
     method public boolean onRequestSendAccessibilityEvent(android.view.View, android.view.accessibility.AccessibilityEvent);
+    method public boolean onStartNestedScroll(android.view.View, android.view.View, int);
+    method public void onStopNestedScroll(android.view.View);
     method public void recomputeViewAttributes(android.view.View);
     method public void removeAllViews();
     method public void removeAllViewsInLayout();
@@ -30569,6 +31115,12 @@
     method public abstract boolean isTextAlignmentResolved();
     method public abstract boolean isTextDirectionResolved();
     method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
+    method public abstract boolean onNestedFling(android.view.View, float, float);
+    method public abstract void onNestedPreScroll(android.view.View, int, int, int[]);
+    method public abstract void onNestedScroll(android.view.View, int, int, int, int);
+    method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int);
+    method public abstract boolean onStartNestedScroll(android.view.View, android.view.View, int);
+    method public abstract void onStopNestedScroll(android.view.View);
     method public abstract void recomputeViewAttributes(android.view.View);
     method public abstract void requestChildFocus(android.view.View, android.view.View);
     method public abstract boolean requestChildRectangleOnScreen(android.view.View, android.graphics.Rect, boolean);
@@ -30617,6 +31169,8 @@
     method public android.view.ViewPropertyAnimator xBy(float);
     method public android.view.ViewPropertyAnimator y(float);
     method public android.view.ViewPropertyAnimator yBy(float);
+    method public android.view.ViewPropertyAnimator z(float);
+    method public android.view.ViewPropertyAnimator zBy(float);
   }
 
   public final class ViewStub extends android.view.View {
@@ -30704,6 +31258,8 @@
     method public abstract void closeAllPanels();
     method public abstract void closePanel(int);
     method public android.view.View findViewById(int);
+    method public boolean getAllowEnterTransitionOverlap();
+    method public boolean getAllowExitTransitionOverlap();
     method public final android.view.WindowManager.LayoutParams getAttributes();
     method public final android.view.Window.Callback getCallback();
     method public final android.view.Window getContainer();
@@ -30711,10 +31267,14 @@
     method public final android.content.Context getContext();
     method public abstract android.view.View getCurrentFocus();
     method public abstract android.view.View getDecorView();
+    method public android.transition.Transition getEnterTransition();
+    method public android.transition.Transition getExitTransition();
     method protected final int getFeatures();
     method protected final int getForcedWindowFlags();
     method public abstract android.view.LayoutInflater getLayoutInflater();
     method protected final int getLocalFeatures();
+    method public android.transition.Transition getSharedElementEnterTransition();
+    method public android.transition.Transition getSharedElementExitTransition();
     method public android.transition.TransitionManager getTransitionManager();
     method public abstract int getVolumeControlStream();
     method public android.view.WindowManager getWindowManager();
@@ -30728,7 +31288,6 @@
     method public abstract boolean isFloating();
     method public abstract boolean isShortcutKey(int, android.view.KeyEvent);
     method public final void makeActive();
-    method public void mapTransitionTargets(java.util.Map<java.lang.String, java.lang.String>);
     method protected abstract void onActive();
     method public abstract void onConfigurationChanged(android.content.res.Configuration);
     method public abstract void openPanel(int, android.view.KeyEvent);
@@ -30739,8 +31298,8 @@
     method public boolean requestFeature(int);
     method public abstract void restoreHierarchyState(android.os.Bundle);
     method public abstract android.os.Bundle saveHierarchyState();
-    method public void setAllowOverlappingEnterTransition(boolean);
-    method public void setAllowOverlappingExitTransition(boolean);
+    method public void setAllowEnterTransitionOverlap(boolean);
+    method public void setAllowExitTransitionOverlap(boolean);
     method public void setAttributes(android.view.WindowManager.LayoutParams);
     method public abstract void setBackgroundDrawable(android.graphics.drawable.Drawable);
     method public void setBackgroundDrawableResource(int);
@@ -30753,6 +31312,8 @@
     method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method protected void setDefaultWindowFormat(int);
     method public void setDimAmount(float);
+    method public void setEnterTransition(android.transition.Transition);
+    method public void setExitTransition(android.transition.Transition);
     method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable);
     method public abstract void setFeatureDrawableAlpha(int, int);
     method public abstract void setFeatureDrawableResource(int, int);
@@ -30765,6 +31326,8 @@
     method public void setLayout(int, int);
     method public void setLocalFocus(boolean, boolean);
     method public void setLogo(int);
+    method public void setSharedElementEnterTransition(android.transition.Transition);
+    method public void setSharedElementExitTransition(android.transition.Transition);
     method public void setSoftInputMode(int);
     method public abstract void setTitle(java.lang.CharSequence);
     method public abstract deprecated void setTitleColor(int);
@@ -30835,6 +31398,20 @@
     method public abstract android.view.ActionMode onWindowStartingActionMode(android.view.ActionMode.Callback);
   }
 
+  public final class WindowAnimationFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
+  public final class WindowContentFrameStats extends android.view.FrameStats implements android.os.Parcelable {
+    method public int describeContents();
+    method public long getFramePostedTimeNano(int);
+    method public long getFrameReadyTimeNano(int);
+    method public void writeToParcel(android.os.Parcel, int);
+    field public static final android.os.Parcelable.Creator CREATOR;
+  }
+
   public class WindowId implements android.os.Parcelable {
     method public int describeContents();
     method public boolean isFocused();
@@ -30869,6 +31446,7 @@
     method public boolean hasInsets();
     method public boolean hasSystemWindowInsets();
     method public boolean hasWindowDecorInsets();
+    method public boolean isRound();
   }
 
   public abstract interface WindowManager implements android.view.ViewManager {
@@ -30936,7 +31514,7 @@
     field public static final int FLAG_SHOW_WALLPAPER = 1048576; // 0x100000
     field public static final int FLAG_SHOW_WHEN_LOCKED = 524288; // 0x80000
     field public static final int FLAG_SPLIT_TOUCH = 8388608; // 0x800000
-    field public static final int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
+    field public static final deprecated int FLAG_TOUCHABLE_WHEN_WAKING = 64; // 0x40
     field public static final int FLAG_TRANSLUCENT_NAVIGATION = 134217728; // 0x8000000
     field public static final int FLAG_TRANSLUCENT_STATUS = 67108864; // 0x4000000
     field public static final int FLAG_TURN_SCREEN_ON = 2097152; // 0x200000
@@ -32483,7 +33061,8 @@
     method public void clearSslPreferences();
     method public deprecated void clearView();
     method public android.webkit.WebBackForwardList copyBackForwardList();
-    method public android.print.PrintDocumentAdapter createPrintDocumentAdapter();
+    method public deprecated android.print.PrintDocumentAdapter createPrintDocumentAdapter();
+    method public android.print.PrintDocumentAdapter createPrintDocumentAdapter(java.lang.String);
     method public void destroy();
     method public void documentHasImages(android.os.Message);
     method public void evaluateJavascript(java.lang.String, android.webkit.ValueCallback<java.lang.String>);
@@ -34073,6 +34652,7 @@
     method public void setExcludeMimes(java.lang.String[]);
     method public void setImageToDefault();
     method public void setMode(int);
+    method public void setOverlay(android.graphics.drawable.Drawable);
     field protected java.lang.String[] mExcludeMimes;
   }
 
@@ -34836,6 +35416,7 @@
     method public void setCursorVisible(boolean);
     method public void setCustomSelectionActionModeCallback(android.view.ActionMode.Callback);
     method public final void setEditableFactory(android.text.Editable.Factory);
+    method public void setElegantTextHeight(boolean);
     method public void setEllipsize(android.text.TextUtils.TruncateAt);
     method public void setEms(int);
     method public void setError(java.lang.CharSequence);
diff --git a/cmds/am/src/com/android/commands/am/Am.java b/cmds/am/src/com/android/commands/am/Am.java
index 92cb52c..6b55b7b 100644
--- a/cmds/am/src/com/android/commands/am/Am.java
+++ b/cmds/am/src/com/android/commands/am/Am.java
@@ -240,6 +240,7 @@
                 "        (to embed a comma into a string escape it using \"\\,\")\n" +
                 "    [-n <COMPONENT>] [-f <FLAGS>]\n" +
                 "    [--grant-read-uri-permission] [--grant-write-uri-permission]\n" +
+                "    [--grant-persistable-uri-permission] [--grant-prefix-uri-permission]\n" +
                 "    [--debug-log-resolution] [--exclude-stopped-packages]\n" +
                 "    [--include-stopped-packages]\n" +
                 "    [--activity-brought-to-front] [--activity-clear-top]\n" +
@@ -455,6 +456,10 @@
                 intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
             } else if (opt.equals("--grant-write-uri-permission")) {
                 intent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            } else if (opt.equals("--grant-persistable-uri-permission")) {
+                intent.addFlags(Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+            } else if (opt.equals("--grant-prefix-uri-permission")) {
+                intent.addFlags(Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
             } else if (opt.equals("--exclude-stopped-packages")) {
                 intent.addFlags(Intent.FLAG_EXCLUDE_STOPPED_PACKAGES);
             } else if (opt.equals("--include-stopped-packages")) {
@@ -744,6 +749,11 @@
                             "Error: Activity not started, you do not "
                             + "have permission to access it.");
                     break;
+                case ActivityManager.START_NOT_VOICE_COMPATIBLE:
+                    out.println(
+                            "Error: Activity not started, voice control not allowed for: "
+                                    + intent);
+                    break;
                 default:
                     out.println(
                             "Error: Activity not started, unknown error code " + res);
diff --git a/cmds/app_process/app_main.cpp b/cmds/app_process/app_main.cpp
index 3e8d6a0..74ccbc2 100644
--- a/cmds/app_process/app_main.cpp
+++ b/cmds/app_process/app_main.cpp
@@ -15,10 +15,12 @@
 #include <cutils/properties.h>
 #include <cutils/trace.h>
 #include <android_runtime/AndroidRuntime.h>
+#include <private/android_filesystem_config.h>  // for AID_SYSTEM
 
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
+#include <sys/prctl.h>
 
 namespace android {
 
@@ -97,7 +99,7 @@
 
     virtual void onExit(int code)
     {
-        if (mClassName == NULL) {
+        if (mClassName.isEmpty()) {
             // if zygote
             IPCThreadState::self()->stopProcess();
         }
@@ -136,14 +138,63 @@
     return (end - start);
 }
 
+static void maybeCreateDalvikCache() {
+#if defined(__aarch64__)
+    static const char kInstructionSet[] = "arm64";
+#elif defined(__x86_64__)
+    static const char kInstructionSet[] = "x86_64";
+#elif defined(__arm__)
+    static const char kInstructionSet[] = "arm";
+#elif defined(__i386__)
+    static const char kInstructionSet[] = "x86";
+#elif defined (__mips__)
+    static const char kInstructionSet[] = "mips";
+#else
+#error "Unknown instruction set"
+#endif
+    const char* androidRoot = getenv("ANDROID_DATA");
+    LOG_ALWAYS_FATAL_IF(androidRoot == NULL, "ANDROID_DATA environment variable unset");
+
+    char dalvikCacheDir[PATH_MAX];
+    const int numChars = snprintf(dalvikCacheDir, PATH_MAX,
+            "%s/dalvik-cache/%s", androidRoot, kInstructionSet);
+    LOG_ALWAYS_FATAL_IF((numChars >= PATH_MAX || numChars < 0),
+            "Error constructing dalvik cache : %s", strerror(errno));
+
+    int result = mkdir(dalvikCacheDir, 0771);
+    LOG_ALWAYS_FATAL_IF((result < 0 && errno != EEXIST),
+            "Error creating cache dir %s : %s", dalvikCacheDir, strerror(errno));
+
+    // We always perform these steps because the directory might
+    // already exist, with wider permissions and a different owner
+    // than we'd like.
+    result = chown(dalvikCacheDir, AID_SYSTEM, AID_SYSTEM);
+    LOG_ALWAYS_FATAL_IF((result < 0), "Error changing dalvik-cache ownership : %s", strerror(errno));
+
+    result = chmod(dalvikCacheDir, 0771);
+    LOG_ALWAYS_FATAL_IF((result < 0),
+            "Error changing dalvik-cache permissions : %s", strerror(errno));
+}
+
 #if defined(__LP64__)
 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist64";
+static const char ZYGOTE_NICE_NAME[] = "zygote64";
 #else
 static const char ABI_LIST_PROPERTY[] = "ro.product.cpu.abilist32";
+static const char ZYGOTE_NICE_NAME[] = "zygote";
 #endif
 
 int main(int argc, char* const argv[])
 {
+    if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+        // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return
+        // EINVAL. Don't die on such kernels.
+        if (errno != EINVAL) {
+            LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno));
+            return 12;
+        }
+    }
+
     AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
     // Process command line arguments
     // ignore argv[0]
@@ -185,16 +236,19 @@
         const char* arg = argv[i++];
         if (strcmp(arg, "--zygote") == 0) {
             zygote = true;
-            niceName = "zygote";
+            niceName = ZYGOTE_NICE_NAME;
         } else if (strcmp(arg, "--start-system-server") == 0) {
             startSystemServer = true;
         } else if (strcmp(arg, "--application") == 0) {
             application = true;
         } else if (strncmp(arg, "--nice-name=", 12) == 0) {
             niceName = arg + 12;
-        } else {
+        } else if (strncmp(arg, "--", 2) != 0) {
             className.setTo(arg);
             break;
+        } else {
+            --i;
+            break;
         }
     }
 
@@ -208,13 +262,16 @@
         args.add(application ? String8("application") : String8("tool"));
         runtime.setClassNameAndArgs(className, argc - i, argv + i);
     } else {
+        // We're in zygote mode.
+        maybeCreateDalvikCache();
+
         if (startSystemServer) {
             args.add(String8("start-system-server"));
         }
 
         char prop[PROP_VALUE_MAX];
         if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
-            LOG_ALWAYS_FATAL("app_process: Unable to deterimine ABI list from property %s.",
+            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                 ABI_LIST_PROPERTY);
             return 11;
         }
diff --git a/cmds/bootanimation/BootAnimation.cpp b/cmds/bootanimation/BootAnimation.cpp
index 41afa39..3dc024e 100644
--- a/cmds/bootanimation/BootAnimation.cpp
+++ b/cmds/bootanimation/BootAnimation.cpp
@@ -51,6 +51,7 @@
 
 #include "BootAnimation.h"
 
+#define OEM_BOOTANIMATION_FILE "/oem/media/bootanimation.zip"
 #define SYSTEM_BOOTANIMATION_FILE "/system/media/bootanimation.zip"
 #define SYSTEM_ENCRYPTED_BOOTANIMATION_FILE "/system/media/bootanimation-encrypted.zip"
 #define EXIT_PROP_NAME "service.bootanim.exit"
@@ -155,12 +156,12 @@
     return NO_ERROR;
 }
 
-status_t BootAnimation::initTexture(void* buffer, size_t len)
+status_t BootAnimation::initTexture(const Animation::Frame& frame)
 {
     //StopWatch watch("blah");
 
     SkBitmap bitmap;
-    SkMemoryStream  stream(buffer, len);
+    SkMemoryStream  stream(frame.map->getDataPtr(), frame.map->getDataLength());
     SkImageDecoder* codec = SkImageDecoder::Factory(&stream);
     if (codec) {
         codec->setDitherImage(false);
@@ -170,6 +171,11 @@
         delete codec;
     }
 
+    // FileMap memory is never released until application exit.
+    // Release it now as the texture is already loaded and the memory used for
+    // the packed resource can be released.
+    frame.map->release();
+
     // ensure we can call getPixels(). No need to call unlock, since the
     // bitmap will go out of scope when we return from this method.
     bitmap.lockPixels();
@@ -283,6 +289,9 @@
             (access(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE, R_OK) == 0) &&
             ((zipFile = ZipFileRO::open(SYSTEM_ENCRYPTED_BOOTANIMATION_FILE)) != NULL)) ||
 
+            ((access(OEM_BOOTANIMATION_FILE, R_OK) == 0) &&
+            ((zipFile = ZipFileRO::open(OEM_BOOTANIMATION_FILE)) != NULL)) ||
+
             ((access(SYSTEM_BOOTANIMATION_FILE, R_OK) == 0) &&
             ((zipFile = ZipFileRO::open(SYSTEM_BOOTANIMATION_FILE)) != NULL))) {
         mZip = zipFile;
@@ -405,6 +414,7 @@
 
     String8 desString((char const*)descMap->getDataPtr(),
             descMap->getDataLength());
+    descMap->release();
     char const* s = desString.string();
 
     Animation animation;
@@ -529,9 +539,7 @@
                         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                         glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
                     }
-                    initTexture(
-                            frame.map->getDataPtr(),
-                            frame.map->getDataLength());
+                    initTexture(frame);
                 }
 
                 if (!clearReg.isEmpty()) {
diff --git a/cmds/bootanimation/BootAnimation.h b/cmds/bootanimation/BootAnimation.h
index 22963c2..ba1c507 100644
--- a/cmds/bootanimation/BootAnimation.h
+++ b/cmds/bootanimation/BootAnimation.h
@@ -79,7 +79,7 @@
     };
 
     status_t initTexture(Texture* texture, AssetManager& asset, const char* name);
-    status_t initTexture(void* buffer, size_t len);
+    status_t initTexture(const Animation::Frame& frame);
     bool android();
     bool movie();
 
diff --git a/cmds/content/src/com/android/commands/content/Content.java b/cmds/content/src/com/android/commands/content/Content.java
index 466dcd4..948c9a2 100644
--- a/cmds/content/src/com/android/commands/content/Content.java
+++ b/cmds/content/src/com/android/commands/content/Content.java
@@ -26,9 +26,17 @@
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.ParcelFileDescriptor;
 import android.os.UserHandle;
 import android.text.TextUtils;
 
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import libcore.io.IoUtils;
+
 /**
  * This class is a command line utility for manipulating content. A client
  * can insert, update, and remove records in a content provider. For example,
@@ -109,6 +117,12 @@
         + "  <METHOD> is the name of a provider-defined method\n"
         + "  <ARG> is an optional string argument\n"
         + "  <BINDING> is like --bind above, typed data of the form <KEY>:{b,s,i,l,f,d}:<VAL>\n"
+        + "\n"
+        + "usage: adb shell content read --uri <URI> [--user <USER_ID>]\n"
+        + "  Example:\n"
+        + "  # cat default ringtone to a file, then pull to host\n"
+        + "  adb shell 'content read --uri content://settings/system/ringtone >"
+                + " /mnt/sdcard/tmp.ogg' && adb pull /mnt/sdcard/tmp.ogg\n"
         + "\n";
 
     private static class Parser {
@@ -117,6 +131,7 @@
         private static final String ARGUMENT_UPDATE = "update";
         private static final String ARGUMENT_QUERY = "query";
         private static final String ARGUMENT_CALL = "call";
+        private static final String ARGUMENT_READ = "read";
         private static final String ARGUMENT_WHERE = "--where";
         private static final String ARGUMENT_BIND = "--bind";
         private static final String ARGUMENT_URI = "--uri";
@@ -154,6 +169,8 @@
                     return parseQueryCommand();
                 } else if (ARGUMENT_CALL.equals(operation)) {
                     return parseCallCommand();
+                } else if (ARGUMENT_READ.equals(operation)) {
+                    return parseReadCommand();
                 } else {
                     throw new IllegalArgumentException("Unsupported operation: " + operation);
                 }
@@ -273,6 +290,25 @@
             return new CallCommand(uri, userId, method, arg, values);
         }
 
+        private ReadCommand parseReadCommand() {
+            Uri uri = null;
+            int userId = UserHandle.USER_OWNER;
+            for (String argument; (argument = mTokenizer.nextArg())!= null;) {
+                if (ARGUMENT_URI.equals(argument)) {
+                    uri = Uri.parse(argumentValueRequired(argument));
+                } else if (ARGUMENT_USER.equals(argument)) {
+                    userId = Integer.parseInt(argumentValueRequired(argument));
+                } else {
+                    throw new IllegalArgumentException("Unsupported argument: " + argument);
+                }
+            }
+            if (uri == null) {
+                throw new IllegalArgumentException("Content provider URI not specified."
+                        + " Did you specify --uri argument?");
+            }
+            return new ReadCommand(uri, userId);
+        }
+
         public QueryCommand parseQueryCommand() {
             Uri uri = null;
             int userId = UserHandle.USER_OWNER;
@@ -458,6 +494,31 @@
         }
     }
 
+    private static class ReadCommand extends Command {
+        public ReadCommand(Uri uri, int userId) {
+            super(uri, userId);
+        }
+
+        @Override
+        public void onExecute(IContentProvider provider) throws Exception {
+            final ParcelFileDescriptor fd = provider.openFile(null, mUri, "r", null);
+            copy(new FileInputStream(fd.getFileDescriptor()), System.out);
+        }
+
+        private static void copy(InputStream is, OutputStream os) throws IOException {
+            final byte[] buffer = new byte[8 * 1024];
+            int read;
+            try {
+                while ((read = is.read(buffer)) > -1) {
+                    os.write(buffer, 0, read);
+                }
+            } finally {
+                IoUtils.closeQuietly(is);
+                IoUtils.closeQuietly(os);
+            }
+        }
+    }
+
     private static class QueryCommand extends DeleteCommand {
         final String[] mProjection;
         final String mSortOrder;
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index b01d92c..2620c44 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -526,6 +526,31 @@
     }
 
     /**
+     * Find the view that has the specified focus type. The search is performed
+     * across all windows.
+     * <p>
+     * <strong>Note:</strong> In order to access the windows your service has
+     * to declare the capability to retrieve window content by setting the
+     * {@link android.R.styleable#AccessibilityService_canRetrieveWindowContent}
+     * property in its meta-data. For details refer to {@link #SERVICE_META_DATA}.
+     * Also the service has to opt-in to retrieve the interactive windows by
+     * setting the {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS}
+     * flag.Otherwise, the search will be performed only in the active window.
+     * </p>
+     *
+     * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
+     *         {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
+     * @return The node info of the focused view or null.
+     *
+     * @see AccessibilityNodeInfo#FOCUS_INPUT
+     * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
+     */
+    public AccessibilityNodeInfo findFocus(int focus) {
+        return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
+                AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
+    }
+
+    /**
      * Gets the an {@link AccessibilityServiceInfo} describing this
      * {@link AccessibilityService}. This method is useful if one wants
      * to change some of the dynamically configurable properties at
diff --git a/core/java/android/alsa/AlsaCardsParser.java b/core/java/android/alsa/AlsaCardsParser.java
new file mode 100644
index 0000000..f9af979
--- /dev/null
+++ b/core/java/android/alsa/AlsaCardsParser.java
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide Retrieves information from an ALSA "cards" file.
+ */
+public class AlsaCardsParser {
+    private static final String TAG = "AlsaCardsParser";
+
+    private static LineTokenizer tokenizer_ = new LineTokenizer(" :[]");
+
+    public class AlsaCardRecord {
+        public int mCardNum = -1;
+        public String mField1 = "";
+        public String mCardName = "";
+        public String mCardDescription = "";
+
+        public AlsaCardRecord() {}
+
+        public boolean parse(String line, int lineIndex) {
+            int tokenIndex = 0;
+            int delimIndex = 0;
+            if (lineIndex == 0) {
+                // line # (skip)
+                tokenIndex = tokenizer_.nextToken(line, tokenIndex);
+                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+
+                // mField1
+                tokenIndex = tokenizer_.nextToken(line, delimIndex);
+                delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+                mField1 = line.substring(tokenIndex, delimIndex);
+
+                // mCardName
+                tokenIndex = tokenizer_.nextToken(line, delimIndex);
+                // delimIndex = tokenizer_.nextDelimiter(line, tokenIndex);
+                mCardName = line.substring(tokenIndex);
+                // done
+              } else if (lineIndex == 1) {
+                  tokenIndex = tokenizer_.nextToken(line, 0);
+                  if (tokenIndex != -1) {
+                      mCardDescription = line.substring(tokenIndex);
+                  }
+            }
+
+            return true;
+        }
+
+        public String textFormat() {
+          return mCardName + " : " + mCardDescription;
+        }
+    }
+
+    private Vector<AlsaCardRecord> cardRecords_ = new Vector<AlsaCardRecord>();
+
+    public void scan() {
+          cardRecords_.clear();
+          final String cardsFilePath = "/proc/asound/cards";
+          File cardsFile = new File(cardsFilePath);
+          try {
+              FileReader reader = new FileReader(cardsFile);
+              BufferedReader bufferedReader = new BufferedReader(reader);
+              String line = "";
+              while ((line = bufferedReader.readLine()) != null) {
+                  AlsaCardRecord cardRecord = new AlsaCardRecord();
+                  cardRecord.parse(line, 0);
+                  cardRecord.parse(line = bufferedReader.readLine(), 1);
+                  cardRecords_.add(cardRecord);
+              }
+              reader.close();
+          } catch (FileNotFoundException e) {
+              e.printStackTrace();
+          } catch (IOException e) {
+              e.printStackTrace();
+          }
+      }
+
+      public AlsaCardRecord getCardRecordAt(int index) {
+          return cardRecords_.get(index);
+      }
+
+      public int getNumCardRecords() {
+          return cardRecords_.size();
+      }
+
+    public void Log() {
+      int numCardRecs = getNumCardRecords();
+      for (int index = 0; index < numCardRecs; ++index) {
+          Slog.w(TAG, "usb:" + getCardRecordAt(index).textFormat());
+      }
+    }
+
+    public AlsaCardsParser() {}
+}
diff --git a/core/java/android/alsa/AlsaDevicesParser.java b/core/java/android/alsa/AlsaDevicesParser.java
new file mode 100644
index 0000000..094c8a2
--- /dev/null
+++ b/core/java/android/alsa/AlsaDevicesParser.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.alsascan;
+
+import android.util.Slog;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Vector;
+
+/**
+ * @hide
+ * Retrieves information from an ALSA "devices" file.
+ */
+public class AlsaDevicesParser {
+    private static final String TAG = "AlsaDevicesParser";
+
+    private static final int kIndex_CardDeviceField = 5;
+    private static final int kStartIndex_CardNum = 6;
+    private static final int kEndIndex_CardNum = 8; // one past
+    private static final int kStartIndex_DeviceNum = 9;
+    private static final int kEndIndex_DeviceNum = 11; // one past
+    private static final int kStartIndex_Type = 14;
+
+    private static LineTokenizer mTokenizer = new LineTokenizer(" :[]-");
+
+    private boolean mHasCaptureDevices = false;
+    private boolean mHasPlaybackDevices = false;
+    private boolean mHasMIDIDevices = false;
+
+    public class AlsaDeviceRecord {
+        public static final int kDeviceType_Unknown = -1;
+        public static final int kDeviceType_Audio = 0;
+        public static final int kDeviceType_Control = 1;
+        public static final int kDeviceType_MIDI = 2;
+
+        public static final int kDeviceDir_Unknown = -1;
+        public static final int kDeviceDir_Capture = 0;
+        public static final int kDeviceDir_Playback = 1;
+
+        int mCardNum = -1;
+        int mDeviceNum = -1;
+        int mDeviceType = kDeviceType_Unknown;
+        int mDeviceDir = kDeviceDir_Unknown;
+
+        public AlsaDeviceRecord() {
+        }
+
+        public boolean parse(String line) {
+            // "0123456789012345678901234567890"
+            // "  2: [ 0-31]: digital audio playback"
+            // "  3: [ 0-30]: digital audio capture"
+            // " 35: [ 1]   : control"
+            // " 36: [ 2- 0]: raw midi"
+
+            final int kToken_LineNum = 0;
+            final int kToken_CardNum = 1;
+            final int kToken_DeviceNum = 2;
+            final int kToken_Type0 = 3; // "digital", "control", "raw"
+            final int kToken_Type1 = 4; // "audio", "midi"
+            final int kToken_Type2 = 5; // "capture", "playback"
+
+            int tokenOffset = 0;
+            int delimOffset = 0;
+            int tokenIndex = kToken_LineNum;
+            while (true) {
+                tokenOffset = mTokenizer.nextToken(line, delimOffset);
+                if (tokenOffset == LineTokenizer.kTokenNotFound) {
+                    break; // bail
+                }
+                delimOffset = mTokenizer.nextDelimiter(line, tokenOffset);
+                if (delimOffset == LineTokenizer.kTokenNotFound) {
+                    delimOffset = line.length();
+                }
+                String token = line.substring(tokenOffset, delimOffset);
+
+                switch (tokenIndex) {
+                case kToken_LineNum:
+                    // ignore
+                    break;
+
+                case kToken_CardNum:
+                    mCardNum = Integer.parseInt(token);
+                    if (line.charAt(delimOffset) != '-') {
+                        tokenIndex++; // no device # in the token stream
+                    }
+                    break;
+
+                case kToken_DeviceNum:
+                    mDeviceNum = Integer.parseInt(token);
+                    break;
+
+                case kToken_Type0:
+                    if (token.equals("digital")) {
+                        // NOP
+                    } else if (token.equals("control")) {
+                        mDeviceType = kDeviceType_Control;
+                    } else if (token.equals("raw")) {
+                        // NOP
+                    }
+                    break;
+
+                case kToken_Type1:
+                    if (token.equals("audio")) {
+                        mDeviceType = kDeviceType_Audio;
+                    } else if (token.equals("midi")) {
+                        mDeviceType = kDeviceType_MIDI;
+                        mHasMIDIDevices = true;
+                    }
+                    break;
+
+                case kToken_Type2:
+                    if (token.equals("capture")) {
+                        mDeviceDir = kDeviceDir_Capture;
+                        mHasCaptureDevices = true;
+                    } else if (token.equals("playback")) {
+                        mDeviceDir = kDeviceDir_Playback;
+                        mHasPlaybackDevices = true;
+                    }
+                    break;
+                } // switch (tokenIndex)
+
+                tokenIndex++;
+            } // while (true)
+
+            return true;
+        } // parse()
+
+        public String textFormat() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("[" + mCardNum + ":" + mDeviceNum + "]");
+
+            switch (mDeviceType) {
+            case kDeviceType_Unknown:
+                sb.append(" N/A");
+                break;
+            case kDeviceType_Audio:
+                sb.append(" Audio");
+                break;
+            case kDeviceType_Control:
+                sb.append(" Control");
+                break;
+            case kDeviceType_MIDI:
+                sb.append(" MIDI");
+                break;
+            }
+
+            switch (mDeviceDir) {
+            case kDeviceDir_Unknown:
+                sb.append(" N/A");
+                break;
+            case kDeviceDir_Capture:
+                sb.append(" Capture");
+                break;
+            case kDeviceDir_Playback:
+                sb.append(" Playback");
+                break;
+            }
+
+            return sb.toString();
+        }
+    }
+
+    private Vector<AlsaDeviceRecord>
+            deviceRecords_ = new Vector<AlsaDeviceRecord>();
+
+    private boolean isLineDeviceRecord(String line) {
+        return line.charAt(kIndex_CardDeviceField) == '[';
+    }
+
+    public AlsaDevicesParser() {
+    }
+
+    public int getNumDeviceRecords() {
+        return deviceRecords_.size();
+    }
+
+    public AlsaDeviceRecord getDeviceRecordAt(int index) {
+        return deviceRecords_.get(index);
+    }
+
+    public void Log() {
+        int numDevRecs = getNumDeviceRecords();
+        for (int index = 0; index < numDevRecs; ++index) {
+            Slog.w(TAG, "usb:" + getDeviceRecordAt(index).textFormat());
+        }
+    }
+
+    public boolean hasPlaybackDevices() {
+        return mHasPlaybackDevices;
+    }
+
+    public boolean hasPlaybackDevices(int card) {
+        for (int index = 0; index < deviceRecords_.size(); index++) {
+            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
+            if (deviceRecord.mCardNum == card &&
+                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
+                deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Playback) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean hasCaptureDevices() {
+        return mHasCaptureDevices;
+    }
+
+    public boolean hasCaptureDevices(int card) {
+        for (int index = 0; index < deviceRecords_.size(); index++) {
+            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
+            if (deviceRecord.mCardNum == card &&
+                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_Audio &&
+                deviceRecord.mDeviceDir == AlsaDeviceRecord.kDeviceDir_Capture) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public boolean hasMIDIDevices() {
+        return mHasMIDIDevices;
+    }
+
+    public boolean hasMIDIDevices(int card) {
+        for (int index = 0; index < deviceRecords_.size(); index++) {
+            AlsaDeviceRecord deviceRecord = deviceRecords_.get(index);
+            if (deviceRecord.mCardNum == card &&
+                deviceRecord.mDeviceType == AlsaDeviceRecord.kDeviceType_MIDI) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    public void scan() {
+        deviceRecords_.clear();
+
+        final String devicesFilePath = "/proc/asound/devices";
+        File devicesFile = new File(devicesFilePath);
+        try {
+            FileReader reader = new FileReader(devicesFile);
+            BufferedReader bufferedReader = new BufferedReader(reader);
+            String line = "";
+            while ((line = bufferedReader.readLine()) != null) {
+                if (isLineDeviceRecord(line)) {
+                    AlsaDeviceRecord deviceRecord = new AlsaDeviceRecord();
+                    deviceRecord.parse(line);
+                    deviceRecords_.add(deviceRecord);
+                }
+            }
+            reader.close();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+} // class AlsaDevicesParser
+
diff --git a/core/java/android/alsa/LineTokenizer.java b/core/java/android/alsa/LineTokenizer.java
new file mode 100644
index 0000000..c138fc5
--- /dev/null
+++ b/core/java/android/alsa/LineTokenizer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.alsascan;
+
+/**
+ * @hide
+ * Breaks lines in an ALSA "cards" or "devices" file into tokens.
+ * TODO(pmclean) Look into replacing this with String.split().
+ */
+public class LineTokenizer {
+    public static final int kTokenNotFound = -1;
+
+    private String mDelimiters = "";
+
+    public LineTokenizer(String delimiters) {
+        mDelimiters = delimiters;
+    }
+
+    int nextToken(String line, int startIndex) {
+        int len = line.length();
+        int offset = startIndex;
+        for (; offset < len; offset++) {
+            if (mDelimiters.indexOf(line.charAt(offset)) == -1) {
+                // past a delimiter
+                break;
+            }
+      }
+
+      return offset < len ? offset : kTokenNotFound;
+    }
+
+    int nextDelimiter(String line, int startIndex) {
+        int len = line.length();
+        int offset = startIndex;
+        for (; offset < len; offset++) {
+            if (mDelimiters.indexOf(line.charAt(offset)) != -1) {
+                // past a delimiter
+                break;
+            }
+        }
+
+      return offset < len ? offset : kTokenNotFound;
+    }
+}
diff --git a/core/java/android/app/ActionBar.java b/core/java/android/app/ActionBar.java
index 34b0f3a..04f62e3 100644
--- a/core/java/android/app/ActionBar.java
+++ b/core/java/android/app/ActionBar.java
@@ -949,10 +949,6 @@
     }
 
     /** @hide */
-    public void captureSharedElements(Map<String, View> sharedElements) {
-    }
-
-    /** @hide */
     public ActionMode startActionMode(ActionMode.Callback callback) {
         return null;
     }
@@ -1239,6 +1235,8 @@
 
         public LayoutParams(int width, int height, int gravity) {
             super(width, height);
+
+            this.gravity = gravity;
         }
 
         public LayoutParams(int gravity) {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index b18eb98..8981c88 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -18,11 +18,11 @@
 
 import android.annotation.NonNull;
 import android.transition.Scene;
-import android.transition.Transition;
 import android.transition.TransitionManager;
 import android.util.ArrayMap;
 import android.util.SuperNotCalledException;
 import android.widget.Toolbar;
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.WindowDecorActionBar;
 import com.android.internal.app.ToolbarActionBar;
 import com.android.internal.policy.PolicyManager;
@@ -727,6 +727,8 @@
     /*package*/ ActionBar mActionBar = null;
     private boolean mEnableDefaultActionBarUp;
 
+    private VoiceInteractor mVoiceInteractor;
+
     private CharSequence mTitle;
     private int mTitleColor = 0;
 
@@ -773,6 +775,8 @@
 
     private Thread mUiThread;
     final Handler mHandler = new Handler();
+    private ActivityOptions mCalledActivityOptions;
+    private EnterTransitionCoordinator mEnterTransitionCoordinator;
 
     /** Return the intent that started this activity. */
     public Intent getIntent() {
@@ -1026,6 +1030,9 @@
             mTitleReady = true;
             onTitleChanged(getTitle(), getTitleColor());
         }
+        if (mEnterTransitionCoordinator != null) {
+            mEnterTransitionCoordinator.readyToEnter();
+        }
         mCalled = true;
     }
 
@@ -1106,6 +1113,7 @@
     protected void onResume() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onResume " + this);
         getApplication().dispatchActivityResumed(this);
+        mCalledActivityOptions = null;
         mCalled = true;
     }
 
@@ -1129,6 +1137,23 @@
     }
 
     /**
+     * Check whether this activity is running as part of a voice interaction with the user.
+     * If true, it should perform its interaction with the user through the
+     * {@link VoiceInteractor} returned by {@link #getVoiceInteractor}.
+     */
+    public boolean isVoiceInteraction() {
+        return mVoiceInteractor != null;
+    }
+
+    /**
+     * Retrieve the active {@link VoiceInteractor} that the user is going through to
+     * interact with this activity.
+     */
+    public VoiceInteractor getVoiceInteractor() {
+        return mVoiceInteractor;
+    }
+
+    /**
      * This is called for activities that set launchMode to "singleTop" in
      * their package, or if a client used the {@link Intent#FLAG_ACTIVITY_SINGLE_TOP}
      * flag when calling {@link #startActivity}.  In either case, when the
@@ -1398,8 +1423,9 @@
     protected void onStop() {
         if (DEBUG_LIFECYCLE) Slog.v(TAG, "onStop " + this);
         if (mActionBar != null) mActionBar.setShowHideAnimationEnabled(false);
-        if (mWindow != null) {
-            mWindow.restoreViewVisibilityAfterTransitionToCallee();
+        if (mCalledActivityOptions != null) {
+            mCalledActivityOptions.dispatchActivityStopped();
+            mCalledActivityOptions = null;
         }
         getApplication().dispatchActivityStopped(this);
         mTranslucentCallback = null;
@@ -3484,7 +3510,7 @@
     public void startActivityForResult(Intent intent, int requestCode) {
         Bundle options = null;
         if (mWindow.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
-            options = ActivityOptions.makeSceneTransitionAnimation().toBundle();
+            options = ActivityOptions.makeSceneTransitionAnimation(mWindow, null).toBundle();
         }
         startActivityForResult(intent, requestCode, options);
     }
@@ -3526,14 +3552,8 @@
     public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
         if (options != null) {
             ActivityOptions activityOptions = new ActivityOptions(options);
-            if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
-                if (mActionBar != null) {
-                    ArrayMap<String, View> sharedElementMap = new ArrayMap<String, View>();
-                    mActionBar.captureSharedElements(sharedElementMap);
-                    activityOptions.addSharedElements(sharedElementMap);
-                }
-                options = mWindow.startExitTransitionToCallee(options);
-            }
+            activityOptions.dispatchStartExit();
+            mCalledActivityOptions = activityOptions;
         }
         if (mParent == null) {
             Instrumentation.ActivityResult ar =
@@ -4314,11 +4334,10 @@
     }
 
     /**
-     * Call this when your activity is done and should be closed.  The
-     * ActivityResult is propagated back to whoever launched you via
-     * onActivityResult().
+     * Finishes the current activity and specifies whether to remove the task associated with this
+     * activity.
      */
-    public void finish() {
+    private void finish(boolean finishTask) {
         if (mParent == null) {
             int resultCode;
             Intent resultData;
@@ -4332,7 +4351,7 @@
                     resultData.prepareToLeaveProcess();
                 }
                 if (ActivityManagerNative.getDefault()
-                    .finishActivity(mToken, resultCode, resultData)) {
+                        .finishActivity(mToken, resultCode, resultData, finishTask)) {
                     mFinished = true;
                 }
             } catch (RemoteException e) {
@@ -4344,6 +4363,15 @@
     }
 
     /**
+     * Call this when your activity is done and should be closed.  The
+     * ActivityResult is propagated back to whoever launched you via
+     * onActivityResult().
+     */
+    public void finish() {
+        finish(false);
+    }
+
+    /**
      * Finish this activity as well as all activities immediately below it
      * in the current task that have the same affinity.  This is typically
      * used when an application can be launched on to another task (such as
@@ -4391,16 +4419,15 @@
      * to reverse its exit Transition. When the exit Transition completes,
      * {@link #finish()} is called. If no entry Transition was used, finish() is called
      * immediately and the Activity exit Transition is run.
-     * @see android.view.Window#setTriggerEarlySceneTransition(boolean, boolean)
-     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
+     * android.app.ActivityOptions.ActivityTransitionListener)
      */
     public void finishWithTransition() {
-        mWindow.startExitTransitionToCaller(new Runnable() {
-            @Override
-            public void run() {
-                finish();
-            }
-        });
+        if (mEnterTransitionCoordinator != null) {
+            mEnterTransitionCoordinator.startExit();
+        } else {
+            finish();
+        }
     }
 
     /**
@@ -4443,6 +4470,14 @@
     }
 
     /**
+     * Call this when your activity is done and should be closed and the task should be completely
+     * removed as a part of finishing the Activity.
+     */
+    public void finishAndRemoveTask() {
+        finish(true);
+    }
+
+    /**
      * Called when an activity you launched exits, giving you the requestCode
      * you started it with, the resultCode it returned, and any additional
      * data from it.  The <var>resultCode</var> will be
@@ -5346,6 +5381,21 @@
         }
     }
 
+    /**
+     * When {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
+     * android.app.ActivityOptions.ActivityTransitionListener)} was used to start an Activity,
+     * the Window will be triggered to enter with a Transition. <code>listener</code> allows
+     * The Activity to listen to events of the entering transition and control the mapping of
+     * shared elements. This requires {@link Window#FEATURE_CONTENT_TRANSITIONS}.
+     *
+     * @param listener Used to listen to events in the entering transition.
+     */
+    public void setActivityTransitionListener(ActivityOptions.ActivityTransitionListener listener) {
+        if (mEnterTransitionCoordinator != null) {
+            mEnterTransitionCoordinator.setActivityTransitionListener(listener);
+        }
+    }
+
     // ------------------ Internal API ------------------
     
     final void setParent(Activity parent) {
@@ -5367,7 +5417,7 @@
             NonConfigurationInstances lastNonConfigurationInstances,
             Configuration config) {
         attach(context, aThread, instr, token, ident, application, intent, info, title, parent, id,
-                lastNonConfigurationInstances, config, null);
+                lastNonConfigurationInstances, config, null, null);
     }
 
     final void attach(Context context, ActivityThread aThread,
@@ -5375,7 +5425,7 @@
             Application application, Intent intent, ActivityInfo info,
             CharSequence title, Activity parent, String id,
             NonConfigurationInstances lastNonConfigurationInstances,
-            Configuration config, Bundle options) {
+            Configuration config, Bundle options, IVoiceInteractor voiceInteractor) {
         attachBaseContext(context);
 
         mFragments.attachActivity(this, mContainer, null);
@@ -5403,6 +5453,8 @@
         mParent = parent;
         mEmbeddedID = id;
         mLastNonConfigurationInstances = lastNonConfigurationInstances;
+        mVoiceInteractor = voiceInteractor != null
+                ? new VoiceInteractor(this, this, voiceInteractor, Looper.myLooper()) : null;
 
         mWindow.setWindowManager(
                 (WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
@@ -5413,34 +5465,12 @@
         }
         mWindowManager = mWindow.getWindowManager();
         mCurrentConfig = config;
-        Window.SceneTransitionListener sceneTransitionListener
-                = new Window.SceneTransitionListener() {
-            @Override
-            public void nullPendingTransition() {
-                overridePendingTransition(0, 0);
+        if (options != null) {
+            ActivityOptions activityOptions = new ActivityOptions(options);
+            if (activityOptions.getAnimationType() == ActivityOptions.ANIM_SCENE_TRANSITION) {
+                mEnterTransitionCoordinator = activityOptions.createEnterActivityTransition(this);
             }
-
-            @Override
-            public void convertFromTranslucent() {
-                Activity.this.convertFromTranslucent();
-            }
-
-            @Override
-            public void convertToTranslucent() {
-                Activity.this.convertToTranslucent(null);
-            }
-
-            @Override
-            public void sharedElementStart(Transition transition) {
-                Activity.this.onCaptureSharedElementStart(transition);
-            }
-
-            @Override
-            public void sharedElementEnd() {
-                Activity.this.onCaptureSharedElementEnd();
-            }
-        };
-        mWindow.setTransitionOptions(options, sceneTransitionListener);
+        }
     }
 
     /** @hide */
@@ -5628,26 +5658,6 @@
     }
 
     /**
-     * Called when setting up Activity Scene transitions when the start state for shared
-     * elements has been captured. Override this method to modify the start position of shared
-     * elements for the entry Transition.
-     *
-     * @param transition The <code>Transition</code> being used to change
-     *                   bounds of shared elements in the source Activity to
-     *                   the bounds defined by the entering Scene.
-     */
-    public void onCaptureSharedElementStart(Transition transition) {
-    }
-
-    /**
-     * Called when setting up Activity Scene transitions when the final state for
-     * shared elements state has been captured. Override this method to modify the destination
-     * position of shared elements for the entry Transition.
-     */
-    public void onCaptureSharedElementEnd() {
-    }
-
-    /**
      * @hide
      */
     public final boolean isResumed() {
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index c027e99..9239faf 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -76,6 +76,13 @@
     public static final String META_HOME_ALTERNATE = "android.app.home.alternate";
 
     /**
+     * Result for IActivityManager.startActivity: trying to start an activity under voice
+     * control when that activity does not support the VOICE category.
+     * @hide
+     */
+    public static final int START_NOT_VOICE_COMPATIBLE = -7;
+
+    /**
      * Result for IActivityManager.startActivity: an error where the
      * start had to be canceled.
      * @hide
@@ -1620,13 +1627,6 @@
         public int lastTrimLevel;
 
         /**
-         * Constant for {@link #importance}: this is a persistent process.
-         * Only used when reporting to process observers.
-         * @hide
-         */
-        public static final int IMPORTANCE_PERSISTENT = 50;
-
-        /**
          * Constant for {@link #importance}: this process is running the
          * foreground UI.
          */
@@ -1741,9 +1741,16 @@
          */
         public int importanceReasonImportance;
 
+        /**
+         * Current process state, as per PROCESS_STATE_* constants.
+         * @hide
+         */
+        public int processState;
+
         public RunningAppProcessInfo() {
             importance = IMPORTANCE_FOREGROUND;
             importanceReasonCode = REASON_UNKNOWN;
+            processState = PROCESS_STATE_IMPORTANT_FOREGROUND;
         }
         
         public RunningAppProcessInfo(String pProcessName, int pPid, String pArr[]) {
@@ -1769,6 +1776,7 @@
             dest.writeInt(importanceReasonPid);
             ComponentName.writeToParcel(importanceReasonComponent, dest);
             dest.writeInt(importanceReasonImportance);
+            dest.writeInt(processState);
         }
 
         public void readFromParcel(Parcel source) {
@@ -1784,6 +1792,7 @@
             importanceReasonPid = source.readInt();
             importanceReasonComponent = ComponentName.readFromParcel(source);
             importanceReasonImportance = source.readInt();
+            processState = source.readInt();
         }
 
         public static final Creator<RunningAppProcessInfo> CREATOR = 
diff --git a/core/java/android/app/ActivityManagerNative.java b/core/java/android/app/ActivityManagerNative.java
index 9f1b56e..b1c37de 100644
--- a/core/java/android/app/ActivityManagerNative.java
+++ b/core/java/android/app/ActivityManagerNative.java
@@ -43,9 +43,11 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.StrictMode;
+import android.service.voice.IVoiceInteractionSession;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Singleton;
+import com.android.internal.app.IVoiceInteractor;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -242,6 +244,33 @@
             return true;
         }
 
+        case START_VOICE_ACTIVITY_TRANSACTION:
+        {
+            data.enforceInterface(IActivityManager.descriptor);
+            String callingPackage = data.readString();
+            int callingPid = data.readInt();
+            int callingUid = data.readInt();
+            Intent intent = Intent.CREATOR.createFromParcel(data);
+            String resolvedType = data.readString();
+            IVoiceInteractionSession session = IVoiceInteractionSession.Stub.asInterface(
+                    data.readStrongBinder());
+            IVoiceInteractor interactor = IVoiceInteractor.Stub.asInterface(
+                    data.readStrongBinder());
+            int startFlags = data.readInt();
+            String profileFile = data.readString();
+            ParcelFileDescriptor profileFd = data.readInt() != 0
+                    ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
+            Bundle options = data.readInt() != 0
+                    ? Bundle.CREATOR.createFromParcel(data) : null;
+            int userId = data.readInt();
+            int result = startVoiceActivity(callingPackage, callingPid, callingUid,
+                    intent, resolvedType, session, interactor, startFlags,
+                    profileFile, profileFd, options, userId);
+            reply.writeNoException();
+            reply.writeInt(result);
+            return true;
+        }
+
         case START_NEXT_MATCHING_ACTIVITY_TRANSACTION:
         {
             data.enforceInterface(IActivityManager.descriptor);
@@ -263,7 +292,8 @@
             if (data.readInt() != 0) {
                 resultData = Intent.CREATOR.createFromParcel(data);
             }
-            boolean res = finishActivity(token, resultCode, resultData);
+            boolean finishTask = (data.readInt() != 0);
+            boolean res = finishActivity(token, resultCode, resultData, finishTask);
             reply.writeNoException();
             reply.writeInt(res ? 1 : 0);
             return true;
@@ -2029,7 +2059,7 @@
             data.enforceInterface(IActivityManager.descriptor);
             IBinder parentActivityToken = data.readStrongBinder();
             IActivityContainerCallback callback =
-                    (IActivityContainerCallback) data.readStrongBinder();
+                    IActivityContainerCallback.Stub.asInterface(data.readStrongBinder());
             IActivityContainer activityContainer =
                     createActivityContainer(parentActivityToken, callback);
             reply.writeNoException();
@@ -2322,6 +2352,42 @@
         data.recycle();
         return result;
     }
+    public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
+            Intent intent, String resolvedType, IVoiceInteractionSession session,
+            IVoiceInteractor interactor, int startFlags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException {
+        Parcel data = Parcel.obtain();
+        Parcel reply = Parcel.obtain();
+        data.writeInterfaceToken(IActivityManager.descriptor);
+        data.writeString(callingPackage);
+        data.writeInt(callingPid);
+        data.writeInt(callingUid);
+        intent.writeToParcel(data, 0);
+        data.writeString(resolvedType);
+        data.writeStrongBinder(session.asBinder());
+        data.writeStrongBinder(interactor.asBinder());
+        data.writeInt(startFlags);
+        data.writeString(profileFile);
+        if (profileFd != null) {
+            data.writeInt(1);
+            profileFd.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
+        } else {
+            data.writeInt(0);
+        }
+        if (options != null) {
+            data.writeInt(1);
+            options.writeToParcel(data, 0);
+        } else {
+            data.writeInt(0);
+        }
+        data.writeInt(userId);
+        mRemote.transact(START_VOICE_ACTIVITY_TRANSACTION, data, reply, 0);
+        reply.readException();
+        int result = reply.readInt();
+        reply.recycle();
+        data.recycle();
+        return result;
+    }
     public boolean startNextMatchingActivity(IBinder callingActivity,
             Intent intent, Bundle options) throws RemoteException {
         Parcel data = Parcel.obtain();
@@ -2342,7 +2408,7 @@
         data.recycle();
         return result != 0;
     }
-    public boolean finishActivity(IBinder token, int resultCode, Intent resultData)
+    public boolean finishActivity(IBinder token, int resultCode, Intent resultData, boolean finishTask)
             throws RemoteException {
         Parcel data = Parcel.obtain();
         Parcel reply = Parcel.obtain();
@@ -2355,6 +2421,7 @@
         } else {
             data.writeInt(0);
         }
+        data.writeInt(finishTask ? 1 : 0);
         mRemote.transact(FINISH_ACTIVITY_TRANSACTION, data, reply, 0);
         reply.readException();
         boolean res = reply.readInt() != 0;
@@ -4744,7 +4811,7 @@
         Parcel reply = Parcel.obtain();
         data.writeInterfaceToken(IActivityManager.descriptor);
         data.writeStrongBinder(parentActivityToken);
-        data.writeStrongBinder((IBinder)callback);
+        data.writeStrongBinder(callback == null ? null : callback.asBinder());
         mRemote.transact(CREATE_ACTIVITY_CONTAINER_TRANSACTION, data, reply, 0);
         reply.readException();
         final int result = reply.readInt();
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index 4384580..a49359f 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -20,16 +20,16 @@
 import android.graphics.Bitmap;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.transition.Transition;
-import android.util.Log;
+import android.util.ArrayMap;
 import android.util.Pair;
 import android.view.View;
+import android.view.Window;
 
-import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -108,23 +108,6 @@
     private static final String KEY_TRANSITION_COMPLETE_LISTENER
             = "android:transitionCompleteListener";
 
-    /**
-     * For Activity transitions, the called Activity's listener to receive calls
-     * when transitions complete.
-     */
-    private static final String KEY_TRANSITION_TARGET_LISTENER = "android:transitionTargetListener";
-
-    /**
-     * The names of shared elements that are transitioned to the started Activity.
-     * This is also the name of shared elements that the started Activity accepted.
-     */
-    private static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names";
-
-    /**
-     * The shared elements names of the views in the calling Activity.
-     */
-    private static final String KEY_LOCAL_ELEMENT_NAMES = "android:local_element_names";
-
     /** @hide */
     public static final int ANIM_NONE = 0;
     /** @hide */
@@ -138,11 +121,6 @@
     /** @hide */
     public static final int ANIM_SCENE_TRANSITION = 5;
 
-    private static final int MSG_SET_LISTENER = 100;
-    private static final int MSG_HIDE_SHARED_ELEMENTS = 101;
-    private static final int MSG_PREPARE_RESTORE = 102;
-    private static final int MSG_RESTORE = 103;
-
     private String mPackageName;
     private int mAnimationType = ANIM_NONE;
     private int mCustomEnterResId;
@@ -153,9 +131,7 @@
     private int mStartWidth;
     private int mStartHeight;
     private IRemoteCallback mAnimationStartedListener;
-    private ResultReceiver mTransitionCompleteListener;
-    private ArrayList<String> mSharedElementNames;
-    private ArrayList<String> mLocalElementNames;
+    private ResultReceiver mExitReceiver;
 
     /**
      * Create an ActivityOptions specifying a custom animation to run when
@@ -231,12 +207,6 @@
         void onAnimationStarted();
     }
 
-    /** @hide */
-    public interface ActivityTransitionTarget {
-        void sharedElementTransitionComplete(Bundle transitionArgs);
-        void exitTransitionComplete();
-    }
-
     /**
      * Create an ActivityOptions specifying an animation where the new
      * activity is scaled from a small originating area of the screen to
@@ -357,49 +327,53 @@
     /**
      * Create an ActivityOptions to transition between Activities using cross-Activity scene
      * animations. This method carries the position of one shared element to the started Activity.
+     * The position of <code>sharedElement</code> will be used as the epicenter for the
+     * exit Transition. The position of the shared element in the launched Activity will be the
+     * epicenter of its entering Transition.
      *
      * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
      * enabled on the calling Activity to cause an exit transition. The same must be in
      * the called Activity to get an entering transition.</p>
+     * @param window The window containing shared elements.
      * @param sharedElement The View to transition to the started Activity. sharedElement must
      *                      have a non-null sharedElementName.
      * @param sharedElementName The shared element name as used in the target Activity. This may
      *                          be null if it has the same name as sharedElement.
      * @return Returns a new ActivityOptions object that you can use to
      *         supply these options as the options Bundle when starting an activity.
+     * @see android.transition.Transition#setEpicenterCallback(
+     *          android.transition.Transition.EpicenterCallback)
      */
-    public static ActivityOptions makeSceneTransitionAnimation(View sharedElement,
-            String sharedElementName) {
-        return makeSceneTransitionAnimation(
-                new Pair<View, String>(sharedElement, sharedElementName));
+    public static ActivityOptions makeSceneTransitionAnimation(Window window,
+            View sharedElement, String sharedElementName) {
+        return makeSceneTransitionAnimation(window,
+                new SharedElementMappingListener(sharedElement, sharedElementName));
     }
 
     /**
      * Create an ActivityOptions to transition between Activities using cross-Activity scene
      * animations. This method carries the position of multiple shared elements to the started
-     * Activity.
+     * Activity. The position of the first element in the value returned from
+     * {@link android.app.ActivityOptions.ActivityTransitionListener#getSharedElementsMapping()}
+     * will be used as the epicenter for the exit Transition. The position of the associated
+     * shared element in the launched Activity will be the epicenter of its entering Transition.
      *
      * <p>This requires {@link android.view.Window#FEATURE_CONTENT_TRANSITIONS} to be
      * enabled on the calling Activity to cause an exit transition. The same must be in
      * the called Activity to get an entering transition.</p>
-     * @param sharedElements The View to transition to the started Activity along with the
-     *                       shared element name as used in the started Activity. The view
-     *                       must have a non-null sharedElementName.
+     * @param window The window containing shared elements.
+     * @param listener The listener to use to monitor activity transition events.
      * @return Returns a new ActivityOptions object that you can use to
      *         supply these options as the options Bundle when starting an activity.
+     * @see android.transition.Transition#setEpicenterCallback(
+     *          android.transition.Transition.EpicenterCallback)
      */
-    public static ActivityOptions makeSceneTransitionAnimation(
-            Pair<View, String>... sharedElements) {
+    public static ActivityOptions makeSceneTransitionAnimation(Window window,
+            ActivityTransitionListener listener) {
         ActivityOptions opts = new ActivityOptions();
         opts.mAnimationType = ANIM_SCENE_TRANSITION;
-        opts.mSharedElementNames = new ArrayList<String>();
-        opts.mLocalElementNames = new ArrayList<String>();
-
-        if (sharedElements != null) {
-            for (Pair<View, String> sharedElement : sharedElements) {
-                opts.addSharedElement(sharedElement.first, sharedElement.second);
-            }
-        }
+        ExitTransitionCoordinator exit = new ExitTransitionCoordinator(window, listener);
+        opts.mExitReceiver = exit;
         return opts;
     }
 
@@ -435,9 +409,7 @@
                 break;
 
             case ANIM_SCENE_TRANSITION:
-                mTransitionCompleteListener = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
-                mSharedElementNames = opts.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
-                mLocalElementNames = opts.getStringArrayList(KEY_LOCAL_ELEMENT_NAMES);
+                mExitReceiver = opts.getParcelable(KEY_TRANSITION_COMPLETE_LISTENER);
                 break;
         }
     }
@@ -493,50 +465,16 @@
     }
 
     /** @hide */
-    public ArrayList<String> getSharedElementNames() { return mSharedElementNames; }
-
-    /** @hide */
-    public ArrayList<String> getLocalElementNames() { return mLocalElementNames; }
-
-    /** @hide */
-    public void dispatchSceneTransitionStarted(final ActivityTransitionTarget target,
-            ArrayList<String> sharedElementNames) {
-        if (mTransitionCompleteListener != null) {
-            IRemoteCallback callback = new IRemoteCallback.Stub() {
-                @Override
-                public void sendResult(Bundle data) throws RemoteException {
-                    if (data == null) {
-                        target.exitTransitionComplete();
-                    } else {
-                        target.sharedElementTransitionComplete(data);
-                    }
-                }
-            };
-            Bundle bundle = new Bundle();
-            bundle.putBinder(KEY_TRANSITION_TARGET_LISTENER, callback.asBinder());
-            bundle.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, sharedElementNames);
-            mTransitionCompleteListener.send(MSG_SET_LISTENER, bundle);
+    public void dispatchActivityStopped() {
+        if (mExitReceiver != null) {
+            mExitReceiver.send(ActivityTransitionCoordinator.MSG_ACTIVITY_STOPPED, null);
         }
     }
 
     /** @hide */
-    public void dispatchSharedElementsReady() {
-        if (mTransitionCompleteListener != null) {
-            mTransitionCompleteListener.send(MSG_HIDE_SHARED_ELEMENTS, null);
-        }
-    }
-
-    /** @hide */
-    public void dispatchPrepareRestore() {
-        if (mTransitionCompleteListener != null) {
-            mTransitionCompleteListener.send(MSG_PREPARE_RESTORE, null);
-        }
-    }
-
-    /** @hide */
-    public void dispatchRestore(Bundle sharedElementsArgs) {
-        if (mTransitionCompleteListener != null) {
-            mTransitionCompleteListener.send(MSG_RESTORE, sharedElementsArgs);
+    public void dispatchStartExit() {
+        if (mExitReceiver != null) {
+            mExitReceiver.send(ActivityTransitionCoordinator.MSG_START_EXIT_TRANSITION, null);
         }
     }
 
@@ -557,6 +495,15 @@
         }
     }
 
+    /** @hide */
+    public EnterTransitionCoordinator createEnterActivityTransition(Activity activity) {
+        EnterTransitionCoordinator coordinator = null;
+        if (mAnimationType == ANIM_SCENE_TRANSITION) {
+            coordinator = new EnterTransitionCoordinator(activity, mExitReceiver);
+        }
+        return coordinator;
+    }
+
     /**
      * Update the current values in this ActivityOptions from those supplied
      * in <var>otherOptions</var>.  Any values
@@ -566,8 +513,7 @@
         if (otherOptions.mPackageName != null) {
             mPackageName = otherOptions.mPackageName;
         }
-        mSharedElementNames = null;
-        mLocalElementNames = null;
+        mExitReceiver = null;
         switch (otherOptions.mAnimationType) {
             case ANIM_CUSTOM:
                 mAnimationType = otherOptions.mAnimationType;
@@ -581,7 +527,6 @@
                     }
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
-                mTransitionCompleteListener = null;
                 break;
             case ANIM_SCALE_UP:
                 mAnimationType = otherOptions.mAnimationType;
@@ -596,7 +541,6 @@
                     }
                 }
                 mAnimationStartedListener = null;
-                mTransitionCompleteListener = null;
                 break;
             case ANIM_THUMBNAIL_SCALE_UP:
             case ANIM_THUMBNAIL_SCALE_DOWN:
@@ -611,15 +555,12 @@
                     }
                 }
                 mAnimationStartedListener = otherOptions.mAnimationStartedListener;
-                mTransitionCompleteListener = null;
                 break;
             case ANIM_SCENE_TRANSITION:
                 mAnimationType = otherOptions.mAnimationType;
-                mTransitionCompleteListener = otherOptions.mTransitionCompleteListener;
+                mExitReceiver = otherOptions.mExitReceiver;
                 mThumbnail = null;
                 mAnimationStartedListener = null;
-                mSharedElementNames = otherOptions.mSharedElementNames;
-                mLocalElementNames = otherOptions.mLocalElementNames;
                 break;
         }
     }
@@ -663,11 +604,9 @@
                 break;
             case ANIM_SCENE_TRANSITION:
                 b.putInt(KEY_ANIM_TYPE, mAnimationType);
-                if (mTransitionCompleteListener != null) {
-                    b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mTransitionCompleteListener);
+                if (mExitReceiver != null) {
+                    b.putParcelable(KEY_TRANSITION_COMPLETE_LISTENER, mExitReceiver);
                 }
-                b.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, mSharedElementNames);
-                b.putStringArrayList(KEY_LOCAL_ELEMENT_NAMES, mLocalElementNames);
                 break;
         }
         return b;
@@ -687,130 +626,126 @@
         return null;
     }
 
-    /** @hide */
-    public void addSharedElements(Map<String, View> sharedElements) {
-        for (Map.Entry<String, View> entry : sharedElements.entrySet()) {
-            addSharedElement(entry.getValue(), entry.getKey());
+    /**
+     * Listener provided in
+     * {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
+     * android.app.ActivityOptions.ActivityTransitionListener)} or in
+     * {@link android.app.Activity#setActivityTransitionListener(
+     * android.app.ActivityOptions.ActivityTransitionListener)} to monitor the Activity transitions.
+     * The events can be used to customize or override Activity Transition behavior.
+     */
+    public static class ActivityTransitionListener {
+        /**
+         * Called when the enter Transition is ready to start, but hasn't started yet. If
+         * {@link android.view.Window#getEnterTransition()} is non-null,
+         * The entering views will be {@link View#INVISIBLE}.
+         */
+        public void onEnterReady() {}
+
+        /**
+         * Called when the remote exiting transition completes.
+         */
+        public void onRemoteExitComplete() {}
+
+        /**
+         * Called when the start state for shared elements is captured on enter.
+         *
+         * @param sharedElementNames The names of the shared elements that were accepted into
+         *                           the View hierarchy.
+         * @param sharedElements The shared elements that are part of the View hierarchy.
+         * @param sharedElementSnapshots The Views containing snap shots of the shared element
+         *                               from the launching Window. These elements will not
+         *                               be part of the scene, but will be positioned relative
+         *                               to the Window decor View.
+         */
+        public void onCaptureSharedElementStart(List<String> sharedElementNames,
+                List<View> sharedElements, List<View> sharedElementSnapshots) {}
+
+        /**
+         * Called when the end state for shared elements is captured on enter.
+         *
+         * @param sharedElementNames The names of the shared elements that were accepted into
+         *                           the View hierarchy.
+         * @param sharedElements The shared elements that are part of the View hierarchy.
+         * @param sharedElementSnapshots The Views containing snap shots of the shared element
+         *                               from the launching Window. These elements will not
+         *                               be part of the scene, but will be positioned relative
+         *                               to the Window decor View.
+         */
+        public void onCaptureSharedElementEnd(List<String> sharedElementNames,
+                List<View> sharedElements, List<View> sharedElementSnapshots) {}
+
+        /**
+         * Called when the enter Transition has been started.
+         * @param sharedElementNames The names of shared elements that were transferred.
+         * @param sharedElements The shared elements that were transferred.
+         */
+        public void onStartEnterTransition(List<String> sharedElementNames,
+                List<View> sharedElements) {}
+
+        /**
+         * Called when the exit Transition has been started.
+         * @param sharedElementNames The names of all shared elements that will be transferred.
+         * @param sharedElements All shared elements that will be transferred.
+         */
+        public void onStartExitTransition(List<String> sharedElementNames,
+                List<View> sharedElements) {}
+
+        /**
+         * Called when the exiting shared element transition completes.
+         */
+        public void onSharedElementExitTransitionComplete() {}
+
+        /**
+         * Called on exit when the shared element has been transferred.
+         * @param sharedElementNames The names of all shared elements that were transferred.
+         * @param sharedElements All shared elements that will were transferred.
+         */
+        public void onSharedElementTransferred(List<String> sharedElementNames,
+                List<View> sharedElements) {}
+
+        /**
+         * Called when the exit transition has completed.
+         */
+        public void onExitTransitionComplete() {}
+
+        /**
+         * Returns a mapping from a View in the View hierarchy to the shared element name used
+         * in the call. This is called twice -- once when the view is
+         * entering and again when it exits. A null return value indicates that the
+         * View hierachy can be trusted without any remapping.
+         * @return A map from a View in the hierarchy to the shared element name used in the
+         * call.
+         */
+        public Pair<View, String>[] getSharedElementsMapping() { return null; }
+
+        /**
+         * Returns <code>true</code> if the ActivityTransitionListener will handle removing
+         * rejected shared elements from the scene. If <code>false</code> is returned, a default
+         * animation will be used to remove the rejected shared elements from the scene.
+         *
+         * @param rejectedSharedElements Views containing visual information of shared elements
+         *                               that are not part of the entering scene. These Views
+         *                               are positioned relative to the Window decor View.
+         * @return <code>false</code> if the default animation should be used to remove the
+         * rejected shared elements from the scene or <code>true</code> if the listener provides
+         * custom handling.
+         */
+        public boolean handleRejectedSharedElements(List<View> rejectedSharedElements) {
+            return false;
         }
     }
 
-    /** @hide */
-    public void updateSceneTransitionAnimation(Transition exitTransition,
-            Transition sharedElementTransition, SharedElementSource sharedElementSource) {
-        mTransitionCompleteListener = new ExitTransitionListener(exitTransition,
-                sharedElementTransition, sharedElementSource);
-    }
+    private static class SharedElementMappingListener extends ActivityTransitionListener {
+        Pair<View, String>[] mSharedElementsMapping = new Pair[1];
 
-    private void addSharedElement(View view, String name) {
-        String sharedElementName = view.getSharedElementName();
-        if (name == null) {
-            name = sharedElementName;
-        }
-        mSharedElementNames.add(name);
-        mLocalElementNames.add(sharedElementName);
-    }
-
-    /** @hide */
-    public interface SharedElementSource {
-        Bundle getSharedElementExitState();
-        void acceptedSharedElements(ArrayList<String> sharedElementNames);
-        void hideSharedElements();
-        void restore(Bundle sharedElementState);
-        void prepareForRestore();
-    }
-
-    private static class ExitTransitionListener extends ResultReceiver
-            implements Transition.TransitionListener {
-        private boolean mSharedElementNotified;
-        private IRemoteCallback mTransitionCompleteCallback;
-        private boolean mExitComplete;
-        private boolean mSharedElementComplete;
-        private SharedElementSource mSharedElementSource;
-
-        public ExitTransitionListener(Transition exitTransition, Transition sharedElementTransition,
-                SharedElementSource sharedElementSource) {
-            super(null);
-            mSharedElementSource = sharedElementSource;
-            exitTransition.addListener(this);
-            sharedElementTransition.addListener(new Transition.TransitionListenerAdapter() {
-                @Override
-                public void onTransitionEnd(Transition transition) {
-                    mSharedElementComplete = true;
-                    notifySharedElement();
-                    transition.removeListener(this);
-                }
-            });
+        public SharedElementMappingListener(View view, String name) {
+            mSharedElementsMapping[0] = Pair.create(view, name);
         }
 
         @Override
-        protected void onReceiveResult(int resultCode, Bundle resultData) {
-            switch (resultCode) {
-                case MSG_SET_LISTENER:
-                    IBinder listener = resultData.getBinder(KEY_TRANSITION_TARGET_LISTENER);
-                    mTransitionCompleteCallback = IRemoteCallback.Stub.asInterface(listener);
-                    ArrayList<String> sharedElementNames
-                            = resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
-                    mSharedElementSource.acceptedSharedElements(sharedElementNames);
-                    notifySharedElement();
-                    notifyExit();
-                    break;
-                case MSG_HIDE_SHARED_ELEMENTS:
-                    mSharedElementSource.hideSharedElements();
-                    break;
-                case MSG_PREPARE_RESTORE:
-                    mSharedElementSource.prepareForRestore();
-                    break;
-                case MSG_RESTORE:
-                    mSharedElementSource.restore(resultData);
-                    break;
-            }
-        }
-
-        @Override
-        public void onTransitionStart(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionEnd(Transition transition) {
-            mExitComplete = true;
-            notifyExit();
-            transition.removeListener(this);
-        }
-
-        @Override
-        public void onTransitionCancel(Transition transition) {
-            onTransitionEnd(transition);
-        }
-
-        @Override
-        public void onTransitionPause(Transition transition) {
-        }
-
-        @Override
-        public void onTransitionResume(Transition transition) {
-        }
-
-        private void notifySharedElement() {
-            if (!mSharedElementNotified && mSharedElementComplete
-                    && mTransitionCompleteCallback != null) {
-                mSharedElementNotified = true;
-                try {
-                    Bundle sharedElementState = mSharedElementSource.getSharedElementExitState();
-                    mTransitionCompleteCallback.sendResult(sharedElementState);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Couldn't notify that the transition ended", e);
-                }
-            }
-        }
-
-        private void notifyExit() {
-            if (mExitComplete && mTransitionCompleteCallback != null) {
-                try {
-                    mTransitionCompleteCallback.sendResult(null);
-                } catch (RemoteException e) {
-                    Log.w(TAG, "Couldn't notify that the transition ended", e);
-                }
-            }
+        public Pair<View, String>[] getSharedElementsMapping() {
+            return mSharedElementsMapping;
         }
     }
 }
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 965f815..7dc21b4 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -94,6 +94,7 @@
 import android.renderscript.RenderScript;
 import android.security.AndroidKeyStoreProvider;
 
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.RuntimeInit;
 import com.android.internal.os.SamplingProfilerIntegration;
@@ -265,6 +266,7 @@
         IBinder token;
         int ident;
         Intent intent;
+        IVoiceInteractor voiceInteractor;
         Bundle state;
         Activity activity;
         Window window;
@@ -603,6 +605,7 @@
         // activity itself back to the activity manager. (matters more with ipc)
         public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
                 ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
+                IVoiceInteractor voiceInteractor,
                 int procState, Bundle state, List<ResultInfo> pendingResults,
                 List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
                 String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
@@ -615,6 +618,7 @@
             r.token = token;
             r.ident = ident;
             r.intent = intent;
+            r.voiceInteractor = voiceInteractor;
             r.activityInfo = info;
             r.compatInfo = compatInfo;
             r.state = state;
@@ -2197,7 +2201,8 @@
                         + r.activityInfo.name + " with config " + config);
                 activity.attach(appContext, this, getInstrumentation(), r.token,
                         r.ident, app, r.intent, r.activityInfo, title, r.parent,
-                        r.embeddedID, r.lastNonConfigurationInstances, config, options);
+                        r.embeddedID, r.lastNonConfigurationInstances, config, options,
+                        r.voiceInteractor);
 
                 if (customIntent != null) {
                     activity.mIntent = customIntent;
@@ -2363,7 +2368,7 @@
             // manager to stop us.
             try {
                 ActivityManagerNative.getDefault()
-                    .finishActivity(r.token, Activity.RESULT_CANCELED, null);
+                    .finishActivity(r.token, Activity.RESULT_CANCELED, null, false);
             } catch (RemoteException ex) {
                 // Ignore
             }
@@ -2984,7 +2989,7 @@
             // just end this activity.
             try {
                 ActivityManagerNative.getDefault()
-                    .finishActivity(token, Activity.RESULT_CANCELED, null);
+                    .finishActivity(token, Activity.RESULT_CANCELED, null, false);
             } catch (RemoteException ex) {
             }
         }
@@ -3003,7 +3008,9 @@
                 int h;
                 if (w < 0) {
                     Resources res = r.activity.getResources();
-                    if (SystemProperties.getBoolean("persist.recents.use_alternate", false)) {
+                    Configuration config = res.getConfiguration();
+                    boolean useAlternateRecents = (config.smallestScreenWidthDp < 600);
+                    if (useAlternateRecents) {
                         int wId = com.android.internal.R.dimen.recents_thumbnail_width;
                         int hId = com.android.internal.R.dimen.recents_thumbnail_height;
                         mThumbnailWidth = w = res.getDimensionPixelSize(wId);
diff --git a/core/java/android/app/ActivityTransitionCoordinator.java b/core/java/android/app/ActivityTransitionCoordinator.java
new file mode 100644
index 0000000..3c1455b
--- /dev/null
+++ b/core/java/android/app/ActivityTransitionCoordinator.java
@@ -0,0 +1,842 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.transition.Transition;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
+import android.util.ArrayMap;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewGroupOverlay;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+import android.widget.ImageView;
+
+import java.util.ArrayList;
+import java.util.Collection;
+
+/**
+ * Base class for ExitTransitionCoordinator and EnterTransitionCoordinator, classes
+ * that manage activity transitions and the communications coordinating them between
+ * Activities. The ExitTransitionCoordinator is created in the
+ * ActivityOptions#makeSceneTransitionAnimation. The EnterTransitionCoordinator
+ * is created by ActivityOptions#createEnterActivityTransition by Activity when the window is
+ * attached.
+ *
+ * Typical startActivity goes like this:
+ * 1) ExitTransitionCoordinator created with ActivityOptions#makeSceneTransitionAnimation
+ * 2) Activity#startActivity called and that calls startExit() through
+ *    ActivityOptions#dispatchStartExit
+ *    - Exit transition starts by setting transitioning Views to INVISIBLE
+ * 3) Launched Activity starts, creating an EnterTransitionCoordinator.
+ *    - The Window is made translucent
+ *    - The Window background alpha is set to 0
+ *    - The transitioning views are made INVISIBLE
+ *    - MSG_SET_LISTENER is sent back to the ExitTransitionCoordinator.
+ * 4) The shared element transition completes.
+ *    - MSG_TAKE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
+ * 5) The MSG_TAKE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator.
+ *    - Shared elements are made VISIBLE
+ *    - Shared elements positions and size are set to match the end state of the calling
+ *      Activity.
+ *    - The shared element transition is started
+ *    - If the window allows overlapping transitions, the views transition is started by setting
+ *      the entering Views to VISIBLE and the background alpha is animated to opaque.
+ *    - MSG_HIDE_SHARED_ELEMENTS is sent to the ExitTransitionCoordinator
+ * 6) MSG_HIDE_SHARED_ELEMENTS is received by the ExitTransitionCoordinator
+ *    - The shared elements are made INVISIBLE
+ * 7) The exit transition completes in the calling Activity.
+ *    - MSG_EXIT_TRANSITION_COMPLETE is sent to the EnterTransitionCoordinator.
+ * 8) The MSG_EXIT_TRANSITION_COMPLETE is received by the EnterTransitionCoordinator.
+ *    - If the window doesn't allow overlapping enter transitions, the enter transition is started
+ *      by setting entering views to VISIBLE and the background is animated to opaque.
+ * 9) The background opacity animation completes.
+ *    - The window is made opaque
+ * 10) The calling Activity gets an onStop() call
+ *    - onActivityStopped() is called and all exited Views are made VISIBLE.
+ *
+ * Typical finishWithTransition goes like this:
+ * 1) finishWithTransition() calls startExit()
+ *    - The Window start transitioning to Translucent
+ *    - If no background exists, a black background is substituted
+ *    - MSG_PREPARE_RESTORE is sent to the ExitTransitionCoordinator
+ *    - The shared elements in the scene are matched against those shared elements
+ *      that were sent by comparing the names.
+ *    - The exit transition is started by setting Views to INVISIBLE.
+ * 2) MSG_PREPARE_RESTORE is received by the EnterTransitionCoordinator
+ *    - All transitioning views are made VISIBLE to reverse what was done when onActivityStopped()
+ *      was called
+ * 3) The Window is made translucent and a callback is received
+ *    - The background alpha is animated to 0
+ * 4) The background alpha animation completes
+ * 5) The shared element transition completes
+ *    - After both 4 & 5 complete, MSG_TAKE_SHARED_ELEMENTS is sent to the
+ *      ExitTransitionCoordinator
+ * 6) MSG_TAKE_SHARED_ELEMENTS is received by ExitTransitionCoordinator
+ *    - Shared elements are made VISIBLE
+ *    - Shared elements positions and size are set to match the end state of the calling
+ *      Activity.
+ *    - The shared element transition is started
+ *    - If the window allows overlapping transitions, the views transition is started by setting
+ *      the entering Views to VISIBLE.
+ *    - MSG_HIDE_SHARED_ELEMENTS is sent to the EnterTransitionCoordinator
+ * 7) MSG_HIDE_SHARED_ELEMENTS is received by the EnterTransitionCoordinator
+ *    - The shared elements are made INVISIBLE
+ * 8) The exit transition completes in the finishing Activity.
+ *    - MSG_EXIT_TRANSITION_COMPLETE is sent to the ExitTransitionCoordinator.
+ *    - finish() is called on the exiting Activity
+ * 9) The MSG_EXIT_TRANSITION_COMPLETE is received by the ExitTransitionCoordinator.
+ *    - If the window doesn't allow overlapping enter transitions, the enter transition is started
+ *      by setting entering views to VISIBLE.
+ */
+abstract class ActivityTransitionCoordinator extends ResultReceiver {
+    private static final String TAG = "ActivityTransitionCoordinator";
+
+    /**
+     * The names of shared elements that are transitioned to the started Activity.
+     * This is also the name of shared elements that the started Activity accepted.
+     */
+    public static final String KEY_SHARED_ELEMENT_NAMES = "android:shared_element_names";
+
+    public static final String KEY_SHARED_ELEMENT_STATE = "android:shared_element_state";
+
+    /**
+     * For Activity transitions, the called Activity's listener to receive calls
+     * when transitions complete.
+     */
+    static final String KEY_TRANSITION_RESULTS_RECEIVER = "android:transitionTargetListener";
+
+    private static final String KEY_SCREEN_X = "shared_element:screenX";
+    private static final String KEY_SCREEN_Y = "shared_element:screenY";
+    private static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
+    private static final String KEY_WIDTH = "shared_element:width";
+    private static final String KEY_HEIGHT = "shared_element:height";
+    private static final String KEY_NAME = "shared_element:name";
+    private static final String KEY_BITMAP = "shared_element:bitmap";
+
+    /**
+     * Sent by the exiting coordinator (either EnterTransitionCoordinator
+     * or ExitTransitionCoordinator) after the shared elements have
+     * become stationary (shared element transition completes). This tells
+     * the remote coordinator to take control of the shared elements and
+     * that animations may begin. The remote Activity won't start entering
+     * until this message is received, but may wait for
+     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
+     */
+    public static final int MSG_SET_LISTENER = 100;
+
+    /**
+     * Sent by the entering coordinator to tell the exiting coordinator
+     * to hide its shared elements after it has started its shared
+     * element transition. This is temporary until the
+     * interlock of shared elements is figured out.
+     */
+    public static final int MSG_HIDE_SHARED_ELEMENTS = 101;
+
+    /**
+     * Sent by the EnterTransitionCoordinator to tell the
+     * ExitTransitionCoordinator to hide all of its exited views after
+     * MSG_ACTIVITY_STOPPED has caused them all to show.
+     */
+    public static final int MSG_PREPARE_RESTORE = 102;
+
+    /**
+     * Sent by the exiting Activity in ActivityOptions#dispatchActivityStopped
+     * to leave the Activity in a good state after it has been hidden.
+     */
+    public static final int MSG_ACTIVITY_STOPPED = 103;
+
+    /**
+     * Sent by the exiting coordinator (either EnterTransitionCoordinator
+     * or ExitTransitionCoordinator) after the shared elements have
+     * become stationary (shared element transition completes). This tells
+     * the remote coordinator to take control of the shared elements and
+     * that animations may begin. The remote Activity won't start entering
+     * until this message is received, but may wait for
+     * MSG_EXIT_TRANSITION_COMPLETE if allowOverlappingTransitions() is true.
+     */
+    public static final int MSG_TAKE_SHARED_ELEMENTS = 104;
+
+    /**
+     * Sent by the exiting coordinator (either
+     * EnterTransitionCoordinator or ExitTransitionCoordinator) after
+     * the exiting Views have finished leaving the scene. This will
+     * be ignored if allowOverlappingTransitions() is true on the
+     * remote coordinator. If it is false, it will trigger the enter
+     * transition to start.
+     */
+    public static final int MSG_EXIT_TRANSITION_COMPLETE = 105;
+
+    /**
+     * Sent by Activity#startActivity to begin the exit transition.
+     */
+    public static final int MSG_START_EXIT_TRANSITION = 106;
+
+    private Window mWindow;
+    private ArrayList<View> mSharedElements = new ArrayList<View>();
+    private ArrayList<String> mTargetSharedNames = new ArrayList<String>();
+    private ActivityOptions.ActivityTransitionListener mListener =
+            new ActivityOptions.ActivityTransitionListener();
+    private ArrayList<View> mEnteringViews;
+    private ResultReceiver mRemoteResultReceiver;
+    private boolean mNotifiedSharedElementTransitionComplete;
+    private boolean mNotifiedExitTransitionComplete;
+    private boolean mSharedElementTransitionStarted;
+
+    private FixedEpicenterCallback mEpicenterCallback = new FixedEpicenterCallback();
+
+    private Transition.TransitionListener mSharedElementListener =
+            new Transition.TransitionListenerAdapter() {
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            transition.removeListener(this);
+            onSharedElementTransitionEnd();
+        }
+    };
+
+    private Transition.TransitionListener mExitListener =
+            new Transition.TransitionListenerAdapter() {
+        @Override
+        public void onTransitionEnd(Transition transition) {
+            transition.removeListener(this);
+            onExitTransitionEnd();
+        }
+    };
+
+    public ActivityTransitionCoordinator(Window window)
+    {
+        super(new Handler());
+        mWindow = window;
+    }
+
+    // -------------------- ResultsReceiver Overrides ----------------------
+    @Override
+    protected void onReceiveResult(int resultCode, Bundle resultData) {
+        switch (resultCode) {
+            case MSG_SET_LISTENER:
+                ResultReceiver resultReceiver
+                        = resultData.getParcelable(KEY_TRANSITION_RESULTS_RECEIVER);
+                setRemoteResultReceiver(resultReceiver);
+                onSetResultReceiver();
+                break;
+            case MSG_HIDE_SHARED_ELEMENTS:
+                onHideSharedElements();
+                break;
+            case MSG_PREPARE_RESTORE:
+                onPrepareRestore();
+                break;
+            case MSG_EXIT_TRANSITION_COMPLETE:
+                if (!mSharedElementTransitionStarted) {
+                    send(resultCode, resultData);
+                } else {
+                    onRemoteSceneExitComplete();
+                }
+                break;
+            case MSG_TAKE_SHARED_ELEMENTS:
+                ArrayList<String> sharedElementNames
+                        = resultData.getStringArrayList(KEY_SHARED_ELEMENT_NAMES);
+                Bundle sharedElementState = resultData.getBundle(KEY_SHARED_ELEMENT_STATE);
+                onTakeSharedElements(sharedElementNames, sharedElementState);
+                break;
+            case MSG_ACTIVITY_STOPPED:
+                onActivityStopped();
+                break;
+            case MSG_START_EXIT_TRANSITION:
+                startExit();
+                break;
+        }
+    }
+
+    // -------------------- calls that can be overridden by subclasses --------------------
+
+    /**
+     * Called when MSG_SET_LISTENER is received. This will only be received by
+     * ExitTransitionCoordinator.
+     */
+    protected void onSetResultReceiver() {}
+
+    /**
+     * Called when MSG_HIDE_SHARED_ELEMENTS is received
+     */
+    protected void onHideSharedElements() {
+        setViewVisibility(getSharedElements(), View.INVISIBLE);
+        mListener.onSharedElementTransferred(getSharedElementNames(), getSharedElements());
+    }
+
+    /**
+     * Called when MSG_PREPARE_RESTORE is called. This will only be received by
+     * ExitTransitionCoordinator.
+     */
+    protected void onPrepareRestore() {
+        mListener.onEnterReady();
+    }
+
+    /**
+     * Called when MSG_EXIT_TRANSITION_COMPLETE is received -- the remote coordinator has
+     * completed its exit transition. This can be called by the ExitTransitionCoordinator when
+     * starting an Activity or EnterTransitionCoordinator when called with finishWithTransition.
+     */
+    protected void onRemoteSceneExitComplete() {
+        if (!allowOverlappingTransitions()) {
+            Transition transition = beginTransition(mEnteringViews, false, true, true);
+            onStartEnterTransition(transition, mEnteringViews);
+        }
+        mListener.onRemoteExitComplete();
+    }
+
+    /**
+     * Called when MSG_TAKE_SHARED_ELEMENTS is received. This means that the shared elements are
+     * in a stable state and ready to move to the Window.
+     * @param sharedElementNames The names of the shared elements to move.
+     * @param state Contains the shared element states (size & position)
+     */
+    protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
+        setSharedElements();
+        reconcileSharedElements(sharedElementNames);
+        mEnteringViews.removeAll(mSharedElements);
+        final ArrayList<View> accepted = new ArrayList<View>();
+        final ArrayList<View> rejected = new ArrayList<View>();
+        createSharedElementImages(accepted, rejected, sharedElementNames, state);
+        setSharedElementState(state, accepted);
+        handleRejected(rejected);
+
+        if (getViewsTransition() != null) {
+            setViewVisibility(mEnteringViews, View.INVISIBLE);
+        }
+        setViewVisibility(mSharedElements, View.VISIBLE);
+        Transition transition = beginTransition(mEnteringViews, true, allowOverlappingTransitions(),
+                true);
+
+        if (allowOverlappingTransitions()) {
+            onStartEnterTransition(transition, mEnteringViews);
+        }
+
+        mRemoteResultReceiver.send(MSG_HIDE_SHARED_ELEMENTS, null);
+    }
+
+    /**
+     * Called when MSG_ACTIVITY_STOPPED is received. This is received when Activity.onStop is
+     * called after running startActivity* is called using an Activity Transition.
+     */
+    protected void onActivityStopped() {}
+
+    /**
+     * Called when the start transition is ready to run. This may be immediately after
+     * MSG_TAKE_SHARED_ELEMENTS or MSG_EXIT_TRANSITION_COMPLETE, depending on whether
+     * overlapping transitions are allowed.
+     * @param transition The transition currently started.
+     * @param enteringViews The views entering the scene. This won't include shared elements.
+     */
+    protected void onStartEnterTransition(Transition transition, ArrayList<View> enteringViews) {
+        if (getViewsTransition() != null) {
+            setViewVisibility(enteringViews, View.VISIBLE);
+        }
+        mEnteringViews = null;
+        mListener.onStartEnterTransition(getSharedElementNames(), getSharedElements());
+    }
+
+    /**
+     * Called when the exit transition has started.
+     * @param exitingViews The views leaving the scene. This won't include shared elements.
+     */
+    protected void onStartExitTransition(ArrayList<View> exitingViews) {}
+
+    /**
+     * Called during the exit when the shared element transition has completed.
+     */
+    protected void onSharedElementTransitionEnd() {
+        Bundle bundle = new Bundle();
+        int[] tempLoc = new int[2];
+        for (int i = 0; i < mSharedElements.size(); i++) {
+            View sharedElement = mSharedElements.get(i);
+            String name = mTargetSharedNames.get(i);
+            captureSharedElementState(sharedElement, name, bundle, tempLoc);
+        }
+        Bundle allValues = new Bundle();
+        allValues.putStringArrayList(KEY_SHARED_ELEMENT_NAMES, getSharedElementNames());
+        allValues.putBundle(KEY_SHARED_ELEMENT_STATE, bundle);
+        sharedElementTransitionComplete(allValues);
+        mListener.onSharedElementExitTransitionComplete();
+    }
+
+    /**
+     * Called after the shared element transition is complete to pass the shared element state
+     * to the remote coordinator.
+     * @param bundle The Bundle to send to the coordinator containing the shared element state.
+     */
+    protected abstract void sharedElementTransitionComplete(Bundle bundle);
+
+    /**
+     * Called when the exit transition finishes.
+     */
+    protected void onExitTransitionEnd() {
+        mListener.onExitTransitionComplete();
+    }
+
+    /**
+     * Called to start the exit transition. Launched from ActivityOptions#dispatchStartExit
+     */
+    protected abstract void startExit();
+
+    /**
+     * A non-null transition indicates that the Views of the Window should be made INVISIBLE.
+     * @return The Transition used to cause transitioning views to either enter or exit the scene.
+     */
+    protected abstract Transition getViewsTransition();
+
+    /**
+     * @return The Transition used to move the shared elements from the start position and size
+     * to the end position and size.
+     */
+    protected abstract Transition getSharedElementTransition();
+
+    /**
+     * @return When the enter transition should overlap with the exit transition of the
+     * remote controller.
+     */
+    protected abstract boolean allowOverlappingTransitions();
+
+    // called by subclasses
+
+    protected void notifySharedElementTransitionComplete(Bundle sharedElements) {
+        if (!mNotifiedSharedElementTransitionComplete) {
+            mNotifiedSharedElementTransitionComplete = true;
+            mRemoteResultReceiver.send(MSG_TAKE_SHARED_ELEMENTS, sharedElements);
+        }
+    }
+
+    protected void notifyExitTransitionComplete() {
+        if (!mNotifiedExitTransitionComplete) {
+            mNotifiedExitTransitionComplete = true;
+            mRemoteResultReceiver.send(MSG_EXIT_TRANSITION_COMPLETE, null);
+        }
+    }
+
+    protected void notifyPrepareRestore() {
+        mRemoteResultReceiver.send(MSG_PREPARE_RESTORE, null);
+    }
+
+    protected void setRemoteResultReceiver(ResultReceiver resultReceiver) {
+        mRemoteResultReceiver = resultReceiver;
+    }
+
+    protected void notifySetListener() {
+        Bundle bundle = new Bundle();
+        bundle.putParcelable(KEY_TRANSITION_RESULTS_RECEIVER, this);
+        mRemoteResultReceiver.send(MSG_SET_LISTENER, bundle);
+    }
+
+    protected void setEnteringViews(ArrayList<View> views) {
+        mEnteringViews = views;
+    }
+
+    protected void setSharedElements() {
+        Pair<View, String>[] sharedElements = mListener.getSharedElementsMapping();
+        mSharedElements.clear();
+        mTargetSharedNames.clear();
+        if (sharedElements == null) {
+            ArrayMap<String, View> map = new ArrayMap<String, View>();
+            if (getViewsTransition() != null) {
+                setViewVisibility(mEnteringViews, View.VISIBLE);
+            }
+            getDecor().findSharedElements(map);
+            if (getViewsTransition() != null) {
+                setViewVisibility(mEnteringViews, View.INVISIBLE);
+            }
+            for (int i = 0; i < map.size(); i++) {
+                View view = map.valueAt(i);
+                String name = map.keyAt(i);
+                mSharedElements.add(view);
+                mTargetSharedNames.add(name);
+            }
+        } else {
+            for (int i = 0; i < sharedElements.length; i++) {
+                Pair<View, String> viewStringPair = sharedElements[i];
+                View view = viewStringPair.first;
+                String name = viewStringPair.second;
+                mSharedElements.add(view);
+                mTargetSharedNames.add(name);
+            }
+        }
+    }
+
+    protected ArrayList<View> getSharedElements() {
+        return mSharedElements;
+    }
+
+    protected ArrayList<String> getSharedElementNames() {
+        return mTargetSharedNames;
+    }
+
+    protected Window getWindow() {
+        return mWindow;
+    }
+
+    protected ViewGroup getDecor() {
+        return (mWindow == null) ? null : (ViewGroup) mWindow.getDecorView();
+    }
+
+    protected void startExitTransition(ArrayList<String> sharedElements) {
+        setSharedElements();
+        reconcileSharedElements(sharedElements);
+        ArrayList<View> transitioningViews = captureTransitioningViews();
+        beginTransition(transitioningViews, true, true, false);
+        onStartExitTransition(transitioningViews);
+        if (getViewsTransition() != null) {
+            setViewVisibility(transitioningViews, View.INVISIBLE);
+        }
+        mListener.onStartExitTransition(getSharedElementNames(), getSharedElements());
+    }
+
+    protected void clearConnections() {
+        mRemoteResultReceiver = null;
+    }
+
+    // public API
+
+    public void setActivityTransitionListener(ActivityOptions.ActivityTransitionListener listener) {
+        if (listener == null) {
+            mListener = new ActivityOptions.ActivityTransitionListener();
+        } else {
+            mListener = listener;
+        }
+    }
+
+    // private methods
+
+    private Transition configureTransition(Transition transition) {
+        if (transition != null) {
+            transition = transition.clone();
+            transition.setEpicenterCallback(mEpicenterCallback);
+        }
+        return transition;
+    }
+
+    private void reconcileSharedElements(ArrayList<String> sharedElementNames) {
+        // keep only those that are in sharedElementNames.
+        int numSharedElements = sharedElementNames.size();
+        int targetIndex = 0;
+        for (int i = 0; i < numSharedElements; i++) {
+            String name = sharedElementNames.get(i);
+            int index = mTargetSharedNames.indexOf(name);
+            if (index >= 0) {
+                // Swap the items at the indexes if necessary.
+                if (index != targetIndex) {
+                    View temp = mSharedElements.get(index);
+                    mSharedElements.set(index, mSharedElements.get(targetIndex));
+                    mSharedElements.set(targetIndex, temp);
+                    mTargetSharedNames.set(index, mTargetSharedNames.get(targetIndex));
+                    mTargetSharedNames.set(targetIndex, name);
+                }
+                targetIndex++;
+            }
+        }
+        for (int i = mSharedElements.size() - 1; i >= targetIndex; i--) {
+            mSharedElements.remove(i);
+            mTargetSharedNames.remove(i);
+        }
+        Rect epicenter = null;
+        if (!mTargetSharedNames.isEmpty()
+                && mTargetSharedNames.get(0).equals(sharedElementNames.get(0))) {
+            epicenter = calcEpicenter(mSharedElements.get(0));
+        }
+        mEpicenterCallback.setEpicenter(epicenter);
+    }
+
+    private void setSharedElementState(Bundle sharedElementState,
+            final ArrayList<View> acceptedOverlayViews) {
+        final int[] tempLoc = new int[2];
+        if (sharedElementState != null) {
+            for (int i = 0; i < mSharedElements.size(); i++) {
+                View sharedElement = mSharedElements.get(i);
+                View parent = (View) sharedElement.getParent();
+                parent.getLocationOnScreen(tempLoc);
+                String name = mTargetSharedNames.get(i);
+                setSharedElementState(sharedElement, name, sharedElementState, tempLoc);
+                sharedElement.requestLayout();
+            }
+        }
+        mListener.onCaptureSharedElementStart(mTargetSharedNames, mSharedElements,
+                acceptedOverlayViews);
+
+        getDecor().getViewTreeObserver().addOnPreDrawListener(
+                new ViewTreeObserver.OnPreDrawListener() {
+                    @Override
+                    public boolean onPreDraw() {
+                        getDecor().getViewTreeObserver().removeOnPreDrawListener(this);
+                        mListener.onCaptureSharedElementEnd(mTargetSharedNames, mSharedElements,
+                                acceptedOverlayViews);
+                        mSharedElementTransitionStarted = true;
+                        return true;
+                    }
+                }
+        );
+    }
+
+    /**
+     * Sets the captured values from a previous
+     * {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
+     * @param view The View to apply placement changes to.
+     * @param name The shared element name given from the source Activity.
+     * @param transitionArgs A <code>Bundle</code> containing all placementinformation for named
+     *                       shared elements in the scene.
+     * @param parentLoc The x and y coordinates of the parent's screen position.
+     */
+    private static void setSharedElementState(View view, String name, Bundle transitionArgs,
+            int[] parentLoc) {
+        Bundle sharedElementBundle = transitionArgs.getBundle(name);
+        if (sharedElementBundle == null) {
+            return;
+        }
+
+        float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
+        view.setTranslationZ(z);
+
+        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
+        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
+        int width = sharedElementBundle.getInt(KEY_WIDTH);
+        int height = sharedElementBundle.getInt(KEY_HEIGHT);
+
+        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
+        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
+        view.measure(widthSpec, heightSpec);
+
+        int left = x - parentLoc[0];
+        int top = y - parentLoc[1];
+        int right = left + width;
+        int bottom = top + height;
+        view.layout(left, top, right, bottom);
+    }
+
+    /**
+     * Captures placement information for Views with a shared element name for
+     * Activity Transitions.
+     * @param view The View to capture the placement information for.
+     * @param name The shared element name in the target Activity to apply the placement
+     *             information for.
+     * @param transitionArgs Bundle to store shared element placement information.
+     * @param tempLoc A temporary int[2] for capturing the current location of views.
+     * @see #setSharedElementState(android.view.View, String, android.os.Bundle, int[])
+     */
+    private static void captureSharedElementState(View view, String name, Bundle transitionArgs,
+            int[] tempLoc) {
+        Bundle sharedElementBundle = new Bundle();
+        view.getLocationOnScreen(tempLoc);
+        float scaleX = view.getScaleX();
+        sharedElementBundle.putInt(KEY_SCREEN_X, tempLoc[0]);
+        int width = Math.round(view.getWidth() * scaleX);
+        sharedElementBundle.putInt(KEY_WIDTH, width);
+
+        float scaleY = view.getScaleY();
+        sharedElementBundle.putInt(KEY_SCREEN_Y, tempLoc[1]);
+        int height= Math.round(view.getHeight() * scaleY);
+        sharedElementBundle.putInt(KEY_HEIGHT, height);
+
+        sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
+
+        sharedElementBundle.putString(KEY_NAME, view.getSharedElementName());
+
+        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
+        Canvas canvas = new Canvas(bitmap);
+        view.draw(canvas);
+        sharedElementBundle.putParcelable(KEY_BITMAP, bitmap);
+
+        transitionArgs.putBundle(name, sharedElementBundle);
+    }
+
+    private static Rect calcEpicenter(View view) {
+        int[] loc = new int[2];
+        view.getLocationOnScreen(loc);
+        int left = loc[0] + Math.round(view.getTranslationX());
+        int top = loc[1] + Math.round(view.getTranslationY());
+        int right = left + view.getWidth();
+        int bottom = top + view.getHeight();
+        return new Rect(left, top, right, bottom);
+    }
+
+    public static void setViewVisibility(Collection<View> views, int visibility) {
+        if (views != null) {
+            for (View view : views) {
+                view.setVisibility(visibility);
+            }
+        }
+    }
+
+    private static Transition addTransitionTargets(Transition transition, Collection<View> views) {
+        if (transition == null || views == null || views.isEmpty()) {
+            return null;
+        }
+        TransitionSet set = new TransitionSet();
+        set.addTransition(transition.clone());
+        if (views != null) {
+            for (View view: views) {
+                set.addTarget(view);
+            }
+        }
+        return set;
+    }
+
+    private ArrayList<View> captureTransitioningViews() {
+        if (getViewsTransition() == null) {
+            return null;
+        }
+        ArrayList<View> transitioningViews = new ArrayList<View>();
+        getDecor().captureTransitioningViews(transitioningViews);
+        transitioningViews.removeAll(getSharedElements());
+        return transitioningViews;
+    }
+
+    private Transition getSharedElementTransition(boolean isEnter) {
+        Transition transition = getSharedElementTransition();
+        if (transition == null) {
+            return null;
+        }
+        transition = configureTransition(transition);
+        if (!isEnter) {
+            transition.addListener(mSharedElementListener);
+        }
+        return transition;
+    }
+
+    private Transition getViewsTransition(ArrayList<View> transitioningViews, boolean isEnter) {
+        Transition transition = getViewsTransition();
+        if (transition == null) {
+            return null;
+        }
+        transition = configureTransition(transition);
+        if (!isEnter) {
+            transition.addListener(mExitListener);
+        }
+        return addTransitionTargets(transition, transitioningViews);
+    }
+
+    private Transition beginTransition(ArrayList<View> transitioningViews,
+            boolean transitionSharedElement, boolean transitionViews, boolean isEnter) {
+        Transition sharedElementTransition = null;
+        if (transitionSharedElement) {
+            sharedElementTransition = getSharedElementTransition(isEnter);
+            if (!isEnter && sharedElementTransition == null) {
+                onSharedElementTransitionEnd();
+            }
+        }
+        Transition viewsTransition = null;
+        if (transitionViews) {
+            viewsTransition = getViewsTransition(transitioningViews, isEnter);
+            if (!isEnter && viewsTransition == null) {
+                onExitTransitionEnd();
+            }
+        }
+
+        Transition transition = null;
+        if (sharedElementTransition == null) {
+            transition = viewsTransition;
+        } else if (viewsTransition == null) {
+            transition = sharedElementTransition;
+        } else {
+            TransitionSet set = new TransitionSet();
+            set.addTransition(sharedElementTransition);
+            set.addTransition(viewsTransition);
+            transition = set;
+        }
+        if (transition != null) {
+            TransitionManager.beginDelayedTransition(getDecor(), transition);
+            if (transitionSharedElement && !mSharedElements.isEmpty()) {
+                mSharedElements.get(0).invalidate();
+            } else if (transitionViews && !transitioningViews.isEmpty()) {
+                transitioningViews.get(0).invalidate();
+            }
+        }
+        return transition;
+    }
+
+    private void handleRejected(final ArrayList<View> rejected) {
+        int numRejected = rejected.size();
+        if (numRejected == 0) {
+            return;
+        }
+        boolean rejectionHandled = mListener.handleRejectedSharedElements(rejected);
+        if (rejectionHandled) {
+            return;
+        }
+
+        ViewGroupOverlay overlay = getDecor().getOverlay();
+        ObjectAnimator animator = null;
+        for (int i = 0; i < numRejected; i++) {
+            View view = rejected.get(i);
+            overlay.add(view);
+            animator = ObjectAnimator.ofFloat(view, View.ALPHA, 1, 0);
+            animator.start();
+        }
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                ViewGroupOverlay overlay = getDecor().getOverlay();
+                for (int i = rejected.size() - 1; i >= 0; i--) {
+                    overlay.remove(rejected.get(i));
+                }
+            }
+        });
+    }
+
+    private void createSharedElementImages(ArrayList<View> accepted, ArrayList<View> rejected,
+            ArrayList<String> sharedElementNames, Bundle state) {
+        int numSharedElements = sharedElementNames.size();
+        Context context = getWindow().getContext();
+        int[] parentLoc = new int[2];
+        getDecor().getLocationOnScreen(parentLoc);
+        for (int i = 0; i < numSharedElements; i++) {
+            String name = sharedElementNames.get(i);
+            Bundle sharedElementBundle = state.getBundle(name);
+            if (sharedElementBundle != null) {
+                Bitmap bitmap = sharedElementBundle.getParcelable(KEY_BITMAP);
+                ImageView imageView = new ImageView(context);
+                imageView.setId(com.android.internal.R.id.shared_element);
+                imageView.setScaleType(ImageView.ScaleType.CENTER);
+                imageView.setImageBitmap(bitmap);
+                imageView.setSharedElementName(name);
+                setSharedElementState(imageView, name, state, parentLoc);
+                if (mTargetSharedNames.contains(name)) {
+                    accepted.add(imageView);
+                } else {
+                    rejected.add(imageView);
+                }
+            }
+        }
+    }
+
+    private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
+        private Rect mEpicenter;
+
+        public void setEpicenter(Rect epicenter) { mEpicenter = epicenter; }
+
+        @Override
+        public Rect getEpicenter(Transition transition) {
+            return mEpicenter;
+        }
+    }
+}
diff --git a/core/java/android/app/ActivityView.java b/core/java/android/app/ActivityView.java
index 113f123..a810134 100644
--- a/core/java/android/app/ActivityView.java
+++ b/core/java/android/app/ActivityView.java
@@ -33,17 +33,20 @@
 import android.view.Surface;
 import android.view.TextureView;
 import android.view.TextureView.SurfaceTextureListener;
-import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
+import dalvik.system.CloseGuard;
+
+import java.lang.ref.WeakReference;
 
 /** @hide */
 public class ActivityView extends ViewGroup {
-    private final String TAG = "ActivityView";
-    private final boolean DEBUG = false;
+    private static final String TAG = "ActivityView";
+    private static final boolean DEBUG = false;
 
+    DisplayMetrics mMetrics;
     private final TextureView mTextureView;
-    private IActivityContainer mActivityContainer;
+    private ActivityContainerWrapper mActivityContainer;
     private Activity mActivity;
     private int mWidth;
     private int mHeight;
@@ -75,9 +78,23 @@
             throw new IllegalStateException("The ActivityView's Context is not an Activity.");
         }
 
+        try {
+            mActivityContainer = new ActivityContainerWrapper(
+                    ActivityManagerNative.getDefault().createActivityContainer(
+                            mActivity.getActivityToken(), new ActivityContainerCallback(this)));
+        } catch (RemoteException e) {
+            throw new RuntimeException("ActivityView: Unable to create ActivityContainer. "
+                    + e);
+        }
+
         mTextureView = new TextureView(context);
         mTextureView.setSurfaceTextureListener(new ActivityViewSurfaceTextureListener());
         addView(mTextureView);
+
+        WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
+        mMetrics = new DisplayMetrics();
+        wm.getDefaultDisplay().getMetrics(mMetrics);
+
         if (DEBUG) Log.v(TAG, "ctor()");
     }
 
@@ -86,57 +103,8 @@
         mTextureView.layout(0, 0, r - l, b - t);
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        if (DEBUG) Log.v(TAG, "onAttachedToWindow()");
-        super.onAttachedToWindow();
-        try {
-            final IBinder token = mActivity.getActivityToken();
-            mActivityContainer =
-                    ActivityManagerNative.getDefault().createActivityContainer(token, null);
-        } catch (RemoteException e) {
-            throw new IllegalStateException("ActivityView: Unable to create ActivityContainer. "
-                    + e);
-        }
-
-        attachToSurfaceWhenReady();
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer);
-        super.onDetachedFromWindow();
-        if (mActivityContainer != null) {
-            detach();
-            try {
-                ActivityManagerNative.getDefault().deleteActivityContainer(mActivityContainer);
-            } catch (RemoteException e) {
-            }
-            mActivityContainer = null;
-        }
-    }
-
-    @Override
-    protected void onWindowVisibilityChanged(int visibility) {
-        if (DEBUG) Log.v(TAG, "onWindowVisibilityChanged(): visibility=" + visibility);
-        super.onWindowVisibilityChanged(visibility);
-        switch (visibility) {
-            case  View.VISIBLE:
-                attachToSurfaceWhenReady();
-                break;
-            case  View.INVISIBLE:
-                break;
-            case View.GONE:
-                break;
-        }
-    }
-
     private boolean injectInputEvent(InputEvent event) {
-        try {
-            return mActivityContainer != null && mActivityContainer.injectEvent(event);
-        } catch (RemoteException e) {
-            return false;
-        }
+        return mActivityContainer != null && mActivityContainer.injectEvent(event);
     }
 
     @Override
@@ -154,125 +122,151 @@
         return super.onGenericMotionEvent(event);
     }
 
+    @Override
+    public void onAttachedToWindow() {
+        if (DEBUG) Log.v(TAG, "onAttachedToWindow(): mActivityContainer=" + mActivityContainer +
+                " mSurface=" + mSurface);
+    }
+
+    @Override
+    public void onDetachedFromWindow() {
+        if (DEBUG) Log.v(TAG, "onDetachedFromWindow(): mActivityContainer=" + mActivityContainer +
+                " mSurface=" + mSurface);
+    }
+
     public boolean isAttachedToDisplay() {
         return mSurface != null;
     }
 
     public void startActivity(Intent intent) {
+        if (mActivityContainer == null) {
+            throw new IllegalStateException("Attempt to call startActivity after release");
+        }
         if (DEBUG) Log.v(TAG, "startActivity(): intent=" + intent + " " +
                 (isAttachedToDisplay() ? "" : "not") + " attached");
         if (mSurface != null) {
-            try {
-                mActivityContainer.startActivity(intent);
-            } catch (RemoteException e) {
-                throw new IllegalStateException("ActivityView: Unable to startActivity. " + e);
-            }
+            mActivityContainer.startActivity(intent);
         } else {
+            mActivityContainer.checkEmbeddedAllowed(intent);
             mQueuedIntent = intent;
             mQueuedPendingIntent = null;
         }
     }
 
-    private void startActivityIntentSender(IIntentSender iIntentSender) {
-        try {
-            mActivityContainer.startActivityIntentSender(iIntentSender);
-        } catch (RemoteException e) {
-            throw new IllegalStateException(
-                    "ActivityView: Unable to startActivity from IntentSender. " + e);
-        }
-    }
-
     public void startActivity(IntentSender intentSender) {
+        if (mActivityContainer == null) {
+            throw new IllegalStateException("Attempt to call startActivity after release");
+        }
         if (DEBUG) Log.v(TAG, "startActivityIntentSender(): intentSender=" + intentSender + " " +
                 (isAttachedToDisplay() ? "" : "not") + " attached");
         final IIntentSender iIntentSender = intentSender.getTarget();
         if (mSurface != null) {
-            startActivityIntentSender(iIntentSender);
+            mActivityContainer.startActivityIntentSender(iIntentSender);
         } else {
+            mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
             mQueuedPendingIntent = iIntentSender;
             mQueuedIntent = null;
         }
     }
 
     public void startActivity(PendingIntent pendingIntent) {
+        if (mActivityContainer == null) {
+            throw new IllegalStateException("Attempt to call startActivity after release");
+        }
         if (DEBUG) Log.v(TAG, "startActivityPendingIntent(): PendingIntent=" + pendingIntent + " "
                 + (isAttachedToDisplay() ? "" : "not") + " attached");
         final IIntentSender iIntentSender = pendingIntent.getTarget();
         if (mSurface != null) {
-            startActivityIntentSender(iIntentSender);
+            mActivityContainer.startActivityIntentSender(iIntentSender);
         } else {
+            mActivityContainer.checkEmbeddedAllowedIntentSender(iIntentSender);
             mQueuedPendingIntent = iIntentSender;
             mQueuedIntent = null;
         }
     }
 
+    public void release() {
+        if (DEBUG) Log.v(TAG, "release() mActivityContainer=" + mActivityContainer +
+                " mSurface=" + mSurface);
+        if (mActivityContainer == null) {
+            Log.e(TAG, "Duplicate call to release");
+            return;
+        }
+        mActivityContainer.release();
+        mActivityContainer = null;
+
+        if (mSurface != null) {
+            mSurface.release();
+            mSurface = null;
+        }
+
+        mTextureView.setSurfaceTextureListener(null);
+    }
+
     private void attachToSurfaceWhenReady() {
         final SurfaceTexture surfaceTexture = mTextureView.getSurfaceTexture();
-        if (mActivityContainer == null || surfaceTexture == null || mSurface != null) {
+        if (surfaceTexture == null || mSurface != null) {
             // Either not ready to attach, or already attached.
             return;
         }
 
-        WindowManager wm = (WindowManager)mActivity.getSystemService(Context.WINDOW_SERVICE);
-        DisplayMetrics metrics = new DisplayMetrics();
-        wm.getDefaultDisplay().getMetrics(metrics);
-
         mSurface = new Surface(surfaceTexture);
         try {
-            mActivityContainer.attachToSurface(mSurface, mWidth, mHeight, metrics.densityDpi);
+            mActivityContainer.setSurface(mSurface, mWidth, mHeight, mMetrics.densityDpi);
         } catch (RemoteException e) {
             mSurface.release();
             mSurface = null;
-            throw new IllegalStateException(
-                    "ActivityView: Unable to create ActivityContainer. " + e);
+            throw new RuntimeException("ActivityView: Unable to create ActivityContainer. " + e);
         }
 
         if (DEBUG) Log.v(TAG, "attachToSurfaceWhenReady: " + (mQueuedIntent != null ||
                 mQueuedPendingIntent != null ? "" : "no") + " queued intent");
         if (mQueuedIntent != null) {
-            startActivity(mQueuedIntent);
+            mActivityContainer.startActivity(mQueuedIntent);
             mQueuedIntent = null;
         } else if (mQueuedPendingIntent != null) {
-            startActivityIntentSender(mQueuedPendingIntent);
+            mActivityContainer.startActivityIntentSender(mQueuedPendingIntent);
             mQueuedPendingIntent = null;
         }
     }
 
-    private void detach() {
-        if (DEBUG) Log.d(TAG, "detach: attached=" + isAttachedToDisplay());
-        if (mSurface != null) {
-            try {
-                mActivityContainer.detachFromDisplay();
-            } catch (RemoteException e) {
-            }
-            mSurface.release();
-            mSurface = null;
-        }
-    }
-
     private class ActivityViewSurfaceTextureListener implements SurfaceTextureListener {
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width,
                 int height) {
+            if (mActivityContainer == null) {
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onSurfaceTextureAvailable: width=" + width + " height="
                     + height);
             mWidth = width;
             mHeight = height;
-            if (mActivityContainer != null) {
-                attachToSurfaceWhenReady();
-            }
+            attachToSurfaceWhenReady();
         }
 
         @Override
         public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width,
                 int height) {
+            if (mActivityContainer == null) {
+                return;
+            }
             if (DEBUG) Log.d(TAG, "onSurfaceTextureSizeChanged: w=" + width + " h=" + height);
         }
 
         @Override
         public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) {
+            if (mActivityContainer == null) {
+                return true;
+            }
             if (DEBUG) Log.d(TAG, "onSurfaceTextureDestroyed");
-            detach();
+            mSurface.release();
+            mSurface = null;
+            try {
+                mActivityContainer.setSurface(null, mWidth, mHeight, mMetrics.densityDpi);
+            } catch (RemoteException e) {
+                throw new RuntimeException(
+                        "ActivityView: Unable to set surface of ActivityContainer. " + e);
+            }
             return true;
         }
 
@@ -282,4 +276,114 @@
         }
 
     }
+
+    private static class ActivityContainerCallback extends IActivityContainerCallback.Stub {
+        private final WeakReference<ActivityView> mActivityViewWeakReference;
+
+        ActivityContainerCallback(ActivityView activityView) {
+            mActivityViewWeakReference = new WeakReference<ActivityView>(activityView);
+        }
+
+        @Override
+        public void setVisible(IBinder container, boolean visible) {
+            if (DEBUG) Log.v(TAG, "setVisible(): container=" + container + " visible=" + visible +
+                    " ActivityView=" + mActivityViewWeakReference.get());
+        }
+    }
+
+    private static class ActivityContainerWrapper {
+        private final IActivityContainer mIActivityContainer;
+        private final CloseGuard mGuard = CloseGuard.get();
+
+        ActivityContainerWrapper(IActivityContainer container) {
+            mIActivityContainer = container;
+            mGuard.open("release");
+        }
+
+        void attachToDisplay(int displayId) {
+            try {
+                mIActivityContainer.attachToDisplay(displayId);
+            } catch (RemoteException e) {
+            }
+        }
+
+        void setSurface(Surface surface, int width, int height, int density)
+                throws RemoteException {
+            mIActivityContainer.setSurface(surface, width, height, density);
+        }
+
+        int startActivity(Intent intent) {
+            try {
+                return mIActivityContainer.startActivity(intent);
+            } catch (RemoteException e) {
+                throw new RuntimeException("ActivityView: Unable to startActivity. " + e);
+            }
+        }
+
+        int startActivityIntentSender(IIntentSender intentSender) {
+            try {
+                return mIActivityContainer.startActivityIntentSender(intentSender);
+            } catch (RemoteException e) {
+                throw new RuntimeException(
+                        "ActivityView: Unable to startActivity from IntentSender. " + e);
+            }
+        }
+
+        void checkEmbeddedAllowed(Intent intent) {
+            try {
+                mIActivityContainer.checkEmbeddedAllowed(intent);
+            } catch (RemoteException e) {
+                throw new RuntimeException(
+                        "ActivityView: Unable to startActivity from Intent. " + e);
+            }
+        }
+
+        void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
+            try {
+                mIActivityContainer.checkEmbeddedAllowedIntentSender(intentSender);
+            } catch (RemoteException e) {
+                throw new RuntimeException(
+                        "ActivityView: Unable to startActivity from IntentSender. " + e);
+            }
+        }
+
+        int getDisplayId() {
+            try {
+                return mIActivityContainer.getDisplayId();
+            } catch (RemoteException e) {
+                return -1;
+            }
+        }
+
+        boolean injectEvent(InputEvent event) {
+            try {
+                return mIActivityContainer.injectEvent(event);
+            } catch (RemoteException e) {
+                return false;
+            }
+        }
+
+        void release() {
+            if (DEBUG) Log.v(TAG, "ActivityContainerWrapper: release called");
+            try {
+                mIActivityContainer.release();
+                mGuard.close();
+            } catch (RemoteException e) {
+            }
+        }
+
+        @Override
+        protected void finalize() throws Throwable {
+            if (DEBUG) Log.v(TAG, "ActivityContainerWrapper: finalize called");
+            try {
+                if (mGuard != null) {
+                    mGuard.warnIfOpen();
+                    release();
+                }
+            } finally {
+                super.finalize();
+            }
+        }
+
+    }
 }
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 6ca5244..ab62427 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -128,6 +128,24 @@
     }
 
     @Override
+    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
+        // Try to find a main leanback_launcher activity.
+        Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
+        intentToResolve.addCategory(Intent.CATEGORY_LEANBACK_LAUNCHER);
+        intentToResolve.setPackage(packageName);
+        List<ResolveInfo> ris = queryIntentActivities(intentToResolve, 0);
+
+        if (ris == null || ris.size() <= 0) {
+            return null;
+        }
+        Intent intent = new Intent(intentToResolve);
+        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setClassName(ris.get(0).activityInfo.packageName,
+                ris.get(0).activityInfo.name);
+        return intent;
+    }
+
+    @Override
     public int[] getPackageGids(String packageName)
             throws NameNotFoundException {
         try {
diff --git a/core/java/android/app/ApplicationThreadNative.java b/core/java/android/app/ApplicationThreadNative.java
index f1c632e..fcc7f8e 100644
--- a/core/java/android/app/ApplicationThreadNative.java
+++ b/core/java/android/app/ApplicationThreadNative.java
@@ -33,6 +33,7 @@
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ParcelFileDescriptor;
+import com.android.internal.app.IVoiceInteractor;
 
 import java.io.FileDescriptor;
 import java.io.IOException;
@@ -136,6 +137,8 @@
             ActivityInfo info = ActivityInfo.CREATOR.createFromParcel(data);
             Configuration curConfig = Configuration.CREATOR.createFromParcel(data);
             CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
+            IVoiceInteractor voiceInteractor = IVoiceInteractor.Stub.asInterface(
+                    data.readStrongBinder());
             int procState = data.readInt();
             Bundle state = data.readBundle();
             List<ResultInfo> ri = data.createTypedArrayList(ResultInfo.CREATOR);
@@ -147,7 +150,8 @@
                     ? ParcelFileDescriptor.CREATOR.createFromParcel(data) : null;
             boolean autoStopProfiler = data.readInt() != 0;
             Bundle resumeArgs = data.readBundle();
-            scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo, procState, state,
+            scheduleLaunchActivity(intent, b, ident, info, curConfig, compatInfo,
+                    voiceInteractor, procState, state,
                     ri, pi, notResumed, isForward, profileName, profileFd, autoStopProfiler,
                     resumeArgs);
             return true;
@@ -735,6 +739,7 @@
 
     public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
+            IVoiceInteractor voiceInteractor,
             int procState, Bundle state, List<ResultInfo> pendingResults,
             List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
@@ -748,6 +753,7 @@
         info.writeToParcel(data, 0);
         curConfig.writeToParcel(data, 0);
         compatInfo.writeToParcel(data, 0);
+        data.writeStrongBinder(voiceInteractor != null ? voiceInteractor.asBinder() : null);
         data.writeInt(procState);
         data.writeBundle(state);
         data.writeTypedList(pendingResults);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1c02102..fe532bf 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -67,11 +67,12 @@
 import android.location.LocationManager;
 import android.media.AudioManager;
 import android.media.MediaRouter;
-import android.media.session.MediaSessionManager;
+import android.media.session.SessionManager;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
 import android.net.INetworkPolicyManager;
 import android.net.NetworkPolicyManager;
+import android.net.NetworkScoreManager;
 import android.net.Uri;
 import android.net.nsd.INsdManager;
 import android.net.nsd.NsdManager;
@@ -82,6 +83,7 @@
 import android.net.wifi.p2p.IWifiP2pManager;
 import android.net.wifi.p2p.WifiP2pManager;
 import android.nfc.NfcManager;
+import android.os.BatteryManager;
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -404,6 +406,11 @@
                     return new DownloadManager(ctx.getContentResolver(), ctx.getPackageName());
                 }});
 
+        registerService(BATTERY_SERVICE, new ServiceFetcher() {
+                public Object createService(ContextImpl ctx) {
+                    return new BatteryManager();
+                }});
+
         registerService(NFC_SERVICE, new ServiceFetcher() {
                 public Object createService(ContextImpl ctx) {
                     return new NfcManager(ctx);
@@ -632,7 +639,7 @@
 
         registerService(MEDIA_SESSION_SERVICE, new ServiceFetcher() {
             public Object createService(ContextImpl ctx) {
-                return new MediaSessionManager(ctx);
+                return new SessionManager(ctx);
             }
         });
         registerService(TRUST_SERVICE, new ServiceFetcher() {
@@ -648,6 +655,12 @@
                 ITvInputManager service = ITvInputManager.Stub.asInterface(iBinder);
                 return new TvInputManager(service, UserHandle.myUserId());
             }});
+
+        registerService(NETWORK_SCORE_SERVICE, new ServiceFetcher() {
+            public Object createService(ContextImpl ctx) {
+                return new NetworkScoreManager(ctx);
+            }
+        });
     }
 
     static ContextImpl getImpl(Context context) {
@@ -1852,17 +1865,26 @@
     }
 
     private String uriModeFlagToString(int uriModeFlags) {
-        switch (uriModeFlags) {
-            case Intent.FLAG_GRANT_READ_URI_PERMISSION |
-                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
-                return "read and write";
-            case Intent.FLAG_GRANT_READ_URI_PERMISSION:
-                return "read";
-            case Intent.FLAG_GRANT_WRITE_URI_PERMISSION:
-                return "write";
+        StringBuilder builder = new StringBuilder();
+        if ((uriModeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
+            builder.append("read and ");
         }
-        throw new IllegalArgumentException(
-                "Unknown permission mode flags: " + uriModeFlags);
+        if ((uriModeFlags & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0) {
+            builder.append("write and ");
+        }
+        if ((uriModeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0) {
+            builder.append("persistable and ");
+        }
+        if ((uriModeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0) {
+            builder.append("prefix and ");
+        }
+
+        if (builder.length() > 5) {
+            builder.setLength(builder.length() - 5);
+            return builder.toString();
+        } else {
+            throw new IllegalArgumentException("Unknown permission mode flags: " + uriModeFlags);
+        }
     }
 
     private void enforceForUri(
diff --git a/core/java/android/app/EnterTransitionCoordinator.java b/core/java/android/app/EnterTransitionCoordinator.java
new file mode 100644
index 0000000..cbb8359
--- /dev/null
+++ b/core/java/android/app/EnterTransitionCoordinator.java
@@ -0,0 +1,287 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.graphics.drawable.ColorDrawable;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+import android.transition.Transition;
+import android.view.View;
+import android.view.ViewTreeObserver;
+import android.view.Window;
+
+import java.util.ArrayList;
+
+/**
+ * This ActivityTransitionCoordinator is created by the Activity to manage
+ * the enter scene and shared element transfer as well as Activity#finishWithTransition
+ * exiting the Scene and transferring shared elements back to the called Activity.
+ */
+class EnterTransitionCoordinator extends ActivityTransitionCoordinator
+        implements ViewTreeObserver.OnPreDrawListener {
+    private static final String TAG = "EnterTransitionCoordinator";
+
+    // The background fade in/out duration. 150ms is pretty quick, but not abrupt.
+    private static final int FADE_BACKGROUND_DURATION_MS = 150;
+
+    /**
+     * The shared element names sent by the ExitTransitionCoordinator and may be
+     * shared when exiting back.
+     */
+    private ArrayList<String> mEnteringSharedElementNames;
+
+    /**
+     * The Activity that has created this coordinator. This is used solely to make the
+     * Window translucent/opaque.
+     */
+    private Activity mActivity;
+
+    /**
+     * True if the Window was opaque at the start and we should make it opaque again after
+     * enter transitions have completed.
+     */
+    private boolean mWasOpaque;
+
+    /**
+     * During exit, is the background alpha == 0?
+     */
+    private boolean mBackgroundFadedOut;
+
+    /**
+     * During exit, has the shared element transition completed?
+     */
+    private boolean mSharedElementTransitionComplete;
+
+    /**
+     * Has the exit started? We don't want to accidentally exit multiple times. e.g. when
+     * back is hit twice during the exit animation.
+     */
+    private boolean mExitTransitionStarted;
+
+    /**
+     * Has the exit transition ended?
+     */
+    private boolean mExitTransitionComplete;
+
+    /**
+     * We only want to make the Window transparent and set the background alpha once. After that,
+     * the Activity won't want the same enter transition.
+     */
+    private boolean mMadeReady;
+
+    /**
+     * True if Window.hasFeature(Window.FEATURE_CONTENT_TRANSITIONS) -- this means that
+     * enter and exit transitions should be active.
+     */
+    private boolean mSupportsTransition;
+
+    /**
+     * Background alpha animations may complete prior to receiving the callback for
+     * onTranslucentConversionComplete. If so, we need to immediately call to make the Window
+     * opaque.
+     */
+    private boolean mMakeOpaque;
+
+    public EnterTransitionCoordinator(Activity activity, ResultReceiver resultReceiver) {
+        super(activity.getWindow());
+        mActivity = activity;
+        setRemoteResultReceiver(resultReceiver);
+    }
+
+    public void readyToEnter() {
+        if (!mMadeReady) {
+            mMadeReady = true;
+            mSupportsTransition = getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS);
+            if (mSupportsTransition) {
+                Window window = getWindow();
+                window.getDecorView().getViewTreeObserver().addOnPreDrawListener(this);
+                mActivity.overridePendingTransition(0, 0);
+                mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
+                    @Override
+                    public void onTranslucentConversionComplete(boolean drawComplete) {
+                        mWasOpaque = true;
+                        if (mMakeOpaque) {
+                            mActivity.convertFromTranslucent();
+                        }
+                    }
+                });
+                Drawable background = getDecor().getBackground();
+                if (background != null) {
+                    window.setBackgroundDrawable(null);
+                    background.setAlpha(0);
+                    window.setBackgroundDrawable(background);
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
+        mEnteringSharedElementNames = new ArrayList<String>();
+        mEnteringSharedElementNames.addAll(sharedElementNames);
+        super.onTakeSharedElements(sharedElementNames, state);
+    }
+
+    @Override
+    protected void sharedElementTransitionComplete(Bundle bundle) {
+        notifySharedElementTransitionComplete(bundle);
+        exitAfterSharedElementTransition();
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        getWindow().getDecorView().getViewTreeObserver().removeOnPreDrawListener(this);
+        setEnteringViews(readyEnteringViews());
+        notifySetListener();
+        onPrepareRestore();
+        return false;
+    }
+
+    @Override
+    public void startExit() {
+        if (!mExitTransitionStarted) {
+            mExitTransitionStarted = true;
+            startExitTransition(mEnteringSharedElementNames);
+        }
+    }
+
+    @Override
+    protected Transition getViewsTransition() {
+        if (!mSupportsTransition) {
+            return null;
+        }
+        return getWindow().getEnterTransition();
+    }
+
+    @Override
+    protected Transition getSharedElementTransition() {
+        if (!mSupportsTransition) {
+            return null;
+        }
+        return getWindow().getSharedElementEnterTransition();
+    }
+
+    @Override
+    protected void onStartEnterTransition(Transition transition, ArrayList<View> enteringViews) {
+        Drawable background = getDecor().getBackground();
+        if (background != null) {
+            ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 255);
+            animator.setDuration(FADE_BACKGROUND_DURATION_MS);
+            animator.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mMakeOpaque = true;
+                    if (mWasOpaque) {
+                        mActivity.convertFromTranslucent();
+                    }
+                }
+            });
+            animator.start();
+        } else if (mWasOpaque) {
+            transition.addListener(new Transition.TransitionListenerAdapter() {
+                @Override
+                public void onTransitionEnd(Transition transition) {
+                    mMakeOpaque = true;
+                    mActivity.convertFromTranslucent();
+                }
+            });
+        }
+        super.onStartEnterTransition(transition, enteringViews);
+    }
+
+    public ArrayList<View> readyEnteringViews() {
+        ArrayList<View> enteringViews = new ArrayList<View>();
+        getDecor().captureTransitioningViews(enteringViews);
+        if (getViewsTransition() != null) {
+            setViewVisibility(enteringViews, View.INVISIBLE);
+        }
+        return enteringViews;
+    }
+
+    @Override
+    protected void startExitTransition(ArrayList<String> sharedElements) {
+        mMakeOpaque = false;
+        notifyPrepareRestore();
+
+        if (getDecor().getBackground() == null) {
+            ColorDrawable black = new ColorDrawable(0xFF000000);
+            getWindow().setBackgroundDrawable(black);
+        }
+        if (mWasOpaque) {
+            mActivity.convertToTranslucent(new Activity.TranslucentConversionListener() {
+                @Override
+                public void onTranslucentConversionComplete(boolean drawComplete) {
+                    fadeOutBackground();
+                }
+            });
+        } else {
+            fadeOutBackground();
+        }
+
+        super.startExitTransition(sharedElements);
+    }
+
+    private void fadeOutBackground() {
+        ObjectAnimator animator = ObjectAnimator.ofInt(getDecor().getBackground(),
+                "alpha", 0);
+        animator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mBackgroundFadedOut = true;
+                if (mSharedElementTransitionComplete) {
+                    EnterTransitionCoordinator.super.onSharedElementTransitionEnd();
+                }
+            }
+        });
+        animator.setDuration(FADE_BACKGROUND_DURATION_MS);
+        animator.start();
+    }
+
+    @Override
+    protected void onExitTransitionEnd() {
+        mExitTransitionComplete = true;
+        exitAfterSharedElementTransition();
+        super.onExitTransitionEnd();
+    }
+
+    @Override
+    protected void onSharedElementTransitionEnd() {
+        mSharedElementTransitionComplete = true;
+        if (mBackgroundFadedOut) {
+            super.onSharedElementTransitionEnd();
+        }
+    }
+
+    @Override
+    protected boolean allowOverlappingTransitions() {
+        return getWindow().getAllowEnterTransitionOverlap();
+    }
+
+    private void exitAfterSharedElementTransition() {
+        if (mSharedElementTransitionComplete && mExitTransitionComplete && mBackgroundFadedOut) {
+            mActivity.finish();
+            if (mSupportsTransition) {
+                mActivity.overridePendingTransition(0, 0);
+            }
+            notifyExitTransitionComplete();
+            clearConnections();
+        }
+    }
+}
diff --git a/core/java/android/app/ExitTransitionCoordinator.java b/core/java/android/app/ExitTransitionCoordinator.java
new file mode 100644
index 0000000..d920787
--- /dev/null
+++ b/core/java/android/app/ExitTransitionCoordinator.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.app;
+
+import android.os.Bundle;
+import android.transition.Transition;
+import android.util.Pair;
+import android.view.View;
+import android.view.Window;
+
+import java.util.ArrayList;
+
+/**
+ * This ActivityTransitionCoordinator is created in ActivityOptions#makeSceneTransitionAnimation
+ * to govern the exit of the Scene and the shared elements when calling an Activity as well as
+ * the reentry of the Scene when coming back from the called Activity.
+ */
+class ExitTransitionCoordinator extends ActivityTransitionCoordinator {
+    private static final String TAG = "ExitTransitionCoordinator";
+
+    /**
+     * The Views that have exited and need to be restored to VISIBLE when returning to the
+     * normal state.
+     */
+    private ArrayList<View> mTransitioningViews;
+
+    /**
+     * Has the exit started? We don't want to accidentally exit multiple times.
+     */
+    private boolean mExitStarted;
+
+    /**
+     * Has the called Activity's ResultReceiver been set?
+     */
+    private boolean mIsResultReceiverSet;
+
+    /**
+     * Has the exit transition completed? If so, we can notify as soon as the ResultReceiver
+     * has been set.
+     */
+    private boolean mExitComplete;
+
+    /**
+     * Has the shared element transition completed? If so, we can notify as soon as the
+     * ResultReceiver has been set.
+     */
+    private Bundle mSharedElements;
+
+    /**
+     * Has the shared element transition completed?
+     */
+    private boolean mSharedElementsComplete;
+
+    public ExitTransitionCoordinator(Window window,
+            ActivityOptions.ActivityTransitionListener listener) {
+        super(window);
+        setActivityTransitionListener(listener);
+    }
+
+    @Override
+    protected void onSetResultReceiver() {
+        mIsResultReceiverSet = true;
+        notifyCompletions();
+    }
+
+    @Override
+    protected void onPrepareRestore() {
+        makeTransitioningViewsInvisible();
+        setEnteringViews(mTransitioningViews);
+        mTransitioningViews = null;
+        super.onPrepareRestore();
+    }
+
+    @Override
+    protected void onTakeSharedElements(ArrayList<String> sharedElementNames, Bundle state) {
+        super.onTakeSharedElements(sharedElementNames, state);
+        clearConnections();
+    }
+
+    @Override
+    protected void onActivityStopped() {
+        if (getViewsTransition() != null) {
+            setViewVisibility(mTransitioningViews, View.VISIBLE);
+        }
+        super.onActivityStopped();
+    }
+
+    @Override
+    protected void sharedElementTransitionComplete(Bundle bundle) {
+        mSharedElements = bundle;
+        mSharedElementsComplete = true;
+        notifyCompletions();
+    }
+
+    @Override
+    protected void onExitTransitionEnd() {
+        mExitComplete = true;
+        notifyCompletions();
+        super.onExitTransitionEnd();
+    }
+
+    private void notifyCompletions() {
+        if (mIsResultReceiverSet && mSharedElementsComplete) {
+            if (mSharedElements != null) {
+                notifySharedElementTransitionComplete(mSharedElements);
+                mSharedElements = null;
+            }
+            if (mExitComplete) {
+                notifyExitTransitionComplete();
+            }
+        }
+    }
+
+    @Override
+    public void startExit() {
+        if (!mExitStarted) {
+            mExitStarted = true;
+            setSharedElements();
+            startExitTransition(getSharedElementNames());
+        }
+    }
+
+    @Override
+    protected Transition getViewsTransition() {
+        if (!getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
+            return null;
+        }
+        return getWindow().getExitTransition();
+    }
+
+    @Override
+    protected Transition getSharedElementTransition() {
+        if (!getWindow().hasFeature(Window.FEATURE_CONTENT_TRANSITIONS)) {
+            return null;
+        }
+        return getWindow().getSharedElementExitTransition();
+    }
+
+    private void makeTransitioningViewsInvisible() {
+        if (getViewsTransition() != null) {
+            setViewVisibility(mTransitioningViews, View.INVISIBLE);
+        }
+    }
+
+    @Override
+    protected void onStartExitTransition(ArrayList<View> exitingViews) {
+        mTransitioningViews = new ArrayList<View>();
+        if (exitingViews != null) {
+            mTransitioningViews.addAll(exitingViews);
+        }
+        mTransitioningViews.addAll(getSharedElements());
+    }
+
+    @Override
+    protected boolean allowOverlappingTransitions() {
+        return getWindow().getAllowExitTransitionOverlap();
+    }
+}
diff --git a/core/java/android/app/IActivityContainer.aidl b/core/java/android/app/IActivityContainer.aidl
index 5b80e06..52884f7 100644
--- a/core/java/android/app/IActivityContainer.aidl
+++ b/core/java/android/app/IActivityContainer.aidl
@@ -26,10 +26,12 @@
 /** @hide */
 interface IActivityContainer {
     void attachToDisplay(int displayId);
-    void attachToSurface(in Surface surface, int width, int height, int density);
-    void detachFromDisplay();
+    void setSurface(in Surface surface, int width, int height, int density);
     int startActivity(in Intent intent);
     int startActivityIntentSender(in IIntentSender intentSender);
+    void checkEmbeddedAllowed(in Intent intent);
+    void checkEmbeddedAllowedIntentSender(in IIntentSender intentSender);
     int getDisplayId();
     boolean injectEvent(in InputEvent event);
+    void release();
 }
diff --git a/core/java/android/app/IActivityContainerCallback.aidl b/core/java/android/app/IActivityContainerCallback.aidl
index 55c2001..7f6d2c3 100644
--- a/core/java/android/app/IActivityContainerCallback.aidl
+++ b/core/java/android/app/IActivityContainerCallback.aidl
@@ -20,5 +20,5 @@
 
 /** @hide */
 interface IActivityContainerCallback {
-    oneway void onLastActivityRemoved(IBinder container);
+    oneway void setVisible(IBinder container, boolean visible);
 }
diff --git a/core/java/android/app/IActivityManager.java b/core/java/android/app/IActivityManager.java
index bfbd339..6b94c4e 100644
--- a/core/java/android/app/IActivityManager.java
+++ b/core/java/android/app/IActivityManager.java
@@ -47,6 +47,8 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.StrictMode;
+import android.service.voice.IVoiceInteractionSession;
+import com.android.internal.app.IVoiceInteractor;
 
 import java.util.List;
 
@@ -77,9 +79,13 @@
             IntentSender intent, Intent fillInIntent, String resolvedType,
             IBinder resultTo, String resultWho, int requestCode,
             int flagsMask, int flagsValues, Bundle options) throws RemoteException;
+    public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
+            Intent intent, String resolvedType, IVoiceInteractionSession session,
+            IVoiceInteractor interactor, int flags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) throws RemoteException;
     public boolean startNextMatchingActivity(IBinder callingActivity,
             Intent intent, Bundle options) throws RemoteException;
-    public boolean finishActivity(IBinder token, int code, Intent data)
+    public boolean finishActivity(IBinder token, int code, Intent data, boolean finishTask)
             throws RemoteException;
     public void finishSubActivity(IBinder token, String resultWho, int requestCode) throws RemoteException;
     public boolean finishActivityAffinity(IBinder token) throws RemoteException;
@@ -733,4 +739,5 @@
     int STOP_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+215;
     int IS_IN_LOCK_TASK_MODE_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+216;
     int SET_ACTIVITY_LABEL_ICON_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+217;
+    int START_VOICE_ACTIVITY_TRANSACTION = IBinder.FIRST_CALL_TRANSACTION+218;
 }
diff --git a/core/java/android/app/IApplicationThread.java b/core/java/android/app/IApplicationThread.java
index ac8ac8f..f290e94 100644
--- a/core/java/android/app/IApplicationThread.java
+++ b/core/java/android/app/IApplicationThread.java
@@ -31,6 +31,8 @@
 import android.os.RemoteException;
 import android.os.IBinder;
 import android.os.IInterface;
+import android.service.voice.IVoiceInteractionSession;
+import com.android.internal.app.IVoiceInteractor;
 
 import java.io.FileDescriptor;
 import java.util.List;
@@ -55,8 +57,9 @@
     void scheduleSendResult(IBinder token, List<ResultInfo> results) throws RemoteException;
     void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
             ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
-            int procState, Bundle state, List<ResultInfo> pendingResults,
-            List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
+            IVoiceInteractor voiceInteractor, int procState, Bundle state,
+            List<ResultInfo> pendingResults, List<Intent> pendingNewIntents, boolean notResumed,
+            boolean isForward,
             String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler,
             Bundle resumeArgs)
             throws RemoteException;
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl
index 9911467..ad4027d 100644
--- a/core/java/android/app/INotificationManager.aidl
+++ b/core/java/android/app/INotificationManager.aidl
@@ -18,11 +18,16 @@
 package android.app;
 
 import android.app.ITransientNotification;
-import android.service.notification.StatusBarNotification;
 import android.app.Notification;
 import android.content.ComponentName;
 import android.content.Intent;
+import android.net.Uri;
+import android.service.notification.Condition;
+import android.service.notification.IConditionListener;
+import android.service.notification.IConditionProvider;
 import android.service.notification.INotificationListener;
+import android.service.notification.StatusBarNotification;
+import android.service.notification.ZenModeConfig;
 
 /** {@hide} */
 interface INotificationManager
@@ -31,7 +36,7 @@
 
     void enqueueToast(String pkg, ITransientNotification callback, int duration);
     void cancelToast(String pkg, ITransientNotification callback);
-    void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+    void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
             in Notification notification, inout int[] idReceived, int userId);
     void cancelNotificationWithTag(String pkg, String tag, int id, int userId);
 
@@ -49,4 +54,10 @@
 
     StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
     String[] getActiveNotificationKeysFromListener(in INotificationListener token);
+
+    ZenModeConfig getZenModeConfig();
+    boolean setZenModeConfig(in ZenModeConfig config);
+    oneway void notifyConditions(String pkg, in IConditionProvider provider, in Condition[] conditions);
+    oneway void requestZenModeConditions(in IConditionListener callback, boolean requested);
+    oneway void setZenModeCondition(in Uri conditionId);
 }
\ No newline at end of file
diff --git a/core/java/android/app/IProcessObserver.aidl b/core/java/android/app/IProcessObserver.aidl
index e587912..ecf2c73 100644
--- a/core/java/android/app/IProcessObserver.aidl
+++ b/core/java/android/app/IProcessObserver.aidl
@@ -20,7 +20,7 @@
 oneway interface IProcessObserver {
 
     void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities);
-    void onImportanceChanged(int pid, int uid, int importance);
+    void onProcessStateChanged(int pid, int uid, int procState);
     void onProcessDied(int pid, int uid);
 
 }
diff --git a/core/java/android/app/IUiAutomationConnection.aidl b/core/java/android/app/IUiAutomationConnection.aidl
index 09bf829..347de97 100644
--- a/core/java/android/app/IUiAutomationConnection.aidl
+++ b/core/java/android/app/IUiAutomationConnection.aidl
@@ -19,6 +19,8 @@
 import android.accessibilityservice.IAccessibilityServiceClient;
 import android.graphics.Bitmap;
 import android.view.InputEvent;
+import android.view.WindowContentFrameStats;
+import android.view.WindowAnimationFrameStats;
 import android.os.ParcelFileDescriptor;
 
 /**
@@ -26,7 +28,7 @@
  * on behalf of an instrumentation that it runs. These operations require
  * special permissions which the shell user has but the instrumentation does
  * not. Running privileged operations by the shell user on behalf of an
- * instrumentation is needed for running UiTestCases. 
+ * instrumentation is needed for running UiTestCases.
  *
  * {@hide}
  */
@@ -37,4 +39,8 @@
     boolean setRotation(int rotation);
     Bitmap takeScreenshot(int width, int height);
     void shutdown();
+    boolean clearWindowContentFrameStats(int windowId);
+    WindowContentFrameStats getWindowContentFrameStats(int windowId);
+    void clearWindowAnimationFrameStats();
+    WindowAnimationFrameStats getWindowAnimationFrameStats();
 }
diff --git a/core/java/android/app/Instrumentation.java b/core/java/android/app/Instrumentation.java
index 028fa68..e58ccb8 100644
--- a/core/java/android/app/Instrumentation.java
+++ b/core/java/android/app/Instrumentation.java
@@ -1428,7 +1428,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
+     * Like {@link #execStartActivity},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1442,7 +1442,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
+     * Like {@link #execStartActivity},
      * but accepts an array of activities to be started.  Note that active
      * {@link ActivityMonitor} objects only match against the first activity in
      * the array.
@@ -1545,8 +1545,7 @@
     }
 
     /**
-     * Like {@link #execStartActivity(Context, IBinder, IBinder, Activity, Intent, int)},
-     * but for starting as a particular user.
+     * Like {@link #execStartActivity}, but for starting as a particular user.
      *
      * @param who The Context from which the activity is being started.
      * @param contextThread The main thread of the Context from which the activity
@@ -1616,7 +1615,8 @@
         mUiAutomationConnection = uiAutomationConnection;
     }
 
-    /*package*/ static void checkStartActivityResult(int res, Object intent) {
+    /** @hide */
+    public static void checkStartActivityResult(int res, Object intent) {
         if (res >= ActivityManager.START_SUCCESS) {
             return;
         }
@@ -1640,6 +1640,9 @@
             case ActivityManager.START_NOT_ACTIVITY:
                 throw new IllegalArgumentException(
                         "PendingIntent is not an activity");
+            case ActivityManager.START_NOT_VOICE_COMPATIBLE:
+                throw new SecurityException(
+                        "Starting under voice control not allowed for: " + intent);
             default:
                 throw new AndroidRuntimeException("Unknown error code "
                         + res + " when starting " + intent);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 36d2635..25a1493 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -328,8 +328,8 @@
 
     /**
      * Bit to be bitwise-ored into the {@link #flags} field that should be
-     * set if you want the sound and/or vibration play each time the
-     * notification is sent, even if it has not been canceled before that.
+     * set if you would only like the sound, vibrate and ticker to be played
+     * if the notification was not already showing.
      */
     public static final int FLAG_ONLY_ALERT_ONCE    = 0x00000008;
 
@@ -1311,6 +1311,7 @@
         private Notification mPublicVersion = null;
         private boolean mQuantumTheme;
         private final LegacyNotificationUtil mLegacyNotificationUtil;
+        private ArrayList<String> mPeople;
 
         /**
          * Constructs a new Builder with the defaults:
@@ -1338,6 +1339,7 @@
             mWhen = System.currentTimeMillis();
             mAudioStreamType = STREAM_DEFAULT;
             mPriority = PRIORITY_DEFAULT;
+            mPeople = new ArrayList<String>();
 
             // TODO: Decide on targetSdk from calling app whether to use quantum theme.
             mQuantumTheme = true;
@@ -1723,6 +1725,16 @@
         }
 
         /**
+         * Add a person that is relevant to this notification.
+         *
+         * @see Notification#EXTRA_PEOPLE
+         */
+        public Builder addPerson(String handle) {
+            mPeople.add(handle);
+            return this;
+        }
+
+        /**
          * Merge additional metadata into this notification.
          *
          * <p>Values within the Bundle will replace existing extras values in this Builder.
@@ -2149,6 +2161,9 @@
             if (mLargeIcon != null) {
                 extras.putParcelable(EXTRA_LARGE_ICON, mLargeIcon);
             }
+            if (!mPeople.isEmpty()) {
+                extras.putStringArray(EXTRA_PEOPLE, mPeople.toArray(new String[mPeople.size()]));
+            }
         }
 
         /**
diff --git a/core/java/android/app/SharedPreferencesImpl.java b/core/java/android/app/SharedPreferencesImpl.java
index 1b838fb..4427ce1 100644
--- a/core/java/android/app/SharedPreferencesImpl.java
+++ b/core/java/android/app/SharedPreferencesImpl.java
@@ -19,6 +19,9 @@
 import android.content.SharedPreferences;
 import android.os.FileUtils;
 import android.os.Looper;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.util.Log;
 
 import com.google.android.collect.Maps;
@@ -43,10 +46,7 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
 
 final class SharedPreferencesImpl implements SharedPreferences {
     private static final String TAG = "SharedPreferencesImpl";
@@ -110,7 +110,7 @@
         Map map = null;
         StructStat stat = null;
         try {
-            stat = Libcore.os.stat(mFile.getPath());
+            stat = Os.stat(mFile.getPath());
             if (mFile.canRead()) {
                 BufferedInputStream str = null;
                 try {
@@ -172,7 +172,7 @@
              * violation, but we explicitly want this one.
              */
             BlockGuard.getThreadPolicy().onReadFromDisk();
-            stat = Libcore.os.stat(mFile.getPath());
+            stat = Os.stat(mFile.getPath());
         } catch (ErrnoException e) {
             return true;
         }
@@ -599,7 +599,7 @@
             str.close();
             ContextImpl.setFilePermissionsFromMode(mFile.getPath(), mMode, 0);
             try {
-                final StructStat stat = Libcore.os.stat(mFile.getPath());
+                final StructStat stat = Os.stat(mFile.getPath());
                 synchronized (this) {
                     mStatTimestamp = stat.st_mtime;
                     mStatSize = stat.st_size;
diff --git a/core/java/android/app/StatusBarManager.java b/core/java/android/app/StatusBarManager.java
index a6a04d1..5cf61a8 100644
--- a/core/java/android/app/StatusBarManager.java
+++ b/core/java/android/app/StatusBarManager.java
@@ -41,8 +41,6 @@
     @Deprecated
     public static final int DISABLE_NOTIFICATION_TICKER
             = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
-    public static final int DISABLE_PRIVATE_NOTIFICATIONS
-            = View.STATUS_BAR_DISABLE_NOTIFICATION_TICKER;
     public static final int DISABLE_SYSTEM_INFO = View.STATUS_BAR_DISABLE_SYSTEM_INFO;
     public static final int DISABLE_HOME = View.STATUS_BAR_DISABLE_HOME;
     public static final int DISABLE_RECENT = View.STATUS_BAR_DISABLE_RECENT;
diff --git a/core/java/android/app/UiAutomation.java b/core/java/android/app/UiAutomation.java
index 354a19f..9405325 100644
--- a/core/java/android/app/UiAutomation.java
+++ b/core/java/android/app/UiAutomation.java
@@ -33,6 +33,8 @@
 import android.view.InputEvent;
 import android.view.KeyEvent;
 import android.view.Surface;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityInteractionClient;
 import android.view.accessibility.AccessibilityNodeInfo;
@@ -295,6 +297,28 @@
     }
 
     /**
+     * Find the view that has the specified focus type. The search is performed
+     * across all windows.
+     * <p>
+     * <strong>Note:</strong> In order to access the windows you have to opt-in
+     * to retrieve the interactive windows by setting the
+     * {@link AccessibilityServiceInfo#FLAG_RETRIEVE_INTERACTIVE_WINDOWS} flag.
+     * Otherwise, the search will be performed only in the active window.
+     * </p>
+     *
+     * @param focus The focus to find. One of {@link AccessibilityNodeInfo#FOCUS_INPUT} or
+     *         {@link AccessibilityNodeInfo#FOCUS_ACCESSIBILITY}.
+     * @return The node info of the focused view or null.
+     *
+     * @see AccessibilityNodeInfo#FOCUS_INPUT
+     * @see AccessibilityNodeInfo#FOCUS_ACCESSIBILITY
+     */
+    public AccessibilityNodeInfo findFocus(int focus) {
+        return AccessibilityInteractionClient.getInstance().findFocus(mConnectionId,
+                AccessibilityNodeInfo.ANY_WINDOW_ID, AccessibilityNodeInfo.ROOT_NODE_ID, focus);
+    }
+
+    /**
      * Gets the an {@link AccessibilityServiceInfo} describing this UiAutomation.
      * This method is useful if one wants to change some of the dynamically
      * configurable properties at runtime.
@@ -674,6 +698,148 @@
         }
     }
 
+    /**
+     * Clears the frame statistics for the content of a given window. These
+     * statistics contain information about the most recently rendered content
+     * frames.
+     *
+     * @param windowId The window id.
+     * @return Whether the window is present and its frame statistics
+     *         were cleared.
+     *
+     * @see android.view.WindowContentFrameStats
+     * @see #getWindowContentFrameStats(int)
+     * @see #getWindows()
+     * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+     */
+    public boolean clearWindowContentFrameStats(int windowId) {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Clearing content frame stats for window: " + windowId);
+            }
+            // Calling out without a lock held.
+            return mUiAutomationConnection.clearWindowContentFrameStats(windowId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error clearing window content frame stats!", re);
+        }
+        return false;
+    }
+
+    /**
+     * Gets the frame statistics for a given window. These statistics contain
+     * information about the most recently rendered content frames.
+     * <p>
+     * A typical usage requires clearing the window frame statistics via {@link
+     * #clearWindowContentFrameStats(int)} followed by an interaction with the UI and
+     * finally getting the window frame statistics via calling this method.
+     * </p>
+     * <pre>
+     * // Assume we have at least one window.
+     * final int windowId = getWindows().get(0).getId();
+     *
+     * // Start with a clean slate.
+     * uiAutimation.clearWindowContentFrameStats(windowId);
+     *
+     * // Do stuff with the UI.
+     *
+     * // Get the frame statistics.
+     * WindowContentFrameStats stats = uiAutomation.getWindowContentFrameStats(windowId);
+     * </pre>
+     *
+     * @param windowId The window id.
+     * @return The window frame statistics, or null if the window is not present.
+     *
+     * @see android.view.WindowContentFrameStats
+     * @see #clearWindowContentFrameStats(int)
+     * @see #getWindows()
+     * @see AccessibilityWindowInfo#getId() AccessibilityWindowInfo.getId()
+     */
+    public WindowContentFrameStats getWindowContentFrameStats(int windowId) {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Getting content frame stats for window: " + windowId);
+            }
+            // Calling out without a lock held.
+            return mUiAutomationConnection.getWindowContentFrameStats(windowId);
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error getting window content frame stats!", re);
+        }
+        return null;
+    }
+
+    /**
+     * Clears the window animation rendering statistics. These statistics contain
+     * information about the most recently rendered window animation frames, i.e.
+     * for window transition animations.
+     *
+     * @see android.view.WindowAnimationFrameStats
+     * @see #getWindowAnimationFrameStats()
+     * @see android.R.styleable#WindowAnimation
+     */
+    public void clearWindowAnimationFrameStats() {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Clearing window animation frame stats");
+            }
+            // Calling out without a lock held.
+            mUiAutomationConnection.clearWindowAnimationFrameStats();
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error clearing window animation frame stats!", re);
+        }
+    }
+
+    /**
+     * Gets the window animation frame statistics. These statistics contain
+     * information about the most recently rendered window animation frames, i.e.
+     * for window transition animations.
+     *
+     * <p>
+     * A typical usage requires clearing the window animation frame statistics via
+     * {@link #clearWindowAnimationFrameStats()} followed by an interaction that causes
+     * a window transition which uses a window animation and finally getting the window
+     * animation frame statistics by calling this method.
+     * </p>
+     * <pre>
+     * // Start with a clean slate.
+     * uiAutimation.clearWindowAnimationFrameStats();
+     *
+     * // Do stuff to trigger a window transition.
+     *
+     * // Get the frame statistics.
+     * WindowAnimationFrameStats stats = uiAutomation.getWindowAnimationFrameStats();
+     * </pre>
+     *
+     * @return The window animation frame statistics.
+     *
+     * @see android.view.WindowAnimationFrameStats
+     * @see #clearWindowAnimationFrameStats()
+     * @see android.R.styleable#WindowAnimation
+     */
+    public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+        synchronized (mLock) {
+            throwIfNotConnectedLocked();
+        }
+        try {
+            if (DEBUG) {
+                Log.i(LOG_TAG, "Getting window animation frame stats");
+            }
+            // Calling out without a lock held.
+            return mUiAutomationConnection.getWindowAnimationFrameStats();
+        } catch (RemoteException re) {
+            Log.e(LOG_TAG, "Error getting window animation frame stats!", re);
+        }
+        return null;
+    }
+
     private static float getDegreesForRotation(int value) {
         switch (value) {
             case Surface.ROTATION_90: {
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 91b0d7c..fa40286 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -22,12 +22,15 @@
 import android.graphics.Bitmap;
 import android.hardware.input.InputManager;
 import android.os.Binder;
+import android.os.IBinder;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.view.IWindowManager;
 import android.view.InputEvent;
 import android.view.SurfaceControl;
+import android.view.WindowAnimationFrameStats;
+import android.view.WindowContentFrameStats;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.IAccessibilityManager;
 
@@ -47,6 +50,9 @@
     private final IWindowManager mWindowManager = IWindowManager.Stub.asInterface(
             ServiceManager.getService(Service.WINDOW_SERVICE));
 
+    private final IAccessibilityManager mAccessibilityManager = IAccessibilityManager.Stub.asInterface(
+            ServiceManager.getService(Service.ACCESSIBILITY_SERVICE));
+
     private final Object mLock = new Object();
 
     private final Binder mToken = new Binder();
@@ -144,6 +150,76 @@
     }
 
     @Override
+    public boolean clearWindowContentFrameStats(int windowId) throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            IBinder token = mAccessibilityManager.getWindowToken(windowId);
+            if (token == null) {
+                return false;
+            }
+            return mWindowManager.clearWindowContentFrameStats(token);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public WindowContentFrameStats getWindowContentFrameStats(int windowId) throws RemoteException {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            IBinder token = mAccessibilityManager.getWindowToken(windowId);
+            if (token == null) {
+                return null;
+            }
+            return mWindowManager.getWindowContentFrameStats(token);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public void clearWindowAnimationFrameStats() {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            SurfaceControl.clearAnimationFrameStats();
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
+    public WindowAnimationFrameStats getWindowAnimationFrameStats() {
+        synchronized (mLock) {
+            throwIfCalledByNotTrustedUidLocked();
+            throwIfShutdownLocked();
+            throwIfNotConnectedLocked();
+        }
+        final long identity = Binder.clearCallingIdentity();
+        try {
+            WindowAnimationFrameStats stats = new WindowAnimationFrameStats();
+            SurfaceControl.getAnimationFrameStats(stats);
+            return stats;
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void shutdown() {
         synchronized (mLock) {
             if (isConnectedLocked()) {
diff --git a/core/java/android/app/VoiceInteractor.java b/core/java/android/app/VoiceInteractor.java
new file mode 100644
index 0000000..6dc48b0
--- /dev/null
+++ b/core/java/android/app/VoiceInteractor.java
@@ -0,0 +1,275 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.IVoiceInteractorCallback;
+import com.android.internal.app.IVoiceInteractorRequest;
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+import java.util.WeakHashMap;
+
+/**
+ * Interface for an {@link Activity} to interact with the user through voice.
+ */
+public class VoiceInteractor {
+    static final String TAG = "VoiceInteractor";
+    static final boolean DEBUG = true;
+
+    final Context mContext;
+    final Activity mActivity;
+    final IVoiceInteractor mInteractor;
+    final HandlerCaller mHandlerCaller;
+    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+        @Override
+        public void executeMessage(Message msg) {
+            SomeArgs args = (SomeArgs)msg.obj;
+            Request request;
+            switch (msg.what) {
+                case MSG_CONFIRMATION_RESULT:
+                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
+                    if (DEBUG) Log.d(TAG, "onConfirmResult: req="
+                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
+                            + " confirmed=" + msg.arg1 + " result=" + args.arg2);
+                    if (request != null) {
+                        ((ConfirmationRequest)request).onConfirmationResult(msg.arg1 != 0,
+                                (Bundle) args.arg2);
+                        request.clear();
+                    }
+                    break;
+                case MSG_COMMAND_RESULT:
+                    request = pullRequest((IVoiceInteractorRequest)args.arg1, msg.arg1 != 0);
+                    if (DEBUG) Log.d(TAG, "onCommandResult: req="
+                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request
+                            + " result=" + args.arg2);
+                    if (request != null) {
+                        ((CommandRequest)request).onCommandResult((Bundle) args.arg2);
+                        if (msg.arg1 != 0) {
+                            request.clear();
+                        }
+                    }
+                    break;
+                case MSG_CANCEL_RESULT:
+                    request = pullRequest((IVoiceInteractorRequest)args.arg1, true);
+                    if (DEBUG) Log.d(TAG, "onCancelResult: req="
+                            + ((IVoiceInteractorRequest)args.arg1).asBinder() + "/" + request);
+                    if (request != null) {
+                        request.onCancel();
+                        request.clear();
+                    }
+                    break;
+            }
+        }
+    };
+
+    final IVoiceInteractorCallback.Stub mCallback = new IVoiceInteractorCallback.Stub() {
+        @Override
+        public void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed,
+                Bundle result) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
+                    MSG_CONFIRMATION_RESULT, confirmed ? 1 : 0, request, result));
+        }
+
+        @Override
+        public void deliverCommandResult(IVoiceInteractorRequest request, boolean complete,
+                Bundle result) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageIOO(
+                    MSG_COMMAND_RESULT, complete ? 1 : 0, request, result));
+        }
+
+        @Override
+        public void deliverCancel(IVoiceInteractorRequest request) throws RemoteException {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(
+                    MSG_CANCEL_RESULT, request));
+        }
+    };
+
+    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+
+    static final int MSG_CONFIRMATION_RESULT = 1;
+    static final int MSG_COMMAND_RESULT = 2;
+    static final int MSG_CANCEL_RESULT = 3;
+
+    public static abstract class Request {
+        IVoiceInteractorRequest mRequestInterface;
+        Context mContext;
+        Activity mActivity;
+
+        public Request() {
+        }
+
+        public void cancel() {
+            try {
+                mRequestInterface.cancel();
+            } catch (RemoteException e) {
+                Log.w(TAG, "Voice interactor has died", e);
+            }
+        }
+
+        public Context getContext() {
+            return mContext;
+        }
+
+        public Activity getActivity() {
+            return mActivity;
+        }
+
+        public void onCancel() {
+        }
+
+        void clear() {
+            mRequestInterface = null;
+            mContext = null;
+            mActivity = null;
+        }
+
+        abstract IVoiceInteractorRequest submit(IVoiceInteractor interactor,
+                String packageName, IVoiceInteractorCallback callback) throws RemoteException;
+    }
+
+    public static class ConfirmationRequest extends Request {
+        final CharSequence mPrompt;
+        final Bundle mExtras;
+
+        /**
+         * Confirms an operation with the user via the trusted system
+         * VoiceInteractionService.  This allows an Activity to complete an unsafe operation that
+         * would require the user to touch the screen when voice interaction mode is not enabled.
+         * The result of the confirmation will be returned through an asynchronous call to
+         * either {@link #onConfirmationResult(boolean, android.os.Bundle)} or
+         * {@link #onCancel()}.
+         *
+         * <p>In some cases this may be a simple yes / no confirmation or the confirmation could
+         * include context information about how the action will be completed
+         * (e.g. booking a cab might include details about how long until the cab arrives)
+         * so the user can give a confirmation.
+         * @param prompt Optional confirmation text to read to the user as the action being
+         * confirmed.
+         * @param extras Additional optional information.
+         */
+        public ConfirmationRequest(CharSequence prompt, Bundle extras) {
+            mPrompt = prompt;
+            mExtras = extras;
+        }
+
+        public void onConfirmationResult(boolean confirmed, Bundle result) {
+        }
+
+        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
+                IVoiceInteractorCallback callback) throws RemoteException {
+            return interactor.startConfirmation(packageName, callback, mPrompt.toString(), mExtras);
+        }
+   }
+
+    public static class CommandRequest extends Request {
+        final String mCommand;
+        final Bundle mArgs;
+
+        /**
+         * Execute a command using the trusted system VoiceInteractionService.
+         * This allows an Activity to request additional information from the user needed to
+         * complete an action (e.g. booking a table might have several possible times that the
+         * user could select from or an app might need the user to agree to a terms of service).
+         * The result of the confirmation will be returned through an asynchronous call to
+         * either {@link #onCommandResult(android.os.Bundle)} or
+         * {@link #onCancel()}.
+         *
+         * <p>The command is a string that describes the generic operation to be performed.
+         * The command will determine how the properties in extras are interpreted and the set of
+         * available commands is expected to grow over time.  An example might be
+         * "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number of bags as part of
+         * airline check-in.  (This is not an actual working example.)
+         *
+         * @param command The desired command to perform.
+         * @param args Additional arguments to control execution of the command.
+         */
+        public CommandRequest(String command, Bundle args) {
+            mCommand = command;
+            mArgs = args;
+        }
+
+        public void onCommandResult(Bundle result) {
+        }
+
+        IVoiceInteractorRequest submit(IVoiceInteractor interactor, String packageName,
+                IVoiceInteractorCallback callback) throws RemoteException {
+            return interactor.startConfirmation(packageName, callback, mCommand, mArgs);
+        }
+   }
+
+    VoiceInteractor(Context context, Activity activity, IVoiceInteractor interactor,
+            Looper looper) {
+        mContext = context;
+        mActivity = activity;
+        mInteractor = interactor;
+        mHandlerCaller = new HandlerCaller(context, looper, mHandlerCallerCallback, true);
+    }
+
+    Request pullRequest(IVoiceInteractorRequest request, boolean complete) {
+        synchronized (mActiveRequests) {
+            Request req = mActiveRequests.get(request.asBinder());
+            if (req != null && complete) {
+                mActiveRequests.remove(request.asBinder());
+            }
+            return req;
+        }
+    }
+
+    public boolean submitRequest(Request request) {
+        try {
+            IVoiceInteractorRequest ireq = request.submit(mInteractor,
+                    mContext.getOpPackageName(), mCallback);
+            request.mRequestInterface = ireq;
+            request.mContext = mContext;
+            request.mActivity = mActivity;
+            synchronized (mActiveRequests) {
+                mActiveRequests.put(ireq.asBinder(), request);
+            }
+            return true;
+        } catch (RemoteException e) {
+            Log.w(TAG, "Remove voice interactor service died", e);
+            return false;
+        }
+    }
+
+    /**
+     * Queries the supported commands available from the VoiceinteractionService.
+     * The command is a string that describes the generic operation to be performed.
+     * An example might be "com.google.voice.commands.REQUEST_NUMBER_BAGS" to request the number
+     * of bags as part of airline check-in.  (This is not an actual working example.)
+     *
+     * @param commands
+     */
+    public boolean[] supportsCommands(String[] commands) {
+        try {
+            boolean[] res = mInteractor.supportsCommands(mContext.getOpPackageName(), commands);
+            if (DEBUG) Log.d(TAG, "supportsCommands: cmds=" + commands + " res=" + res);
+            return res;
+        } catch (RemoteException e) {
+            throw new RuntimeException("Voice interactor has died", e);
+        }
+    }
+}
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index e6e0f35..58d707c 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -16,6 +16,7 @@
 
 package android.app;
 
+import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -44,10 +45,14 @@
 import android.os.ParcelFileDescriptor;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.os.SystemProperties;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.WindowManagerGlobal;
 
 import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -65,6 +70,11 @@
     private float mWallpaperXStep = -1;
     private float mWallpaperYStep = -1;
 
+    /** {@hide} */
+    private static final String PROP_WALLPAPER = "ro.config.wallpaper";
+    /** {@hide} */
+    private static final String PROP_WALLPAPER_COMPONENT = "ro.config.wallpaper_component";
+
     /**
      * Activity Action: Show settings for choosing wallpaper. Do not use directly to construct
      * an intent; instead, use {@link #getCropAndSetWallpaperIntent}.
@@ -269,13 +279,15 @@
         }
 
         private Bitmap getCurrentWallpaperLocked(Context context) {
+            if (mService == null) {
+                Log.w(TAG, "WallpaperService not running");
+                return null;
+            }
+
             try {
                 Bundle params = new Bundle();
                 ParcelFileDescriptor fd = mService.getWallpaper(this, params);
                 if (fd != null) {
-                    int width = params.getInt("width", 0);
-                    int height = params.getInt("height", 0);
-
                     try {
                         BitmapFactory.Options options = new BitmapFactory.Options();
                         return BitmapFactory.decodeFileDescriptor(
@@ -297,28 +309,20 @@
         }
         
         private Bitmap getDefaultWallpaperLocked(Context context) {
-            try {
-                InputStream is = context.getResources().openRawResource(
-                        com.android.internal.R.drawable.default_wallpaper);
-                if (is != null) {
-                    int width = mService.getWidthHint();
-                    int height = mService.getHeightHint();
-
+            InputStream is = openDefaultWallpaper(context);
+            if (is != null) {
+                try {
+                    BitmapFactory.Options options = new BitmapFactory.Options();
+                    return BitmapFactory.decodeStream(is, null, options);
+                } catch (OutOfMemoryError e) {
+                    Log.w(TAG, "Can't decode stream", e);
+                } finally {
                     try {
-                        BitmapFactory.Options options = new BitmapFactory.Options();
-                        return BitmapFactory.decodeStream(is, null, options);
-                    } catch (OutOfMemoryError e) {
-                        Log.w(TAG, "Can't decode stream", e);
-                    } finally {
-                        try {
-                            is.close();
-                        } catch (IOException e) {
-                            // Ignore
-                        }
+                        is.close();
+                    } catch (IOException e) {
+                        // Ignore
                     }
                 }
-            } catch (RemoteException e) {
-                // Ignore
             }
             return null;
         }
@@ -403,8 +407,7 @@
         horizontalAlignment = Math.max(0, Math.min(1, horizontalAlignment));
         verticalAlignment = Math.max(0, Math.min(1, verticalAlignment));
 
-        InputStream is = new BufferedInputStream(
-                resources.openRawResource(com.android.internal.R.drawable.default_wallpaper));
+        InputStream is = new BufferedInputStream(openDefaultWallpaper(mContext));
 
         if (is == null) {
             Log.e(TAG, "default wallpaper input stream is null");
@@ -429,8 +432,7 @@
                     }
                 }
 
-                is = new BufferedInputStream(resources.openRawResource(
-                        com.android.internal.R.drawable.default_wallpaper));
+                is = new BufferedInputStream(openDefaultWallpaper(mContext));
 
                 RectF cropRectF;
 
@@ -479,8 +481,7 @@
 
                 if (crop == null) {
                     // BitmapRegionDecoder has failed, try to crop in-memory
-                    is = new BufferedInputStream(resources.openRawResource(
-                            com.android.internal.R.drawable.default_wallpaper));
+                    is = new BufferedInputStream(openDefaultWallpaper(mContext));
                     Bitmap fullSize = null;
                     if (is != null) {
                         BitmapFactory.Options options = new BitmapFactory.Options();
@@ -650,6 +651,10 @@
      *         not "image/*"
      */
     public Intent getCropAndSetWallpaperIntent(Uri imageUri) {
+        if (imageUri == null) {
+            throw new IllegalArgumentException("Image URI must not be null");
+        }
+
         if (!ContentResolver.SCHEME_CONTENT.equals(imageUri.getScheme())) {
             throw new IllegalArgumentException("Image URI must be of the "
                     + ContentResolver.SCHEME_CONTENT + " scheme type");
@@ -1009,6 +1014,53 @@
      * wallpaper.
      */
     public void clear() throws IOException {
-        setResource(com.android.internal.R.drawable.default_wallpaper);
+        setStream(openDefaultWallpaper(mContext));
+    }
+
+    /**
+     * Open stream representing the default static image wallpaper.
+     *
+     * @hide
+     */
+    public static InputStream openDefaultWallpaper(Context context) {
+        final String path = SystemProperties.get(PROP_WALLPAPER);
+        if (!TextUtils.isEmpty(path)) {
+            final File file = new File(path);
+            if (file.exists()) {
+                try {
+                    return new FileInputStream(file);
+                } catch (IOException e) {
+                    // Ignored, fall back to platform default below
+                }
+            }
+        }
+        return context.getResources().openRawResource(
+                com.android.internal.R.drawable.default_wallpaper);
+    }
+
+    /**
+     * Return {@link ComponentName} of the default live wallpaper, or
+     * {@code null} if none is defined.
+     *
+     * @hide
+     */
+    public static ComponentName getDefaultWallpaperComponent(Context context) {
+        String flat = SystemProperties.get(PROP_WALLPAPER_COMPONENT);
+        if (!TextUtils.isEmpty(flat)) {
+            final ComponentName cn = ComponentName.unflattenFromString(flat);
+            if (cn != null) {
+                return cn;
+            }
+        }
+
+        flat = context.getString(com.android.internal.R.string.default_wallpaper_component);
+        if (!TextUtils.isEmpty(flat)) {
+            final ComponentName cn = ComponentName.unflattenFromString(flat);
+            if (cn != null) {
+                return cn;
+            }
+        }
+
+        return null;
     }
 }
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 30c84f6..6f68dfb 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -26,12 +26,14 @@
 import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
+import android.os.Bundle;
 import android.os.Handler;
 import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.service.trust.TrustAgentService;
 import android.util.Log;
 
 import com.android.org.conscrypt.TrustedCertificateStore;
@@ -170,6 +172,16 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SET_NEW_PASSWORD
             = "android.app.action.SET_NEW_PASSWORD";
+    /**
+     * Flag for {@link #forwardMatchingIntents}: the intents will forwarded to the primary user.
+     */
+    public static int FLAG_TO_PRIMARY_USER = 0x0001;
+
+    /**
+     * Flag for {@link #forwardMatchingIntents}: the intents will be forwarded to the managed
+     * profile.
+     */
+    public static int FLAG_TO_MANAGED_PROFILE = 0x0002;
 
     /**
      * Return true if the given administrator component is currently
@@ -1266,7 +1278,7 @@
     public static final int KEYGUARD_DISABLE_FEATURES_NONE = 0;
 
     /**
-     * Disable all keyguard widgets
+     * Disable all keyguard widgets. Has no effect.
      */
     public static final int KEYGUARD_DISABLE_WIDGETS_ALL = 1 << 0;
 
@@ -1276,6 +1288,22 @@
     public static final int KEYGUARD_DISABLE_SECURE_CAMERA = 1 << 1;
 
     /**
+     * Disable showing all notifications on secure keyguard screens (e.g. PIN/Pattern/Password)
+     */
+    public static final int KEYGUARD_DISABLE_SECURE_NOTIFICATIONS = 1 << 2;
+
+    /**
+     * Only allow redacted notifications on secure keyguard screens (e.g. PIN/Pattern/Password)
+     */
+    public static final int KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS = 1 << 3;
+
+    /**
+     * Ignore {@link TrustAgentService} state on secure keyguard screens
+     * (e.g. PIN/Pattern/Password).
+     */
+    public static final int KEYGUARD_DISABLE_TRUST_AGENTS = 1 << 4;
+
+    /**
      * Disable all current and future keyguard customizations.
      */
     public static final int KEYGUARD_DISABLE_FEATURES_ALL = 0x7fffffff;
@@ -1495,7 +1523,8 @@
      * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
      * @param which {@link #KEYGUARD_DISABLE_FEATURES_NONE} (default),
      * {@link #KEYGUARD_DISABLE_WIDGETS_ALL}, {@link #KEYGUARD_DISABLE_SECURE_CAMERA},
-     * {@link #KEYGUARD_DISABLE_FEATURES_ALL}
+     * {@link #KEYGUARD_DISABLE_SECURE_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_TRUST_AGENTS},
+     * {@link #KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS}, {@link #KEYGUARD_DISABLE_FEATURES_ALL}
      */
     public void setKeyguardDisabledFeatures(ComponentName admin, int which) {
         if (mService != null) {
@@ -1534,10 +1563,10 @@
     /**
      * @hide
      */
-    public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+    public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing, int userHandle) {
         if (mService != null) {
             try {
-                mService.setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
+                mService.setActiveAdmin(policyReceiver, refreshing, userHandle);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed talking with device policy service", e);
             }
@@ -1545,6 +1574,13 @@
     }
 
     /**
+     * @hide
+     */
+    public void setActiveAdmin(ComponentName policyReceiver, boolean refreshing) {
+        setActiveAdmin(policyReceiver, refreshing, UserHandle.myUserId());
+    }
+
+    /**
      * Returns the DeviceAdminInfo as defined by the administrator's package info & meta-data
      * @hide
      */
@@ -1749,8 +1785,26 @@
     }
 
     /**
+     * Sets the enabled state of the profile. A profile should be enabled only once it is ready to
+     * be used. Only the profile owner can call this.
+     *
+     * @see #isProfileOwnerApp
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     */
+    public void setProfileEnabled(ComponentName admin) {
+        if (mService != null) {
+            try {
+                mService.setProfileEnabled(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
      * Used to determine if a particular package is registered as the Profile Owner for the
-     * current user. A profile owner is a special device admin that has additional priviledges
+     * current user. A profile owner is a special device admin that has additional privileges
      * within the managed profile.
      *
      * @param packageName The package name of the app to compare with the registered profile owner.
@@ -1855,4 +1909,136 @@
             }
         }
     }
+
+    /**
+     * Called by a profile or device owner to set the application restrictions for a given target
+     * application running in the managed profile.
+     *
+     * <p>The provided {@link Bundle} consists of key-value pairs, where the types of values may be
+     * {@link Boolean}, {@link String}, or {@link String}[]. The recommended format for key strings
+     * is "com.example.packagename/example-setting" to avoid naming conflicts with library
+     * components such as {@link android.webkit.WebView}.
+     *
+     * <p>The application restrictions are only made visible to the target application and the
+     * profile or device owner.
+     *
+     * <p>The calling device admin must be a profile or device owner; if it is not, a security
+     * exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The name of the package to update restricted settings for.
+     * @param settings A {@link Bundle} to be parsed by the receiving application, conveying a new
+     * set of active restrictions.
+     */
+    public void setApplicationRestrictions(ComponentName admin, String packageName,
+            Bundle settings) {
+        if (mService != null) {
+            try {
+                mService.setApplicationRestrictions(admin, packageName, settings);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile owner to forward intents sent from the managed profile to the owner, or
+     * from the owner to the managed profile.
+     * If an intent matches this intent filter, then activities belonging to the other user can
+     * respond to this intent.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param filter if an intent matches this IntentFilter, then it can be forwarded.
+     */
+    public void forwardMatchingIntents(ComponentName admin, IntentFilter filter, int flags) {
+        if (mService != null) {
+            try {
+                mService.forwardMatchingIntents(admin, filter, flags);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile owner to remove all the forwarding intent filters from the current user
+     * and from the owner.
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     */
+    public void clearForwardingIntentFilters(ComponentName admin) {
+        if (mService != null) {
+            try {
+                mService.clearForwardingIntentFilters(admin);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile or device owner to get the application restrictions for a given target
+     * application running in the managed profile.
+     *
+     * <p>The calling device admin must be a profile or device owner; if it is not, a security
+     * exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated with.
+     * @param packageName The name of the package to fetch restricted settings of.
+     * @return {@link Bundle} of settings corresponding to what was set last time
+     * {@link DevicePolicyManager#setApplicationRestrictions} was called, or an empty {@link Bundle}
+     * if no restrictions have been set.
+     */
+    public Bundle getApplicationRestrictions(ComponentName admin, String packageName) {
+        if (mService != null) {
+            try {
+                return mService.getApplicationRestrictions(admin, packageName);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Called by a profile or device owner to set a user restriction specified
+     * by the key.
+     * <p>
+     * The calling device admin must be a profile or device owner; if it is not,
+     * a security exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated
+     *            with.
+     * @param key The key of the restriction. See the constants in
+     *            {@link android.os.UserManager} for the list of keys.
+     */
+    public void addUserRestriction(ComponentName admin, String key) {
+        if (mService != null) {
+            try {
+                mService.setUserRestriction(admin, key, true);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
+
+    /**
+     * Called by a profile or device owner to clear a user restriction specified
+     * by the key.
+     * <p>
+     * The calling device admin must be a profile or device owner; if it is not,
+     * a security exception will be thrown.
+     *
+     * @param admin Which {@link DeviceAdminReceiver} this request is associated
+     *            with.
+     * @param key The key of the restriction. See the constants in
+     *            {@link android.os.UserManager} for the list of keys.
+     */
+    public void clearUserRestriction(ComponentName admin, String key) {
+        if (mService != null) {
+            try {
+                mService.setUserRestriction(admin, key, false);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed talking with device policy service", e);
+            }
+        }
+    }
 }
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 8119585..495a5f9 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -19,6 +19,7 @@
 
 import android.content.ComponentName;
 import android.content.IntentFilter;
+import android.os.Bundle;
 import android.os.RemoteCallback;
 
 /**
@@ -107,10 +108,18 @@
     boolean setProfileOwner(String packageName, String ownerName, int userHandle);
     String getProfileOwner(int userHandle);
     String getProfileOwnerName(int userHandle);
+    void setProfileEnabled(in ComponentName who);
 
     boolean installCaCert(in byte[] certBuffer);
     void uninstallCaCert(in byte[] certBuffer);
 
     void addPersistentPreferredActivity(in ComponentName admin, in IntentFilter filter, in ComponentName activity);
     void clearPackagePersistentPreferredActivities(in ComponentName admin, String packageName);
+
+    void setApplicationRestrictions(in ComponentName who, in String packageName, in Bundle settings);
+    Bundle getApplicationRestrictions(in ComponentName who, in String packageName);
+
+    void setUserRestriction(in ComponentName who, in String key, boolean enable);
+    void forwardMatchingIntents(in ComponentName admin, in IntentFilter filter, int flags);
+    void clearForwardingIntentFilters(in ComponentName admin);
 }
diff --git a/core/java/android/app/backup/BackupAgent.java b/core/java/android/app/backup/BackupAgent.java
index 3c31f8d..886f1a6 100644
--- a/core/java/android/app/backup/BackupAgent.java
+++ b/core/java/android/app/backup/BackupAgent.java
@@ -29,6 +29,10 @@
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
 import android.os.RemoteException;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
 import android.util.Log;
 
 import java.io.File;
@@ -38,11 +42,6 @@
 import java.util.LinkedList;
 import java.util.concurrent.CountDownLatch;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.OsConstants;
-import libcore.io.StructStat;
-
 /**
  * Provides the central interface between an
  * application and Android's data backup infrastructure.  An application that wishes
@@ -195,7 +194,7 @@
      * the key supplied as part of the entity.  Writing an entity with a negative
      * data size instructs the transport to delete whatever entity currently exists
      * under that key from the remote data set.
-     * 
+     *
      * @param oldState An open, read-only ParcelFileDescriptor pointing to the
      *            last backup state provided by the application. May be
      *            <code>null</code>, in which case no prior state is being
@@ -226,7 +225,7 @@
      * onRestore() throws an exception, the OS will assume that the
      * application's data may now be in an incoherent state, and will clear it
      * before proceeding.
-     * 
+     *
      * @param data A structured wrapper around an open, read-only
      *            file descriptor pointing to a full snapshot of the
      *            application's data.  The application should consume every
@@ -416,7 +415,7 @@
                     }
 
                     // If it's a directory, enqueue its contents for scanning.
-                    StructStat stat = Libcore.os.lstat(filePath);
+                    StructStat stat = Os.lstat(filePath);
                     if (OsConstants.S_ISLNK(stat.st_mode)) {
                         if (DEBUG) Log.i(TAG, "Symlink (skipping)!: " + file);
                         continue;
diff --git a/core/java/android/app/backup/FullBackup.java b/core/java/android/app/backup/FullBackup.java
index cfd0a65..6ebb6c4 100644
--- a/core/java/android/app/backup/FullBackup.java
+++ b/core/java/android/app/backup/FullBackup.java
@@ -17,6 +17,8 @@
 package android.app.backup;
 
 import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Log;
 
 import java.io.File;
@@ -24,9 +26,6 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-
 /**
  * Global constant definitions et cetera related to the full-backup-to-fd
  * binary format.  Nothing in this namespace is part of any API; it's all
@@ -147,7 +146,7 @@
             try {
                 // explicitly prevent emplacement of files accessible by outside apps
                 mode &= 0700;
-                Libcore.os.chmod(outFile.getPath(), (int)mode);
+                Os.chmod(outFile.getPath(), (int)mode);
             } catch (ErrnoException e) {
                 e.rethrowAsIOException();
             }
diff --git a/core/java/android/bluetooth/BluetoothGatt.java b/core/java/android/bluetooth/BluetoothGatt.java
index 101b721..ff3af7c 100644
--- a/core/java/android/bluetooth/BluetoothGatt.java
+++ b/core/java/android/bluetooth/BluetoothGatt.java
@@ -50,6 +50,7 @@
     private boolean mAutoConnect;
     private int mConnState;
     private final Object mStateLock = new Object();
+    private Boolean mDeviceBusy = false;
 
     private static final int CONN_STATE_IDLE = 0;
     private static final int CONN_STATE_CONNECTING = 1;
@@ -166,6 +167,10 @@
                         mConnState = CONN_STATE_IDLE;
                     }
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
             }
 
             /**
@@ -301,6 +306,11 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
+
                 if ((status == GATT_INSUFFICIENT_AUTHENTICATION
                   || status == GATT_INSUFFICIENT_ENCRYPTION)
                   && mAuthRetry == false) {
@@ -348,6 +358,11 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
+
                 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
                                                           srvcInstId, srvcType);
                 if (service == null) return;
@@ -425,6 +440,11 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
+
                 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
                                                           srvcInstId, srvcType);
                 if (service == null) return;
@@ -474,6 +494,11 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
+
                 BluetoothGattService service = getService(mDevice, srvcUuid.getUuid(),
                                                           srvcInstId, srvcType);
                 if (service == null) return;
@@ -519,6 +544,11 @@
                 if (!address.equals(mDevice.getAddress())) {
                     return;
                 }
+
+                synchronized(mDeviceBusy) {
+                    mDeviceBusy = false;
+                }
+
                 try {
                     mCallback.onReliableWriteCompleted(BluetoothGatt.this, status);
                 } catch (Exception ex) {
@@ -851,6 +881,11 @@
         BluetoothDevice device = service.getDevice();
         if (device == null) return false;
 
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
         try {
             mService.readCharacteristic(mClientIf, device.getAddress(),
                 service.getType(), service.getInstanceId(),
@@ -858,6 +893,7 @@
                 new ParcelUuid(characteristic.getUuid()), AUTHENTICATION_NONE);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
+            mDeviceBusy = false;
             return false;
         }
 
@@ -890,6 +926,11 @@
         BluetoothDevice device = service.getDevice();
         if (device == null) return false;
 
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
         try {
             mService.writeCharacteristic(mClientIf, device.getAddress(),
                 service.getType(), service.getInstanceId(),
@@ -899,6 +940,7 @@
                 characteristic.getValue());
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
+            mDeviceBusy = false;
             return false;
         }
 
@@ -930,6 +972,11 @@
         BluetoothDevice device = service.getDevice();
         if (device == null) return false;
 
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
         try {
             mService.readDescriptor(mClientIf, device.getAddress(), service.getType(),
                 service.getInstanceId(), new ParcelUuid(service.getUuid()),
@@ -938,6 +985,7 @@
                 AUTHENTICATION_NONE);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
+            mDeviceBusy = false;
             return false;
         }
 
@@ -968,6 +1016,11 @@
         BluetoothDevice device = service.getDevice();
         if (device == null) return false;
 
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
         try {
             mService.writeDescriptor(mClientIf, device.getAddress(), service.getType(),
                 service.getInstanceId(), new ParcelUuid(service.getUuid()),
@@ -977,6 +1030,7 @@
                 descriptor.getValue());
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
+            mDeviceBusy = false;
             return false;
         }
 
@@ -1034,10 +1088,16 @@
         if (DBG) Log.d(TAG, "executeReliableWrite() - device: " + mDevice.getAddress());
         if (mService == null || mClientIf == 0) return false;
 
+        synchronized(mDeviceBusy) {
+            if (mDeviceBusy) return false;
+            mDeviceBusy = true;
+        }
+
         try {
             mService.endReliableWrite(mClientIf, mDevice.getAddress(), true);
         } catch (RemoteException e) {
             Log.e(TAG,"",e);
+            mDeviceBusy = false;
             return false;
         }
 
diff --git a/core/java/android/content/ContentResolver.java b/core/java/android/content/ContentResolver.java
index f3c803d..5b41394 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -1641,7 +1641,7 @@
      *
      * @see #getPersistedUriPermissions()
      */
-    public void takePersistableUriPermission(Uri uri, int modeFlags) {
+    public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
         try {
             ActivityManagerNative.getDefault().takePersistableUriPermission(uri, modeFlags);
         } catch (RemoteException e) {
@@ -1656,7 +1656,7 @@
      *
      * @see #getPersistedUriPermissions()
      */
-    public void releasePersistableUriPermission(Uri uri, int modeFlags) {
+    public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
         try {
             ActivityManagerNative.getDefault().releasePersistableUriPermission(uri, modeFlags);
         } catch (RemoteException e) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ed0cc23..de223a3 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -2009,6 +2009,7 @@
             CAMERA_SERVICE,
             PRINT_SERVICE,
             MEDIA_SESSION_SERVICE,
+            BATTERY_SERVICE,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ServiceName {}
@@ -2060,6 +2061,8 @@
      * <dd> An {@link android.app.UiModeManager} for controlling UI modes.
      * <dt> {@link #DOWNLOAD_SERVICE} ("download")
      * <dd> A {@link android.app.DownloadManager} for requesting HTTP downloads
+     * <dt> {@link #BATTERY_SERVICE} ("batterymanager")
+     * <dd> A {@link android.os.BatteryManager} for managing battery state
      * </dl>
      *
      * <p>Note:  System services obtained via this API may be closely associated with
@@ -2113,6 +2116,8 @@
      * @see android.app.UiModeManager
      * @see #DOWNLOAD_SERVICE
      * @see android.app.DownloadManager
+     * @see #BATTERY_SERVICE
+     * @see android.os.BatteryManager
      */
     public abstract Object getSystemService(@ServiceName @NonNull String name);
 
@@ -2382,10 +2387,10 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
-     * {@link android.media.session.MediaSessionManager} for managing media Sessions.
+     * {@link android.media.session.SessionManager} for managing media Sessions.
      *
      * @see #getSystemService
-     * @see android.media.session.MediaSessionManager
+     * @see android.media.session.SessionManager
      */
     public static final String MEDIA_SESSION_SERVICE = "media_session";
 
@@ -2437,6 +2442,14 @@
     public static final String APPWIDGET_SERVICE = "appwidget";
 
     /**
+     * Official published name of the (internal) voice interaction manager service.
+     *
+     * @hide
+     * @see #getSystemService
+     */
+    public static final String VOICE_INTERACTION_MANAGER_SERVICE = "voiceinteraction";
+
+    /**
      * Use with {@link #getSystemService} to retrieve an
      * {@link android.app.backup.IBackupManager IBackupManager} for communicating
      * with the backup mechanism.
@@ -2481,6 +2494,14 @@
 
     /**
      * Use with {@link #getSystemService} to retrieve a
+     * {@link android.os.BatteryManager} for managing battery state.
+     *
+     * @see #getSystemService
+     */
+    public static final String BATTERY_SERVICE = "batterymanager";
+
+    /**
+     * Use with {@link #getSystemService} to retrieve a
      * {@link android.nfc.NfcManager} for using NFC.
      *
      * @see #getSystemService
@@ -2630,6 +2651,14 @@
     public static final String TV_INPUT_SERVICE = "tv_input";
 
     /**
+     * {@link android.net.NetworkScoreManager} for managing network scoring.
+     * @see #getSystemService
+     * @see android.net.NetworkScoreManager
+     * @hide
+     */
+    public static final String NETWORK_SCORE_SERVICE = "network_score";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
@@ -2770,9 +2799,13 @@
      * @param uri The Uri you would like to grant access to.
      * @param modeFlags The desired access modes.  Any combination of
      * {@link Intent#FLAG_GRANT_READ_URI_PERMISSION
-     * Intent.FLAG_GRANT_READ_URI_PERMISSION} or
+     * Intent.FLAG_GRANT_READ_URI_PERMISSION},
      * {@link Intent#FLAG_GRANT_WRITE_URI_PERMISSION
-     * Intent.FLAG_GRANT_WRITE_URI_PERMISSION}.
+     * Intent.FLAG_GRANT_WRITE_URI_PERMISSION},
+     * {@link Intent#FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+     * Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION}, or
+     * {@link Intent#FLAG_GRANT_PREFIX_URI_PERMISSION
+     * Intent.FLAG_GRANT_PREFIX_URI_PERMISSION}.
      *
      * @see #revokeUriPermission
      */
@@ -2785,7 +2818,8 @@
      * Uri will match all previously granted Uris that are the same or a
      * sub-path of the given Uri.  That is, revoking "content://foo/target" will
      * revoke both "content://foo/target" and "content://foo/target/sub", but not
-     * "content://foo".
+     * "content://foo".  It will not remove any prefix grants that exist at a
+     * higher level.
      *
      * @param uri The Uri you would like to revoke access to.
      * @param modeFlags The desired access modes.  Any combination of
@@ -2796,7 +2830,7 @@
      *
      * @see #grantUriPermission
      */
-    public abstract void revokeUriPermission(Uri uri, @Intent.GrantUriMode int modeFlags);
+    public abstract void revokeUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags);
 
     /**
      * Determine whether a particular process and user ID has been granted
@@ -2820,7 +2854,7 @@
      * @see #checkCallingUriPermission
      */
     public abstract int checkUriPermission(Uri uri, int pid, int uid,
-            @Intent.GrantUriMode int modeFlags);
+            @Intent.AccessUriMode int modeFlags);
 
     /**
      * Determine whether the calling process and user ID has been
@@ -2843,7 +2877,7 @@
      *
      * @see #checkUriPermission(Uri, int, int, int)
      */
-    public abstract int checkCallingUriPermission(Uri uri, @Intent.GrantUriMode int modeFlags);
+    public abstract int checkCallingUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags);
 
     /**
      * Determine whether the calling process of an IPC <em>or you</em> has been granted
@@ -2863,7 +2897,7 @@
      * @see #checkCallingUriPermission
      */
     public abstract int checkCallingOrSelfUriPermission(Uri uri,
-            @Intent.GrantUriMode int modeFlags);
+            @Intent.AccessUriMode int modeFlags);
 
     /**
      * Check both a Uri and normal permission.  This allows you to perform
@@ -2889,7 +2923,7 @@
      */
     public abstract int checkUriPermission(@Nullable Uri uri, @Nullable String readPermission,
             @Nullable String writePermission, int pid, int uid,
-            @Intent.GrantUriMode int modeFlags);
+            @Intent.AccessUriMode int modeFlags);
 
     /**
      * If a particular process and user ID has not been granted
@@ -2911,7 +2945,7 @@
      * @see #checkUriPermission(Uri, int, int, int)
      */
     public abstract void enforceUriPermission(
-            Uri uri, int pid, int uid, @Intent.GrantUriMode int modeFlags, String message);
+            Uri uri, int pid, int uid, @Intent.AccessUriMode int modeFlags, String message);
 
     /**
      * If the calling process and user ID has not been granted
@@ -2933,7 +2967,7 @@
      * @see #checkCallingUriPermission(Uri, int)
      */
     public abstract void enforceCallingUriPermission(
-            Uri uri, @Intent.GrantUriMode int modeFlags, String message);
+            Uri uri, @Intent.AccessUriMode int modeFlags, String message);
 
     /**
      * If the calling process of an IPC <em>or you</em> has not been
@@ -2952,7 +2986,7 @@
      * @see #checkCallingOrSelfUriPermission(Uri, int)
      */
     public abstract void enforceCallingOrSelfUriPermission(
-            Uri uri, @Intent.GrantUriMode int modeFlags, String message);
+            Uri uri, @Intent.AccessUriMode int modeFlags, String message);
 
     /**
      * Enforce both a Uri and normal permission.  This allows you to perform
@@ -2977,7 +3011,7 @@
      */
     public abstract void enforceUriPermission(
             @Nullable Uri uri, @Nullable String readPermission,
-            @Nullable String writePermission, int pid, int uid, @Intent.GrantUriMode int modeFlags,
+            @Nullable String writePermission, int pid, int uid, @Intent.AccessUriMode int modeFlags,
             @Nullable String message);
 
     /** @hide */
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 9881428..ae5437b 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -18,6 +18,7 @@
 
 import android.content.pm.ApplicationInfo;
 import android.util.ArraySet;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -864,8 +865,9 @@
         }
 
         // Migrate any clip data and flags from target.
-        int permFlags = target.getFlags()
-                & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION);
+        int permFlags = target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
+                | FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                | FLAG_GRANT_PREFIX_URI_PERMISSION);
         if (permFlags != 0) {
             ClipData targetClipData = target.getClipData();
             if (targetClipData == null && target.getData() != null) {
@@ -1417,15 +1419,38 @@
     // Standard intent broadcast actions (see action variable).
 
     /**
-     * Broadcast Action: Sent after the screen turns off.
+     * Broadcast Action: Sent when the device goes to sleep and becomes non-interactive.
+     * <p>
+     * For historical reasons, the name of this broadcast action refers to the power
+     * state of the screen but it is actually sent in response to changes in the
+     * overall interactive state of the device.
+     * </p><p>
+     * This broadcast is sent when the device becomes non-interactive which may have
+     * nothing to do with the screen turning off.  To determine the
+     * actual state of the screen, use {@link android.view.Display#getState}.
+     * </p><p>
+     * See {@link android.os.PowerManager#isInteractive} for details.
+     * </p>
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_SCREEN_OFF = "android.intent.action.SCREEN_OFF";
+
     /**
-     * Broadcast Action: Sent after the screen turns on.
+     * Broadcast Action: Sent when the device wakes up and becomes interactive.
+     * <p>
+     * For historical reasons, the name of this broadcast action refers to the power
+     * state of the screen but it is actually sent in response to changes in the
+     * overall interactive state of the device.
+     * </p><p>
+     * This broadcast is sent when the device becomes interactive which may have
+     * nothing to do with the screen turning on.  To determine the
+     * actual state of the screen, use {@link android.view.Display#getState}.
+     * </p><p>
+     * See {@link android.os.PowerManager#isInteractive} for details.
+     * </p>
      *
      * <p class="note">This is a protected intent that can only be sent
      * by the system.
@@ -2283,6 +2308,16 @@
             = "android.intent.action.ADVANCED_SETTINGS";
 
     /**
+     *  Broadcast Action: Sent after application restrictions are changed.
+     *
+     * <p class="note">This is a protected intent that can only be sent
+     * by the system.</p>
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_APPLICATION_RESTRICTIONS_CHANGED =
+            "android.intent.action.APPLICATION_RESTRICTIONS_CHANGED";
+
+    /**
      * Broadcast Action: An outgoing call is about to be placed.
      *
      * <p>The Intent will have the following extra value:</p>
@@ -2665,9 +2700,11 @@
      * take the persistable permissions using
      * {@link ContentResolver#takePersistableUriPermission(Uri, int)}.
      * <p>
-     * Callers can restrict document selection to a specific kind of data, such
-     * as photos, by setting one or more MIME types in
-     * {@link #EXTRA_MIME_TYPES}.
+     * Callers must indicate the acceptable document MIME types through
+     * {@link #setType(String)}. For example, to select photos, use
+     * {@code image/*}. If multiple disjoint MIME types are acceptable, define
+     * them in {@link #EXTRA_MIME_TYPES} and {@link #setType(String)} to
+     * {@literal *}/*.
      * <p>
      * If the caller can handle multiple returned items (the user performing
      * multiple selection), then you can specify {@link #EXTRA_ALLOW_MULTIPLE}
@@ -2677,9 +2714,10 @@
      * returned URIs can be opened with
      * {@link ContentResolver#openFileDescriptor(Uri, String)}.
      * <p>
-     * Output: The URI of the item that was picked. This must be a
-     * {@code content://} URI so that any receiver can access it. If multiple
-     * documents were selected, they are returned in {@link #getClipData()}.
+     * Output: The URI of the item that was picked, returned in
+     * {@link #getData()}. This must be a {@code content://} URI so that any
+     * receiver can access it. If multiple documents were selected, they are
+     * returned in {@link #getClipData()}.
      *
      * @see DocumentsContract
      * @see #ACTION_CREATE_DOCUMENT
@@ -2721,6 +2759,24 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_CREATE_DOCUMENT = "android.intent.action.CREATE_DOCUMENT";
 
+    /**
+     * Activity Action: Allow the user to pick a directory. When invoked, the
+     * system will display the various {@link DocumentsProvider} instances
+     * installed on the device, letting the user navigate through them. Apps can
+     * fully manage documents within the returned directory.
+     * <p>
+     * To gain access to descendant (child, grandchild, etc) documents, use
+     * {@link DocumentsContract#buildDocumentViaUri(Uri, String)} and
+     * {@link DocumentsContract#buildChildDocumentsViaUri(Uri, String)} using
+     * the returned directory URI.
+     * <p>
+     * Output: The URI representing the selected directory.
+     *
+     * @see DocumentsContract
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_PICK_DIRECTORY = "android.intent.action.PICK_DIRECTORY";
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent categories (see addCategory()).
@@ -2748,6 +2804,14 @@
     @SdkConstant(SdkConstantType.INTENT_CATEGORY)
     public static final String CATEGORY_BROWSABLE = "android.intent.category.BROWSABLE";
     /**
+     * Categories for activities that can participate in voice interaction.
+     * An activity that supports this category must be prepared to run with
+     * no UI shown at all (though in some case it may have a UI shown), and
+     * rely on {@link android.app.VoiceInteractor} to interact with the user.
+     */
+    @SdkConstant(SdkConstantType.INTENT_CATEGORY)
+    public static final String CATEGORY_VOICE = "android.intent.category.VOICE";
+    /**
      * Set if the activity should be considered as an alternative action to
      * the data the user is currently viewing.  See also
      * {@link #CATEGORY_SELECTED_ALTERNATIVE} for an alternative action that
@@ -3299,6 +3363,7 @@
      * @see #ACTION_GET_CONTENT
      * @see #ACTION_OPEN_DOCUMENT
      * @see #ACTION_CREATE_DOCUMENT
+     * @see #ACTION_PICK_DIRECTORY
      */
     public static final String EXTRA_LOCAL_ONLY =
             "android.intent.extra.LOCAL_ONLY";
@@ -3392,11 +3457,29 @@
     // Intent flags (see mFlags variable).
 
     /** @hide */
-    @IntDef(flag = true,
-            value = {FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION})
+    @IntDef(flag = true, value = {
+            FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION,
+            FLAG_GRANT_PERSISTABLE_URI_PERMISSION, FLAG_GRANT_PREFIX_URI_PERMISSION })
     @Retention(RetentionPolicy.SOURCE)
     public @interface GrantUriMode {}
 
+    /** @hide */
+    @IntDef(flag = true, value = {
+            FLAG_GRANT_READ_URI_PERMISSION, FLAG_GRANT_WRITE_URI_PERMISSION })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface AccessUriMode {}
+
+    /**
+     * Test if given mode flags specify an access mode, which must be at least
+     * read and/or write.
+     *
+     * @hide
+     */
+    public static boolean isAccessUriMode(int modeFlags) {
+        return (modeFlags & (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) != 0;
+    }
+
     /**
      * If set, the recipient of this Intent will be granted permission to
      * perform read operations on the URI in the Intent's data and any URIs
@@ -3458,6 +3541,17 @@
     public static final int FLAG_GRANT_PERSISTABLE_URI_PERMISSION = 0x00000040;
 
     /**
+     * When combined with {@link #FLAG_GRANT_READ_URI_PERMISSION} and/or
+     * {@link #FLAG_GRANT_WRITE_URI_PERMISSION}, the URI permission grant
+     * applies to any URI that is a prefix match against the original granted
+     * URI. (Without this flag, the URI must match exactly for access to be
+     * granted.) Another URI is considered a prefix match only when scheme,
+     * authority, and all path segments defined by the prefix are an exact
+     * match.
+     */
+    public static final int FLAG_GRANT_PREFIX_URI_PERMISSION = 0x00000080;
+
+    /**
      * If set, the new activity is not kept in the history stack.  As soon as
      * the user navigates away from it, the activity is finished.  This may also
      * be set with the {@link android.R.styleable#AndroidManifestActivity_noHistory
@@ -3777,9 +3871,9 @@
     /**
      * @hide Flags that can't be changed with PendingIntent.
      */
-    public static final int IMMUTABLE_FLAGS =
-            FLAG_GRANT_READ_URI_PERMISSION
-            | FLAG_GRANT_WRITE_URI_PERMISSION;
+    public static final int IMMUTABLE_FLAGS = FLAG_GRANT_READ_URI_PERMISSION
+            | FLAG_GRANT_WRITE_URI_PERMISSION | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+            | FLAG_GRANT_PREFIX_URI_PERMISSION;
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
@@ -6317,6 +6411,8 @@
      *
      * @see #FLAG_GRANT_READ_URI_PERMISSION
      * @see #FLAG_GRANT_WRITE_URI_PERMISSION
+     * @see #FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+     * @see #FLAG_GRANT_PREFIX_URI_PERMISSION
      * @see #FLAG_DEBUG_LOG_RESOLUTION
      * @see #FLAG_FROM_BACKGROUND
      * @see #FLAG_ACTIVITY_BROUGHT_TO_FRONT
@@ -7348,9 +7444,10 @@
                     // Since we migrated in child, we need to promote ClipData
                     // and flags to ourselves to grant.
                     setClipData(target.getClipData());
-                    addFlags(target.getFlags()
-                            & (FLAG_GRANT_READ_URI_PERMISSION | FLAG_GRANT_WRITE_URI_PERMISSION
-                                    | FLAG_GRANT_PERSISTABLE_URI_PERMISSION));
+                    addFlags(target.getFlags() & (FLAG_GRANT_READ_URI_PERMISSION
+                            | FLAG_GRANT_WRITE_URI_PERMISSION
+                            | FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                            | FLAG_GRANT_PREFIX_URI_PERMISSION));
                     return true;
                 } else {
                     return false;
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 9916476..c53e545 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -198,7 +198,7 @@
     /**
      * @hide Bit in {@link #flags}: If set, this component will only be seen
      * by the primary user.  Only works with broadcast receivers.  Set from the
-     * {@link android.R.attr#primaryUserOnly} attribute.
+     * android.R.attr#primaryUserOnly attribute.
      */
     public static final int FLAG_PRIMARY_USER_ONLY = 0x20000000;
     /**
@@ -210,6 +210,13 @@
      */
     public static final int FLAG_SINGLE_USER = 0x40000000;
     /**
+     * @hide Bit in {@link #flags}: If set, this activity may be launched into an
+     * owned ActivityContainer such as that within an ActivityView. If not set and
+     * this activity is launched into such a container a SecurityExcception will be
+     * thrown. Set from the {@link android.R.attr#allowEmbedded} attribute.
+     */
+    public static final int FLAG_ALLOW_EMBEDDED = 0x80000000;
+    /**
      * Options that have been set in the activity declaration in the
      * manifest.
      * These include:
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5d02ae9..0d1b262 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -447,6 +447,15 @@
     public String nativeLibraryDir;
 
     /**
+     * The ABI that this application requires, This is inferred from the ABIs
+     * of the native JNI libraries the application bundles. Will be {@code null}
+     * if this application does not require any particular ABI.
+     *
+     * {@hide}
+     */
+    public String requiredCpuAbi;
+
+    /**
      * The kernel user-ID that has been assigned to this application;
      * currently this is not a unique ID (multiple applications can have
      * the same uid).
@@ -583,6 +592,7 @@
         sourceDir = orig.sourceDir;
         publicSourceDir = orig.publicSourceDir;
         nativeLibraryDir = orig.nativeLibraryDir;
+        requiredCpuAbi = orig.requiredCpuAbi;
         resourceDirs = orig.resourceDirs;
         seinfo = orig.seinfo;
         sharedLibraryFiles = orig.sharedLibraryFiles;
@@ -624,6 +634,7 @@
         dest.writeString(sourceDir);
         dest.writeString(publicSourceDir);
         dest.writeString(nativeLibraryDir);
+        dest.writeString(requiredCpuAbi);
         dest.writeStringArray(resourceDirs);
         dest.writeString(seinfo);
         dest.writeStringArray(sharedLibraryFiles);
@@ -664,6 +675,7 @@
         sourceDir = source.readString();
         publicSourceDir = source.readString();
         nativeLibraryDir = source.readString();
+        requiredCpuAbi = source.readString();
         resourceDirs = source.readStringArray();
         seinfo = source.readString();
         sharedLibraryFiles = source.readStringArray();
diff --git a/core/java/android/content/pm/ILauncherApps.aidl b/core/java/android/content/pm/ILauncherApps.aidl
index 796b113..0acf043 100644
--- a/core/java/android/content/pm/ILauncherApps.aidl
+++ b/core/java/android/content/pm/ILauncherApps.aidl
@@ -35,4 +35,6 @@
     ResolveInfo resolveActivity(in Intent intent, in UserHandle user);
     void startActivityAsUser(in ComponentName component, in Rect sourceBounds,
             in Bundle opts, in UserHandle user);
+    boolean isPackageEnabled(String packageName, in UserHandle user);
+    boolean isActivityEnabled(in ComponentName component, in UserHandle user);
 }
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index ae0899f..cf9a296 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -74,6 +74,9 @@
 
     ActivityInfo getActivityInfo(in ComponentName className, int flags, int userId);
 
+    boolean activitySupportsIntent(in ComponentName className, in Intent intent,
+            String resolvedType);
+
     ActivityInfo getReceiverInfo(in ComponentName className, int flags, int userId);
 
     ServiceInfo getServiceInfo(in ComponentName className, int flags, int userId);
@@ -108,6 +111,8 @@
 
     ResolveInfo resolveIntent(in Intent intent, String resolvedType, int flags, int userId);
 
+    boolean canForwardTo(in Intent intent, String resolvedType, int userIdFrom, int userIdDest);
+
     List<ResolveInfo> queryIntentActivities(in Intent intent, 
             String resolvedType, int flags, int userId);
 
@@ -242,6 +247,10 @@
 
     void clearPackagePersistentPreferredActivities(String packageName, int userId);
 
+    void addForwardingIntentFilter(in IntentFilter filter, int userIdOrig, int userIdDest);
+
+    void clearForwardingIntentFilters(int userIdOrig);
+
     /**
      * Report the set of 'Home' activity candidates, plus (if any) which of them
      * is the current "always use this one" setting.
diff --git a/core/java/android/content/pm/LauncherActivityInfo.java b/core/java/android/content/pm/LauncherActivityInfo.java
index 92b9146..9087338 100644
--- a/core/java/android/content/pm/LauncherActivityInfo.java
+++ b/core/java/android/content/pm/LauncherActivityInfo.java
@@ -19,6 +19,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Bitmap.Config;
@@ -37,6 +39,8 @@
  */
 public class LauncherActivityInfo {
     private static final boolean DEBUG = false;
+    private static final String TAG = "LauncherActivityInfo";
+
     private final PackageManager mPm;
     private final UserManager mUm;
 
@@ -121,25 +125,42 @@
     }
 
     /**
+     * Returns the name for the acitivty from  android:name in the manifest.
+     * @return the name from android:name for the acitivity.
+     */
+    public String getName() {
+        return mActivityInfo.name;
+    }
+
+    /**
      * Returns the activity icon with badging appropriate for the profile.
      * @param density Optional density for the icon, or 0 to use the default density.
      * @return A badged icon for the activity.
      */
     public Drawable getBadgedIcon(int density) {
-        // TODO: Handle density
-        if (mUser.equals(android.os.Process.myUserHandle())) {
-            return mActivityInfo.loadIcon(mPm);
-        }
-        Drawable originalIcon = mActivityInfo.loadIcon(mPm);
-        if (originalIcon == null) {
-            if (DEBUG) {
-                Log.w("LauncherActivityInfo", "Couldn't find icon for activity");
+        int iconRes = mActivityInfo.getIconResource();
+        Resources resources = null;
+        Drawable originalIcon = null;
+        try {
+            resources = mPm.getResourcesForApplication(mActivityInfo.applicationInfo);
+            try {
+                if (density != 0) {
+                    originalIcon = resources.getDrawableForDensity(iconRes, density);
+                }
+            } catch (Resources.NotFoundException e) {
             }
-            originalIcon = mPm.getDefaultActivityIcon();
+        } catch (NameNotFoundException nnfe) {
         }
+
+        if (originalIcon == null) {
+            originalIcon = mActivityInfo.loadIcon(mPm);
+        }
+
         if (originalIcon instanceof BitmapDrawable) {
             return mUm.getBadgedDrawableForUser(
                     originalIcon, mUser);
+        } else {
+            Log.e(TAG, "Unable to create badged icon for " + mActivityInfo);
         }
         return originalIcon;
     }
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index 5187181..8025b60 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -187,6 +187,39 @@
     }
 
     /**
+     * Checks if the package is installed and enabled for a profile.
+     *
+     * @param packageName The package to check.
+     * @param user The UserHandle of the profile.
+     *
+     * @return true if the package exists and is enabled.
+     */
+    public boolean isPackageEnabledForProfile(String packageName, UserHandle user) {
+        try {
+            return mService.isPackageEnabled(packageName, user);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+    /**
+     * Checks if the activity exists and it enabled for a profile.
+     *
+     * @param component The activity to check.
+     * @param user The UserHandle of the profile.
+     *
+     * @return true if the activity exists and is enabled.
+     */
+    public boolean isActivityEnabledForProfile(ComponentName component, UserHandle user) {
+        try {
+            return mService.isActivityEnabled(component, user);
+        } catch (RemoteException re) {
+            return false;
+        }
+    }
+
+
+    /**
      * Adds a listener for changes to packages in current and managed profiles.
      *
      * @param listener The listener to add.
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 3300e9d..484a2a1 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -698,6 +698,25 @@
     public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;
 
     /**
+     * Installation failed return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
+     * if the system failed to install the package because its packaged native code did not
+     * match any of the ABIs supported by the system.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -113;
+
+    /**
+     * Internal return code for NativeLibraryHelper methods to indicate that the package
+     * being processed did not contain any native code. This is placed here only so that
+     * it can belong to the same value space as the other install failure codes.
+     *
+     * @hide
+     */
+    public static final int NO_NATIVE_LIBRARIES = -114;
+
+    /**
      * Flag parameter for {@link #deletePackage} to indicate that you don't want to delete the
      * package's data directory.
      *
@@ -993,6 +1012,7 @@
      * @hide
      * @deprecated
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_NFC_HCE = "android.hardware.nfc.hce";
 
@@ -1215,7 +1235,6 @@
      */
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_LIVE_WALLPAPER = "android.software.live_wallpaper";
-
     /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports app widgets.
@@ -1224,6 +1243,17 @@
     public static final String FEATURE_APP_WIDGETS = "android.software.app_widgets";
 
     /**
+     * @hide
+     * Feature for {@link #getSystemAvailableFeatures} and
+     * {@link #hasSystemFeature}: The device supports
+     * {@link android.service.voice.VoiceInteractionService} and
+     * {@link android.app.VoiceInteractor}.
+     */
+    @SdkConstant(SdkConstantType.FEATURE)
+    public static final String FEATURE_VOICE_RECOGNIZERS = "android.software.voice_recognizers";
+
+
+    /**
      * Feature for {@link #getSystemAvailableFeatures} and
      * {@link #hasSystemFeature}: The device supports a home screen that is replaceable
      * by third party applications.
@@ -1289,6 +1319,7 @@
      * something like a DPAD, not through touch or mouse.
      * @deprecated use {@link #FEATURE_LEANBACK} instead.
      */
+    @Deprecated
     @SdkConstant(SdkConstantType.FEATURE)
     public static final String FEATURE_TELEVISION = "android.hardware.type.television";
 
@@ -1503,17 +1534,33 @@
     public abstract Intent getLaunchIntentForPackage(String packageName);
 
     /**
-     * Return an array of all of the secondary group-ids that have been
-     * assigned to a package.
-     *
-     * <p>Throws {@link NameNotFoundException} if a package with the given
-     * name cannot be found on the system.
-     *
+     * Return a "good" intent to launch a front-door Leanback activity in a
+     * package, for use for example to implement an "open" button when browsing
+     * through packages. The current implementation will look for a main
+     * activity in the category {@link Intent#CATEGORY_LEANBACK_LAUNCHER}, or
+     * return null if no main leanback activities are found.
+     * <p>
+     * Throws {@link NameNotFoundException} if a package with the given name
+     * cannot be found on the system.
+     * 
+     * @param packageName The name of the package to inspect.
+     * @return Returns either a fully-qualified Intent that can be used to launch
+     *         the main Leanback activity in the package, or null if the package
+     *         does not contain such an activity.
+     */
+    public abstract Intent getLeanbackLaunchIntentForPackage(String packageName);
+
+    /**
+     * Return an array of all of the secondary group-ids that have been assigned
+     * to a package.
+     * <p>
+     * Throws {@link NameNotFoundException} if a package with the given name
+     * cannot be found on the system.
+     * 
      * @param packageName The full name (i.e. com.google.apps.contacts) of the
-     *                    desired package.
-     *
-     * @return Returns an int array of the assigned gids, or null if there
-     * are none.
+     *            desired package.
+     * @return Returns an int array of the assigned gids, or null if there are
+     *         none.
      */
     public abstract int[] getPackageGids(String packageName)
             throws NameNotFoundException;
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 4b5616f..080b37b 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -50,6 +50,7 @@
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -147,8 +148,7 @@
     private String[] mSeparateProcesses;
     private boolean mOnlyCoreApps;
     private static final int SDK_VERSION = Build.VERSION.SDK_INT;
-    private static final String SDK_CODENAME = "REL".equals(Build.VERSION.CODENAME)
-            ? null : Build.VERSION.CODENAME;
+    private static final String[] SDK_CODENAMES = Build.VERSION.ACTIVE_CODENAMES;
 
     private int mParseError = PackageManager.INSTALL_SUCCEEDED;
 
@@ -459,7 +459,7 @@
         return pi;
     }
 
-    private Certificate[] loadCertificates(StrictJarFile jarFile, ZipEntry je,
+    private Certificate[][] loadCertificates(StrictJarFile jarFile, ZipEntry je,
             byte[] readBuffer) {
         try {
             // We must read the stream for the JarEntry to retrieve
@@ -469,7 +469,7 @@
                 // not using
             }
             is.close();
-            return je != null ? jarFile.getCertificates(je) : null;
+            return je != null ? jarFile.getCertificateChains(je) : null;
         } catch (IOException e) {
             Slog.w(TAG, "Exception reading " + je.getName() + " in " + jarFile, e);
         } catch (RuntimeException e) {
@@ -632,7 +632,7 @@
         try {
             StrictJarFile jarFile = new StrictJarFile(mArchiveSourcePath);
 
-            Certificate[] certs = null;
+            Certificate[][] certs = null;
 
             if ((flags&PARSE_IS_SYSTEM) != 0) {
                 // If this package comes from the system image, then we
@@ -656,8 +656,8 @@
                         final int N = certs.length;
                         for (int i=0; i<N; i++) {
                             Slog.i(TAG, "  Public key: "
-                                    + certs[i].getPublicKey().getEncoded()
-                                    + " " + certs[i].getPublicKey());
+                                    + certs[i][0].getPublicKey().getEncoded()
+                                    + " " + certs[i][0].getPublicKey());
                         }
                     }
                 }
@@ -677,7 +677,7 @@
                                 ManifestDigest.fromInputStream(jarFile.getInputStream(je));
                     }
 
-                    final Certificate[] localCerts = loadCertificates(jarFile, je, readBuffer);
+                    final Certificate[][] localCerts = loadCertificates(jarFile, je, readBuffer);
                     if (DEBUG_JAR) {
                         Slog.i(TAG, "File " + mArchiveSourcePath + " entry " + je.getName()
                                 + ": certs=" + certs + " ("
@@ -726,8 +726,7 @@
                 final int N = certs.length;
                 pkg.mSignatures = new Signature[certs.length];
                 for (int i=0; i<N; i++) {
-                    pkg.mSignatures[i] = new Signature(
-                            certs[i].getEncoded());
+                    pkg.mSignatures[i] = new Signature(certs[i]);
                 }
             } else {
                 Slog.e(TAG, "Package " + pkg.packageName
@@ -739,7 +738,7 @@
             // Add the signing KeySet to the system
             pkg.mSigningKeys = new HashSet<PublicKey>();
             for (int i=0; i < certs.length; i++) {
-                pkg.mSigningKeys.add(certs[i].getPublicKey());
+                pkg.mSigningKeys.add(certs[i][0].getPublicKey());
             }
 
         } catch (CertificateEncodingException e) {
@@ -1200,10 +1199,18 @@
                     sa.recycle();
 
                     if (minCode != null) {
-                        if (!minCode.equals(SDK_CODENAME)) {
-                            if (SDK_CODENAME != null) {
+                        boolean allowedCodename = false;
+                        for (String codename : SDK_CODENAMES) {
+                            if (minCode.equals(codename)) {
+                                allowedCodename = true;
+                                break;
+                            }
+                        }
+                        if (!allowedCodename) {
+                            if (SDK_CODENAMES.length > 0) {
                                 outError[0] = "Requires development platform " + minCode
-                                        + " (current platform is " + SDK_CODENAME + ")";
+                                        + " (current platform is any of "
+                                        + Arrays.toString(SDK_CODENAMES) + ")";
                             } else {
                                 outError[0] = "Requires development platform " + minCode
                                         + " but this is a release platform.";
@@ -1219,10 +1226,18 @@
                     }
                     
                     if (targetCode != null) {
-                        if (!targetCode.equals(SDK_CODENAME)) {
-                            if (SDK_CODENAME != null) {
+                        boolean allowedCodename = false;
+                        for (String codename : SDK_CODENAMES) {
+                            if (targetCode.equals(codename)) {
+                                allowedCodename = true;
+                                break;
+                            }
+                        }
+                        if (!allowedCodename) {
+                            if (SDK_CODENAMES.length > 0) {
                                 outError[0] = "Requires development platform " + targetCode
-                                        + " (current platform is " + SDK_CODENAME + ")";
+                                        + " (current platform is any of "
+                                        + Arrays.toString(SDK_CODENAMES) + ")";
                             } else {
                                 outError[0] = "Requires development platform " + targetCode
                                         + " but this is a release platform.";
@@ -2452,6 +2467,12 @@
             a.info.flags |= ActivityInfo.FLAG_PERSISTABLE;
         }
 
+        if (sa.getBoolean(
+                com.android.internal.R.styleable.AndroidManifestActivity_allowEmbedded,
+                false)) {
+            a.info.flags |= ActivityInfo.FLAG_ALLOW_EMBEDDED;
+        }
+
         if (!receiver) {
             if (sa.getBoolean(
                     com.android.internal.R.styleable.AndroidManifestActivity_hardwareAccelerated,
@@ -3292,19 +3313,23 @@
         if (packageName == null || packageName.length() == 0) {
             Slog.i(TAG, "verifier package name was null; skipping");
             return null;
-        } else if (encodedPublicKey == null) {
-            Slog.i(TAG, "verifier " + packageName + " public key was null; skipping");
         }
 
-        PublicKey publicKey = parsePublicKey(encodedPublicKey);
-        if (publicKey != null) {
-            return new VerifierInfo(packageName, publicKey);
+        final PublicKey publicKey = parsePublicKey(encodedPublicKey);
+        if (publicKey == null) {
+            Slog.i(TAG, "Unable to parse verifier public key for " + packageName);
+            return null;
         }
 
-        return null;
+        return new VerifierInfo(packageName, publicKey);
     }
 
-    public static final PublicKey parsePublicKey(String encodedPublicKey) {
+    public static final PublicKey parsePublicKey(final String encodedPublicKey) {
+        if (encodedPublicKey == null) {
+            Slog.i(TAG, "Could not parse null public key");
+            return null;
+        }
+
         EncodedKeySpec keySpec;
         try {
             final byte[] encoded = Base64.decode(encodedPublicKey, Base64.DEFAULT);
diff --git a/core/java/android/content/pm/Signature.java b/core/java/android/content/pm/Signature.java
index 752bf8b..f4e7dc3 100644
--- a/core/java/android/content/pm/Signature.java
+++ b/core/java/android/content/pm/Signature.java
@@ -25,6 +25,7 @@
 import java.lang.ref.SoftReference;
 import java.security.PublicKey;
 import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
 import java.util.Arrays;
@@ -38,12 +39,28 @@
     private int mHashCode;
     private boolean mHaveHashCode;
     private SoftReference<String> mStringRef;
+    private Certificate[] mCertificateChain;
 
     /**
      * Create Signature from an existing raw byte array.
      */
     public Signature(byte[] signature) {
         mSignature = signature.clone();
+        mCertificateChain = null;
+    }
+
+    /**
+     * Create signature from a certificate chain. Used for backward
+     * compatibility.
+     *
+     * @throws CertificateEncodingException
+     * @hide
+     */
+    public Signature(Certificate[] certificateChain) throws CertificateEncodingException {
+        mSignature = certificateChain[0].getEncoded();
+        if (certificateChain.length > 1) {
+            mCertificateChain = Arrays.copyOfRange(certificateChain, 1, certificateChain.length);
+        }
     }
 
     private static final int parseHexDigit(int nibble) {
@@ -156,6 +173,29 @@
         return cert.getPublicKey();
     }
 
+    /**
+     * Used for compatibility code that needs to check the certificate chain
+     * during upgrades.
+     *
+     * @throws CertificateEncodingException
+     * @hide
+     */
+    public Signature[] getChainSignatures() throws CertificateEncodingException {
+        if (mCertificateChain == null) {
+            return new Signature[] { this };
+        }
+
+        Signature[] chain = new Signature[1 + mCertificateChain.length];
+        chain[0] = this;
+
+        int i = 1;
+        for (Certificate c : mCertificateChain) {
+            chain[i++] = new Signature(c.getEncoded());
+        }
+
+        return chain;
+    }
+
     @Override
     public boolean equals(Object obj) {
         try {
diff --git a/core/java/android/content/pm/UserInfo.java b/core/java/android/content/pm/UserInfo.java
index f53aa4c..c0383a3 100644
--- a/core/java/android/content/pm/UserInfo.java
+++ b/core/java/android/content/pm/UserInfo.java
@@ -27,8 +27,8 @@
  */
 public class UserInfo implements Parcelable {
 
-    /** 6 bits for user type */
-    public static final int FLAG_MASK_USER_TYPE = 0x0000003F;
+    /** 8 bits for user type */
+    public static final int FLAG_MASK_USER_TYPE = 0x000000FF;
 
     /**
      * *************************** NOTE ***************************
@@ -70,6 +70,11 @@
      */
     public static final int FLAG_MANAGED_PROFILE = 0x00000020;
 
+    /**
+     * Indicates that this user is disabled.
+     */
+    public static final int FLAG_DISABLED = 0x00000040;
+
 
     public static final int NO_PROFILE_GROUP_ID = -1;
 
@@ -117,6 +122,10 @@
         return (flags & FLAG_MANAGED_PROFILE) == FLAG_MANAGED_PROFILE;
     }
 
+    public boolean isEnabled() {
+        return (flags & FLAG_DISABLED) != FLAG_DISABLED;
+    }
+
     /**
      * @return true if this user can be switched to.
      **/
diff --git a/core/java/android/ddm/DdmHandleHeap.java b/core/java/android/ddm/DdmHandleHeap.java
index cece556..e24aeb2 100644
--- a/core/java/android/ddm/DdmHandleHeap.java
+++ b/core/java/android/ddm/DdmHandleHeap.java
@@ -219,7 +219,7 @@
 
         if (false)
             Log.d("ddm-heap", "Heap GC request");
-        System.gc();
+        Runtime.getRuntime().gc();
 
         return null;        // empty response
     }
diff --git a/core/java/android/hardware/Sensor.java b/core/java/android/hardware/Sensor.java
index 89a5819..4bea9ee 100644
--- a/core/java/android/hardware/Sensor.java
+++ b/core/java/android/hardware/Sensor.java
@@ -38,6 +38,13 @@
     public static final int TYPE_ACCELEROMETER = 1;
 
     /**
+     * A constant string describing an accelerometer sensor type.
+     *
+     * @see #TYPE_ACCELEROMETER
+     */
+    public static final String STRING_TYPE_ACCELEROMETER = "android.sensor.accelerometer";
+
+    /**
      * A constant describing a magnetic field sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -45,6 +52,13 @@
     public static final int TYPE_MAGNETIC_FIELD = 2;
 
     /**
+     * A constant string describing a magnetic field sensor type.
+     *
+     * @see #TYPE_MAGNETIC_FIELD
+     */
+    public static final String STRING_TYPE_MAGNETIC_FIELD = "android.sensor.magnetic_field";
+
+    /**
      * A constant describing an orientation sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -55,24 +69,58 @@
     @Deprecated
     public static final int TYPE_ORIENTATION = 3;
 
-    /** A constant describing a gyroscope sensor type.
+    /**
+     * A constant string describing an orientation sensor type.
+     *
+     * @see #TYPE_ORIENTATION
+     * @deprecated use {@link android.hardware.SensorManager#getOrientation
+     *             SensorManager.getOrientation()} instead.
+     */
+    @Deprecated
+    public static final String STRING_TYPE_ORIENTATION = "android.sensor.orientation";
+
+    /**
+     * A constant describing a gyroscope sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details. */
     public static final int TYPE_GYROSCOPE = 4;
 
     /**
+     * A constant string describing a gyroscope sensor type.
+     *
+     * @see #TYPE_GYROSCOPE
+     */
+    public static final String STRING_TYPE_GYROSCOPE = "android.sensor.gyroscope";
+
+    /**
      * A constant describing a light sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
      */
     public static final int TYPE_LIGHT = 5;
 
-    /** A constant describing a pressure sensor type.
+    /**
+     * A constant string describing a light sensor type.
+     *
+     * @see #TYPE_LIGHT
+     */
+    public static final String STRING_TYPE_LIGHT = "android.sensor.light";
+
+    /**
+     * A constant describing a pressure sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
-     * for more details. */
+     * for more details.
+     */
     public static final int TYPE_PRESSURE = 6;
 
     /**
+     * A constant string describing a pressure sensor type.
+     *
+     * @see #TYPE_PRESSURE
+     */
+    public static final String STRING_TYPE_PRESSURE = "android.sensor.pressure";
+
+    /**
      * A constant describing a temperature sensor type
      *
      * @deprecated use
@@ -83,6 +131,17 @@
     public static final int TYPE_TEMPERATURE = 7;
 
     /**
+     * A constant string describing a temperature sensor type
+     *
+     * @see #TYPE_TEMPERATURE
+     * @deprecated use
+     *             {@link android.hardware.Sensor#STRING_TYPE_AMBIENT_TEMPERATURE
+     *             Sensor.STRING_TYPE_AMBIENT_TEMPERATURE} instead.
+     */
+    @Deprecated
+    public static final String STRING_TYPE_TEMPERATURE = "android.sensor.temperature";
+
+    /**
      * A constant describing a proximity sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -90,6 +149,13 @@
     public static final int TYPE_PROXIMITY = 8;
 
     /**
+     * A constant string describing a proximity sensor type.
+     *
+     * @see #TYPE_PROXIMITY
+     */
+    public static final String STRING_TYPE_PROXIMITY = "android.sensor.proximity";
+
+    /**
      * A constant describing a gravity sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -97,6 +163,13 @@
     public static final int TYPE_GRAVITY = 9;
 
     /**
+     * A constant string describing a gravity sensor type.
+     *
+     * @see #TYPE_GRAVITY
+     */
+    public static final String STRING_TYPE_GRAVITY = "android.sensor.gravity";
+
+    /**
      * A constant describing a linear acceleration sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -104,6 +177,14 @@
     public static final int TYPE_LINEAR_ACCELERATION = 10;
 
     /**
+     * A constant string describing a linear acceleration sensor type.
+     *
+     * @see #TYPE_LINEAR_ACCELERATION
+     */
+    public static final String STRING_TYPE_LINEAR_ACCELERATION =
+        "android.sensor.linear_acceleration";
+
+    /**
      * A constant describing a rotation vector sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
@@ -111,18 +192,42 @@
     public static final int TYPE_ROTATION_VECTOR = 11;
 
     /**
+     * A constant string describing a rotation vector sensor type.
+     *
+     * @see #TYPE_ROTATION_VECTOR
+     */
+    public static final String STRING_TYPE_ROTATION_VECTOR = "android.sensor.rotation_vector";
+
+    /**
      * A constant describing a relative humidity sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
      * for more details.
      */
     public static final int TYPE_RELATIVE_HUMIDITY = 12;
 
-    /** A constant describing an ambient temperature sensor type.
+    /**
+     * A constant string describing a relative humidity sensor type
+     *
+     * @see #TYPE_RELATIVE_HUMIDITY
+     */
+    public static final String STRING_TYPE_RELATIVE_HUMIDITY = "android.sensor.relative_humidity";
+
+    /**
+     * A constant describing an ambient temperature sensor type.
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values}
-     * for more details. */
+     * for more details.
+     */
     public static final int TYPE_AMBIENT_TEMPERATURE = 13;
 
     /**
+     * A constant string describing an ambient temperature sensor type.
+     *
+     * @see #TYPE_AMBIENT_TEMPERATURE
+     */
+    public static final String STRING_TYPE_AMBIENT_TEMPERATURE =
+        "android.sensor.ambient_temperature";
+
+    /**
      * A constant describing an uncalibrated magnetic field sensor type.
      * <p>
      * Similar to {@link #TYPE_MAGNETIC_FIELD} but the hard iron calibration (device calibration
@@ -139,6 +244,13 @@
      * details.
      */
     public static final int TYPE_MAGNETIC_FIELD_UNCALIBRATED = 14;
+    /**
+     * A constant string describing an uncalibrated magnetic field sensor type.
+     *
+     * @see #TYPE_MAGNETIC_FIELD_UNCALIBRATED
+     */
+    public static final String STRING_TYPE_MAGNETIC_FIELD_UNCALIBRATED =
+        "android.sensor.magnetic_field_uncalibrated";
 
     /**
      * A constant describing an uncalibrated rotation vector sensor type.
@@ -156,10 +268,17 @@
      * <p>See {@link android.hardware.SensorEvent#values SensorEvent.values} for more
      * details.
      */
-
     public static final int TYPE_GAME_ROTATION_VECTOR = 15;
 
     /**
+     * A constant string describing an uncalibrated rotation vector sensor type.
+     *
+     * @see #TYPE_GAME_ROTATION_VECTOR
+     */
+    public static final String STRING_TYPE_GAME_ROTATION_VECTOR =
+        "android.sensor.game_rotation_vector";
+
+    /**
      * A constant describing an uncalibrated gyroscope sensor type.
      * <p>Similar to {@link #TYPE_GYROSCOPE} but no gyro-drift compensation has been performed
      * to adjust the given sensor values. However, such gyro-drift bias values
@@ -174,6 +293,14 @@
     public static final int TYPE_GYROSCOPE_UNCALIBRATED = 16;
 
     /**
+     * A constant string describing an uncalibrated gyroscope sensor type.
+     *
+     * @see #TYPE_GYROSCOPE_UNCALIBRATED
+     */
+    public static final String STRING_TYPE_GYROSCOPE_UNCALIBRATED =
+        "android.sensor.gyroscope_uncalibrated";
+
+    /**
      * A constant describing a significant motion trigger sensor.
      * <p>
      * It triggers when an event occurs and then automatically disables
@@ -186,6 +313,14 @@
     public static final int TYPE_SIGNIFICANT_MOTION = 17;
 
     /**
+     * A constant string describing a significant motion trigger sensor.
+     *
+     * @see #TYPE_SIGNIFICANT_MOTION
+     */
+    public static final String STRING_TYPE_SIGNIFICANT_MOTION =
+        "android.sensor.significant_motion";
+
+    /**
      * A constant describing a step detector sensor.
      * <p>
      * A sensor of this type triggers an event each time a step is taken by the user. The only
@@ -198,6 +333,13 @@
     public static final int TYPE_STEP_DETECTOR = 18;
 
     /**
+     * A constant string describing a step detector sensor.
+     *
+     * @see #TYPE_STEP_DETECTOR
+     */
+    public static final String STRING_TYPE_STEP_DETECTOR = "android.sensor.step_detector";
+
+    /**
      * A constant describing a step counter sensor.
      * <p>
      * A sensor of this type returns the number of steps taken by the user since the last reboot
@@ -211,7 +353,14 @@
     public static final int TYPE_STEP_COUNTER = 19;
 
     /**
-     * A constant describing the geo-magnetic rotation vector.
+     * A constant string describing a step counter sensor.
+     *
+     * @see #TYPE_STEP_COUNTER
+     */
+    public static final String STRING_TYPE_STEP_COUNTER = "android.sensor.step_counter";
+
+    /**
+     * A constant describing a geo-magnetic rotation vector.
      * <p>
      * Similar to {@link #TYPE_ROTATION_VECTOR}, but using a magnetometer instead of using a
      * gyroscope. This sensor uses lower power than the other rotation vectors, because it doesn't
@@ -222,6 +371,32 @@
     public static final int TYPE_GEOMAGNETIC_ROTATION_VECTOR = 20;
 
     /**
+     * A constant string describing a geo-magnetic rotation vector.
+     *
+     * @see #TYPE_GEOMAGNETIC_ROTATION_VECTOR
+     */
+    public static final String STRING_TYPE_GEOMAGNETIC_ROTATION_VECTOR =
+        "android.sensor.geomagnetic_rotation_vector";
+
+    /**
+     * A constant describing a heart rate monitor.
+     * <p>
+     * A sensor that measures the heart rate in beats per minute.
+     * <p>
+     * value[0] represents the beats per minute when the measurement was taken.
+     * value[0] is 0 if the heart rate monitor could not measure the rate or the
+     * rate is 0 beat per minute.
+     */
+    public static final int TYPE_HEART_RATE = 21;
+
+    /**
+     * A constant string describing a heart rate monitor.
+     *
+     * @see #TYPE_HEART_RATE
+     */
+    public static final String STRING_TYPE_HEART_RATE = "android.sensor.heart_rate";
+
+    /**
      * A constant describing all sensor types.
      */
     public static final int TYPE_ALL = -1;
@@ -265,7 +440,8 @@
             // added post 4.3
             REPORTING_MODE_ON_CHANGE,  1, // SENSOR_TYPE_STEP_DETECTOR
             REPORTING_MODE_ON_CHANGE,  1, // SENSOR_TYPE_STEP_COUNTER
-            REPORTING_MODE_CONTINUOUS, 5  // SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR
+            REPORTING_MODE_CONTINUOUS, 5, // SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR
+            REPORTING_MODE_ON_CHANGE, 1  // SENSOR_TYPE_HEART_RATE_MONITOR
     };
 
     static int getReportingMode(Sensor sensor) {
@@ -321,6 +497,8 @@
     private int     mMinDelay;
     private int     mFifoReservedEventCount;
     private int     mFifoMaxEventCount;
+    private String  mStringType;
+    private String  mRequiredPermission;
 
     Sensor() {
     }
@@ -401,6 +579,20 @@
         return mFifoMaxEventCount;
     }
 
+    /**
+     * @return The type of this sensor as a string.
+     */
+    public String getStringType() {
+        return mStringType;
+    }
+
+    /**
+     * @return The permission required to access this sensor. If empty, no permission is required.
+     */
+    public String getRequiredPermission() {
+        return mRequiredPermission;
+    }
+
     /** @hide */
     public int getHandle() {
         return mHandle;
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 9852776..722d956 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -455,22 +455,25 @@
      * <p>The maximum numbers of different types of output streams
      * that can be configured and used simultaneously by a camera device.</p>
      * <p>This is a 3 element tuple that contains the max number of output simultaneous
-     * streams for raw sensor, processed (and uncompressed), and JPEG formats respectively.
-     * For example, if max raw sensor format output stream number is 1, max YUV streams
+     * streams for raw sensor, processed (but not stalling), and processed (and stalling)
+     * formats respectively. For example, assuming that JPEG is typically a processed and
+     * stalling stream, if max raw sensor format output stream number is 1, max YUV streams
      * number is 3, and max JPEG stream number is 2, then this tuple should be <code>(1, 3, 2)</code>.</p>
      * <p>This lists the upper bound of the number of output streams supported by
      * the camera device. Using more streams simultaneously may require more hardware and
      * CPU resources that will consume more power. The image format for a output stream can
-     * be any supported format provided by {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats}. The formats
-     * defined in {@link CameraCharacteristics#SCALER_AVAILABLE_FORMATS android.scaler.availableFormats} can be catergorized into the 3 stream types
-     * as below:</p>
+     * be any supported format provided by {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS android.scaler.availableStreamConfigurations}.
+     * The formats defined in {@link CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS android.scaler.availableStreamConfigurations} can be catergorized
+     * into the 3 stream types as below:</p>
      * <ul>
-     * <li>JPEG-compressed format: BLOB.</li>
-     * <li>Raw formats: RAW_SENSOR and RAW_OPAQUE.</li>
-     * <li>processed, uncompressed formats: YCbCr_420_888, YCrCb_420_SP, YV12.</li>
+     * <li>Processed (but stalling): any non-RAW format with a stallDurations &gt; 0.
+     * Typically JPEG format (ImageFormat#JPEG).</li>
+     * <li>Raw formats: ImageFormat#RAW_SENSOR and ImageFormat#RAW_OPAQUE.</li>
+     * <li>Processed (but not-stalling): any non-RAW format without a stall duration.
+     * Typically ImageFormat#YUV_420_888, ImageFormat#NV21, ImageFormat#YV12.</li>
      * </ul>
      *
-     * @see CameraCharacteristics#SCALER_AVAILABLE_FORMATS
+     * @see CameraCharacteristics#SCALER_AVAILABLE_STREAM_CONFIGURATIONS
      */
     public static final Key<int[]> REQUEST_MAX_NUM_OUTPUT_STREAMS =
             new Key<int[]>("android.request.maxNumOutputStreams", int[].class);
@@ -1030,6 +1033,195 @@
             new Key<Integer>("android.sensor.info.whiteLevel", int.class);
 
     /**
+     * <p>The standard reference illuminant used as the scene light source when
+     * calculating the {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM1 android.sensor.colorTransform1},
+     * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1 android.sensor.calibrationTransform1}, and
+     * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX1 android.sensor.forwardMatrix1} matrices.</p>
+     * <p>The values in this tag correspond to the values defined for the
+     * EXIF LightSource tag. These illuminants are standard light sources
+     * that are often used calibrating camera devices.</p>
+     * <p>If this tag is present, then {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM1 android.sensor.colorTransform1},
+     * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1 android.sensor.calibrationTransform1}, and
+     * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX1 android.sensor.forwardMatrix1} will also be present.</p>
+     * <p>Some devices may choose to provide a second set of calibration
+     * information for improved quality, including
+     * {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2} and its corresponding matrices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM1
+     * @see CameraCharacteristics#SENSOR_COLOR_TRANSFORM1
+     * @see CameraCharacteristics#SENSOR_FORWARD_MATRIX1
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_FLASH
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_SHADE
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_D55
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_D65
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_D75
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_D50
+     * @see #SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN
+     */
+    public static final Key<Integer> SENSOR_REFERENCE_ILLUMINANT1 =
+            new Key<Integer>("android.sensor.referenceIlluminant1", int.class);
+
+    /**
+     * <p>The standard reference illuminant used as the scene light source when
+     * calculating the {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM2 android.sensor.colorTransform2},
+     * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2 android.sensor.calibrationTransform2}, and
+     * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX2 android.sensor.forwardMatrix2} matrices.</p>
+     * <p>See {@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1} for more details.
+     * Valid values for this are the same as those given for the first
+     * reference illuminant.</p>
+     * <p>If this tag is present, then {@link CameraCharacteristics#SENSOR_COLOR_TRANSFORM2 android.sensor.colorTransform2},
+     * {@link CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2 android.sensor.calibrationTransform2}, and
+     * {@link CameraCharacteristics#SENSOR_FORWARD_MATRIX2 android.sensor.forwardMatrix2} will also be present.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_CALIBRATION_TRANSFORM2
+     * @see CameraCharacteristics#SENSOR_COLOR_TRANSFORM2
+     * @see CameraCharacteristics#SENSOR_FORWARD_MATRIX2
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final Key<Byte> SENSOR_REFERENCE_ILLUMINANT2 =
+            new Key<Byte>("android.sensor.referenceIlluminant2", byte.class);
+
+    /**
+     * <p>A per-device calibration transform matrix that maps from the
+     * reference sensor colorspace to the actual device sensor colorspace.</p>
+     * <p>This matrix is used to correct for per-device variations in the
+     * sensor colorspace, and is used for processing raw buffer data.</p>
+     * <p>The matrix is expressed as a 3x3 matrix in row-major-order, and
+     * contains a per-device calibration transform that maps colors
+     * from reference sensor color space (i.e. the "golden module"
+     * colorspace) into this camera device's native sensor color
+     * space under the first reference illuminant
+     * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final Key<Rational[]> SENSOR_CALIBRATION_TRANSFORM1 =
+            new Key<Rational[]>("android.sensor.calibrationTransform1", Rational[].class);
+
+    /**
+     * <p>A per-device calibration transform matrix that maps from the
+     * reference sensor colorspace to the actual device sensor colorspace
+     * (this is the colorspace of the raw buffer data).</p>
+     * <p>This matrix is used to correct for per-device variations in the
+     * sensor colorspace, and is used for processing raw buffer data.</p>
+     * <p>The matrix is expressed as a 3x3 matrix in row-major-order, and
+     * contains a per-device calibration transform that maps colors
+     * from reference sensor color space (i.e. the "golden module"
+     * colorspace) into this camera device's native sensor color
+     * space under the second reference illuminant
+     * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2}).</p>
+     * <p>This matrix will only be present if the second reference
+     * illuminant is present.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
+     */
+    public static final Key<Rational[]> SENSOR_CALIBRATION_TRANSFORM2 =
+            new Key<Rational[]>("android.sensor.calibrationTransform2", Rational[].class);
+
+    /**
+     * <p>A matrix that transforms color values from CIE XYZ color space to
+     * reference sensor color space.</p>
+     * <p>This matrix is used to convert from the standard CIE XYZ color
+     * space to the reference sensor colorspace, and is used when processing
+     * raw buffer data.</p>
+     * <p>The matrix is expressed as a 3x3 matrix in row-major-order, and
+     * contains a color transform matrix that maps colors from the CIE
+     * XYZ color space to the reference sensor color space (i.e. the
+     * "golden module" colorspace) under the first reference illuminant
+     * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1}).</p>
+     * <p>The white points chosen in both the reference sensor color space
+     * and the CIE XYZ colorspace when calculating this transform will
+     * match the standard white point for the first reference illuminant
+     * (i.e. no chromatic adaptation will be applied by this transform).</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final Key<Rational[]> SENSOR_COLOR_TRANSFORM1 =
+            new Key<Rational[]>("android.sensor.colorTransform1", Rational[].class);
+
+    /**
+     * <p>A matrix that transforms color values from CIE XYZ color space to
+     * reference sensor color space.</p>
+     * <p>This matrix is used to convert from the standard CIE XYZ color
+     * space to the reference sensor colorspace, and is used when processing
+     * raw buffer data.</p>
+     * <p>The matrix is expressed as a 3x3 matrix in row-major-order, and
+     * contains a color transform matrix that maps colors from the CIE
+     * XYZ color space to the reference sensor color space (i.e. the
+     * "golden module" colorspace) under the second reference illuminant
+     * ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2}).</p>
+     * <p>The white points chosen in both the reference sensor color space
+     * and the CIE XYZ colorspace when calculating this transform will
+     * match the standard white point for the second reference illuminant
+     * (i.e. no chromatic adaptation will be applied by this transform).</p>
+     * <p>This matrix will only be present if the second reference
+     * illuminant is present.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
+     */
+    public static final Key<Rational[]> SENSOR_COLOR_TRANSFORM2 =
+            new Key<Rational[]>("android.sensor.colorTransform2", Rational[].class);
+
+    /**
+     * <p>A matrix that transforms white balanced camera colors from the reference
+     * sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.</p>
+     * <p>This matrix is used to convert to the standard CIE XYZ colorspace, and
+     * is used when processing raw buffer data.</p>
+     * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and contains
+     * a color transform matrix that maps white balanced colors from the
+     * reference sensor color space to the CIE XYZ color space with a D50 white
+     * point.</p>
+     * <p>Under the first reference illuminant ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1 android.sensor.referenceIlluminant1})
+     * this matrix is chosen so that the standard white point for this reference
+     * illuminant in the reference sensor colorspace is mapped to D50 in the
+     * CIE XYZ colorspace.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final Key<Rational[]> SENSOR_FORWARD_MATRIX1 =
+            new Key<Rational[]>("android.sensor.forwardMatrix1", Rational[].class);
+
+    /**
+     * <p>A matrix that transforms white balanced camera colors from the reference
+     * sensor colorspace to the CIE XYZ colorspace with a D50 whitepoint.</p>
+     * <p>This matrix is used to convert to the standard CIE XYZ colorspace, and
+     * is used when processing raw buffer data.</p>
+     * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and contains
+     * a color transform matrix that maps white balanced colors from the
+     * reference sensor color space to the CIE XYZ color space with a D50 white
+     * point.</p>
+     * <p>Under the second reference illuminant ({@link CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2 android.sensor.referenceIlluminant2})
+     * this matrix is chosen so that the standard white point for this reference
+     * illuminant in the reference sensor colorspace is mapped to D50 in the
+     * CIE XYZ colorspace.</p>
+     * <p>This matrix will only be present if the second reference
+     * illuminant is present.</p>
+     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
+     *
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT2
+     */
+    public static final Key<Rational[]> SENSOR_FORWARD_MATRIX2 =
+            new Key<Rational[]>("android.sensor.forwardMatrix2", Rational[].class);
+
+    /**
      * <p>Gain factor from electrons to raw units when
      * ISO=100</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 2c53f03..bb290af 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -570,6 +570,14 @@
     public static abstract class CaptureListener {
 
         /**
+         * This constant is used to indicate that no images were captured for
+         * the request.
+         *
+         * @hide
+         */
+        public static final int NO_FRAMES_CAPTURED = -1;
+
+        /**
          * This method is called when the camera device has started capturing
          * the output image for the request, at the beginning of image exposure.
          *
@@ -693,9 +701,12 @@
          *            The CameraDevice sending the callback.
          * @param sequenceId
          *            A sequence ID returned by the {@link #capture} family of functions.
-         * @param frameNumber
+         * @param lastFrameNumber
          *            The last frame number (returned by {@link CaptureResult#getFrameNumber}
          *            or {@link CaptureFailure#getFrameNumber}) in the capture sequence.
+         *            The last frame number may be equal to NO_FRAMES_CAPTURED if no images
+         *            were captured for this sequence. This can happen, for example, when a
+         *            repeating request or burst is cleared right after being set.
          *
          * @see CaptureResult#getFrameNumber()
          * @see CaptureFailure#getFrameNumber()
@@ -703,7 +714,7 @@
          * @see CaptureFailure#getSequenceId()
          */
         public void onCaptureSequenceCompleted(CameraDevice camera,
-                int sequenceId, int frameNumber) {
+                int sequenceId, int lastFrameNumber) {
             // default empty implementation
         }
     }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 1e34498..ba8db3a 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -457,6 +457,110 @@
     public static final int SENSOR_INFO_COLOR_FILTER_ARRANGEMENT_RGB = 4;
 
     //
+    // Enumeration values for CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+    //
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT = 1;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_FLUORESCENT = 2;
+
+    /**
+     * <p>Incandescent light</p>
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_TUNGSTEN = 3;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_FLASH = 4;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_FINE_WEATHER = 9;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_CLOUDY_WEATHER = 10;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_SHADE = 11;
+
+    /**
+     * <p>D 5700 - 7100K</p>
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_DAYLIGHT_FLUORESCENT = 12;
+
+    /**
+     * <p>N 4600 - 5400K</p>
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_DAY_WHITE_FLUORESCENT = 13;
+
+    /**
+     * <p>W 3900 - 4500K</p>
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_COOL_WHITE_FLUORESCENT = 14;
+
+    /**
+     * <p>WW 3200 - 3700K</p>
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_WHITE_FLUORESCENT = 15;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_A = 17;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_B = 18;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_STANDARD_C = 19;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_D55 = 20;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_D65 = 21;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_D75 = 22;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_D50 = 23;
+
+    /**
+     * @see CameraCharacteristics#SENSOR_REFERENCE_ILLUMINANT1
+     */
+    public static final int SENSOR_REFERENCE_ILLUMINANT1_ISO_STUDIO_TUNGSTEN = 24;
+
+    //
     // Enumeration values for CameraCharacteristics#LED_AVAILABLE_LEDS
     //
 
@@ -940,6 +1044,17 @@
      */
     public static final int CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG = 5;
 
+    /**
+     * <p>This request is for manual capture use case where
+     * the applications want to directly control the capture parameters
+     * (e.g. {@link CaptureRequest#SENSOR_EXPOSURE_TIME android.sensor.exposureTime}, {@link CaptureRequest#SENSOR_SENSITIVITY android.sensor.sensitivity} etc.).</p>
+     *
+     * @see CaptureRequest#SENSOR_EXPOSURE_TIME
+     * @see CaptureRequest#SENSOR_SENSITIVITY
+     * @see CaptureRequest#CONTROL_CAPTURE_INTENT
+     */
+    public static final int CONTROL_CAPTURE_INTENT_MANUAL = 6;
+
     //
     // Enumeration values for CaptureRequest#CONTROL_EFFECT_MODE
     //
@@ -1720,110 +1835,6 @@
     public static final int LENS_STATE_MOVING = 1;
 
     //
-    // Enumeration values for CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-    //
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT = 1;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT = 2;
-
-    /**
-     * <p>Incandescent light</p>
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN = 3;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_FLASH = 4;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER = 9;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER = 10;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_SHADE = 11;
-
-    /**
-     * <p>D 5700 - 7100K</p>
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT = 12;
-
-    /**
-     * <p>N 4600 - 5400K</p>
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT = 13;
-
-    /**
-     * <p>W 3900 - 4500K</p>
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT = 14;
-
-    /**
-     * <p>WW 3200 - 3700K</p>
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT = 15;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_A = 17;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_B = 18;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_STANDARD_C = 19;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_D55 = 20;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_D65 = 21;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_D75 = 22;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_D50 = 23;
-
-    /**
-     * @see CaptureResult#SENSOR_REFERENCE_ILLUMINANT
-     */
-    public static final int SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN = 24;
-
-    //
     // Enumeration values for CaptureResult#STATISTICS_SCENE_FLICKER
     //
 
diff --git a/core/java/android/hardware/camera2/CaptureRequest.java b/core/java/android/hardware/camera2/CaptureRequest.java
index 7656505..c4e342c 100644
--- a/core/java/android/hardware/camera2/CaptureRequest.java
+++ b/core/java/android/hardware/camera2/CaptureRequest.java
@@ -714,16 +714,21 @@
      * auto-focus, auto-white balance) routines about the purpose
      * of this capture, to help the camera device to decide optimal 3A
      * strategy.</p>
-     * <p>This control is only effective if <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code>
-     * and any 3A routine is active.</p>
+     * <p>This control (except for MANUAL) is only effective if
+     * <code>{@link CaptureRequest#CONTROL_MODE android.control.mode} != OFF</code> and any 3A routine is active.</p>
+     * <p>ZERO_SHUTTER_LAG must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains ZSL. MANUAL must be supported if {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities}
+     * contains MANUAL_SENSOR.</p>
      *
      * @see CaptureRequest#CONTROL_MODE
+     * @see CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES
      * @see #CONTROL_CAPTURE_INTENT_CUSTOM
      * @see #CONTROL_CAPTURE_INTENT_PREVIEW
      * @see #CONTROL_CAPTURE_INTENT_STILL_CAPTURE
      * @see #CONTROL_CAPTURE_INTENT_VIDEO_RECORD
      * @see #CONTROL_CAPTURE_INTENT_VIDEO_SNAPSHOT
      * @see #CONTROL_CAPTURE_INTENT_ZERO_SHUTTER_LAG
+     * @see #CONTROL_CAPTURE_INTENT_MANUAL
      */
     public static final Key<Integer> CONTROL_CAPTURE_INTENT =
             new Key<Integer>("android.control.captureIntent", int.class);
diff --git a/core/java/android/hardware/camera2/CaptureResult.java b/core/java/android/hardware/camera2/CaptureResult.java
index b3bce3b..d8981c8 100644
--- a/core/java/android/hardware/camera2/CaptureResult.java
+++ b/core/java/android/hardware/camera2/CaptureResult.java
@@ -1607,77 +1607,14 @@
             new Key<Float>("android.sensor.temperature", float.class);
 
     /**
-     * <p>A reference illumination source roughly matching the current scene
-     * illumination, which is used to describe the sensor color space
-     * transformations.</p>
-     * <p>The values in this tag correspond to the values defined for the
-     * EXIF LightSource tag. These illuminants are standard light sources
-     * that are often used for calibrating camera devices.</p>
-     * @see #SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_FLUORESCENT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_TUNGSTEN
-     * @see #SENSOR_REFERENCE_ILLUMINANT_FLASH
-     * @see #SENSOR_REFERENCE_ILLUMINANT_FINE_WEATHER
-     * @see #SENSOR_REFERENCE_ILLUMINANT_CLOUDY_WEATHER
-     * @see #SENSOR_REFERENCE_ILLUMINANT_SHADE
-     * @see #SENSOR_REFERENCE_ILLUMINANT_DAYLIGHT_FLUORESCENT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_DAY_WHITE_FLUORESCENT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_COOL_WHITE_FLUORESCENT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_WHITE_FLUORESCENT
-     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_A
-     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_B
-     * @see #SENSOR_REFERENCE_ILLUMINANT_STANDARD_C
-     * @see #SENSOR_REFERENCE_ILLUMINANT_D55
-     * @see #SENSOR_REFERENCE_ILLUMINANT_D65
-     * @see #SENSOR_REFERENCE_ILLUMINANT_D75
-     * @see #SENSOR_REFERENCE_ILLUMINANT_D50
-     * @see #SENSOR_REFERENCE_ILLUMINANT_ISO_STUDIO_TUNGSTEN
-     */
-    public static final Key<Integer> SENSOR_REFERENCE_ILLUMINANT =
-            new Key<Integer>("android.sensor.referenceIlluminant", int.class);
-
-    /**
-     * <p>A per-device calibration transform matrix to be applied after the
-     * color space transform when rendering the raw image buffer.</p>
-     * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and
-     * contains a per-device calibration transform that maps colors
-     * from reference camera color space (i.e. the "golden module"
-     * colorspace) into this camera device's linear native sensor color
-     * space for the current scene illumination and white balance choice.</p>
-     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
-     */
-    public static final Key<Rational[]> SENSOR_CALIBRATION_TRANSFORM =
-            new Key<Rational[]>("android.sensor.calibrationTransform", Rational[].class);
-
-    /**
-     * <p>A matrix that transforms color values from CIE XYZ color space to
-     * reference camera color space when rendering the raw image buffer.</p>
-     * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and
-     * contains a color transform matrix that maps colors from the CIE
-     * XYZ color space to the reference camera raw color space (i.e. the
-     * "golden module" colorspace) for the current scene illumination and
-     * white balance choice.</p>
-     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
-     */
-    public static final Key<Rational[]> SENSOR_COLOR_TRANSFORM =
-            new Key<Rational[]>("android.sensor.colorTransform", Rational[].class);
-
-    /**
-     * <p>A matrix that transforms white balanced camera colors to the CIE XYZ
-     * colorspace with a D50 whitepoint.</p>
-     * <p>This matrix is expressed as a 3x3 matrix in row-major-order, and contains
-     * a color transform matrix that maps a unit vector in the linear native
-     * sensor color space to the D50 whitepoint in CIE XYZ color space.</p>
-     * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
-     */
-    public static final Key<Rational[]> SENSOR_FORWARD_MATRIX =
-            new Key<Rational[]>("android.sensor.forwardMatrix", Rational[].class);
-
-    /**
-     * <p>The estimated white balance at the time of capture.</p>
-     * <p>The estimated white balance encoded as the RGB values of the
-     * perfectly neutral color point in the linear native sensor color space.
-     * The order of the values is R, G, B; where R is in the lowest index.</p>
+     * <p>The estimated camera neutral color in the native sensor colorspace at
+     * the time of capture.</p>
+     * <p>This value gives the neutral color point encoded as an RGB value in the
+     * native sensor color space.  The neutral color point indicates the
+     * currently estimated white point of the scene illumination.  It can be
+     * used to interpolate between the provided color transforms when
+     * processing raw sensor data.</p>
+     * <p>The order of the values is R, G, B; where R is in the lowest index.</p>
      * <p><b>Optional</b> - This value may be {@code null} on some devices.</p>
      */
     public static final Key<Rational[]> SENSOR_NEUTRAL_COLOR_POINT =
@@ -2197,8 +2134,8 @@
      * @see #SYNC_FRAME_NUMBER_UNKNOWN
      * @hide
      */
-    public static final Key<Integer> SYNC_FRAME_NUMBER =
-            new Key<Integer>("android.sync.frameNumber", int.class);
+    public static final Key<Long> SYNC_FRAME_NUMBER =
+            new Key<Long>("android.sync.frameNumber", long.class);
 
     /*~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~@~
      * End generated code
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
similarity index 69%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/hardware/camera2/CaptureResultExtras.aidl
index 0377123..6587f02 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.hardware.camera2;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+/** @hide */
+parcelable CaptureResultExtras;
diff --git a/core/java/android/hardware/camera2/CaptureResultExtras.java b/core/java/android/hardware/camera2/CaptureResultExtras.java
new file mode 100644
index 0000000..e5c2c1c
--- /dev/null
+++ b/core/java/android/hardware/camera2/CaptureResultExtras.java
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class CaptureResultExtras implements Parcelable {
+    private int requestId;
+    private int subsequenceId;
+    private int afTriggerId;
+    private int precaptureTriggerId;
+    private long frameNumber;
+
+    public static final Parcelable.Creator<CaptureResultExtras> CREATOR =
+            new Parcelable.Creator<CaptureResultExtras>() {
+        @Override
+        public CaptureResultExtras createFromParcel(Parcel in) {
+            return new CaptureResultExtras(in);
+        }
+
+        @Override
+        public CaptureResultExtras[] newArray(int size) {
+            return new CaptureResultExtras[size];
+        }
+    };
+
+    private CaptureResultExtras(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(requestId);
+        dest.writeInt(subsequenceId);
+        dest.writeInt(afTriggerId);
+        dest.writeInt(precaptureTriggerId);
+        dest.writeLong(frameNumber);
+    }
+
+    public void readFromParcel(Parcel in) {
+        requestId = in.readInt();
+        subsequenceId = in.readInt();
+        afTriggerId = in.readInt();
+        precaptureTriggerId = in.readInt();
+        frameNumber = in.readLong();
+    }
+
+    public int getRequestId() {
+        return requestId;
+    }
+
+    public int getSubsequenceId() {
+        return subsequenceId;
+    }
+
+    public int getAfTriggerId() {
+        return afTriggerId;
+    }
+
+    public int getPrecaptureTriggerId() {
+        return precaptureTriggerId;
+    }
+
+    public long getFrameNumber() {
+        return frameNumber;
+    }
+
+}
diff --git a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
index 02a73d66..a14d38b 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceCallbacks.aidl
@@ -17,6 +17,7 @@
 package android.hardware.camera2;
 
 import android.hardware.camera2.impl.CameraMetadataNative;
+import android.hardware.camera2.CaptureResultExtras;
 
 /** @hide */
 interface ICameraDeviceCallbacks
@@ -25,8 +26,9 @@
      * Keep up-to-date with frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
      */
 
-    oneway void onCameraError(int errorCode);
+    oneway void onCameraError(int errorCode, in CaptureResultExtras resultExtras);
     oneway void onCameraIdle();
-    oneway void onCaptureStarted(int requestId, long timestamp);
-    oneway void onResultReceived(int requestId, in CameraMetadataNative result);
+    oneway void onCaptureStarted(in CaptureResultExtras resultExtras, long timestamp);
+    oneway void onResultReceived(in CameraMetadataNative result,
+                                 in CaptureResultExtras resultExtras);
 }
diff --git a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
index 1936963..d77f3d1 100644
--- a/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
+++ b/core/java/android/hardware/camera2/ICameraDeviceUser.aidl
@@ -20,6 +20,8 @@
 import android.hardware.camera2.impl.CameraMetadataNative;
 import android.hardware.camera2.CaptureRequest;
 
+import android.hardware.camera2.LongParcelable;
+
 /** @hide */
 interface ICameraDeviceUser
 {
@@ -31,9 +33,13 @@
     // ints here are status_t
 
     // non-negative value is the requestId. negative value is status_t
-    int submitRequest(in CaptureRequest request, boolean streaming);
+    int submitRequest(in CaptureRequest request, boolean streaming,
+                      out LongParcelable lastFrameNumber);
 
-    int cancelRequest(int requestId);
+    int submitRequestList(in List<CaptureRequest> requestList, boolean streaming,
+                          out LongParcelable lastFrameNumber);
+
+    int cancelRequest(int requestId, out LongParcelable lastFrameNumber);
 
     int deleteStream(int streamId);
 
@@ -46,5 +52,5 @@
 
     int waitUntilIdle();
 
-    int flush();
+    int flush(out LongParcelable lastFrameNumber);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/hardware/camera2/LongParcelable.aidl
similarity index 69%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/hardware/camera2/LongParcelable.aidl
index 0377123..7d7e51b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/hardware/camera2/LongParcelable.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.hardware.camera2;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+/** @hide */
+parcelable LongParcelable;
\ No newline at end of file
diff --git a/core/java/android/hardware/camera2/LongParcelable.java b/core/java/android/hardware/camera2/LongParcelable.java
new file mode 100644
index 0000000..97b0631
--- /dev/null
+++ b/core/java/android/hardware/camera2/LongParcelable.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.hardware.camera2;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * @hide
+ */
+public class LongParcelable implements Parcelable {
+    private long number;
+
+    public LongParcelable() {
+        this.number = 0;
+    }
+
+    public LongParcelable(long number) {
+        this.number = number;
+    }
+
+    public static final Parcelable.Creator<LongParcelable> CREATOR =
+            new Parcelable.Creator<LongParcelable>() {
+        @Override
+        public LongParcelable createFromParcel(Parcel in) {
+            return new LongParcelable(in);
+        }
+
+        @Override
+        public LongParcelable[] newArray(int size) {
+            return new LongParcelable[size];
+        }
+    };
+
+    private LongParcelable(Parcel in) {
+        readFromParcel(in);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeLong(number);
+    }
+
+    public void readFromParcel(Parcel in) {
+        number = in.readLong();
+    }
+
+    public long getNumber() {
+        return number;
+    }
+
+    public void setNumber(long number) {
+        this.number = number;
+    }
+
+}
diff --git a/core/java/android/hardware/camera2/impl/CameraDevice.java b/core/java/android/hardware/camera2/impl/CameraDevice.java
index ecc461e..40a7905 100644
--- a/core/java/android/hardware/camera2/impl/CameraDevice.java
+++ b/core/java/android/hardware/camera2/impl/CameraDevice.java
@@ -21,8 +21,10 @@
 import android.hardware.camera2.CameraAccessException;
 import android.hardware.camera2.CaptureRequest;
 import android.hardware.camera2.CaptureResult;
+import android.hardware.camera2.CaptureResultExtras;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
+import android.hardware.camera2.LongParcelable;
 import android.hardware.camera2.utils.CameraBinderDecorator;
 import android.hardware.camera2.utils.CameraRuntimeException;
 import android.os.Handler;
@@ -33,10 +35,12 @@
 import android.util.SparseArray;
 import android.view.Surface;
 
+import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.TreeSet;
 
 /**
  * HAL2.1+ implementation of CameraDevice. Use CameraManager#open to instantiate
@@ -69,10 +73,24 @@
 
     private final String mCameraId;
 
+    /**
+     * A list tracking request and its expected last frame.
+     * Updated when calling ICameraDeviceUser methods.
+     */
+    private final List<SimpleEntry</*frameNumber*/Long, /*requestId*/Integer>>
+            mFrameNumberRequestPairs = new ArrayList<SimpleEntry<Long, Integer>>();
+
+    /**
+     * An object tracking received frame numbers.
+     * Updated when receiving callbacks from ICameraDeviceCallbacks.
+     */
+    private final FrameNumberTracker mFrameNumberTracker = new FrameNumberTracker();
+
     // Runnables for all state transitions, except error, which needs the
     // error code argument
 
     private final Runnable mCallOnOpened = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onOpened(CameraDevice.this);
@@ -81,6 +99,7 @@
     };
 
     private final Runnable mCallOnUnconfigured = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onUnconfigured(CameraDevice.this);
@@ -89,6 +108,7 @@
     };
 
     private final Runnable mCallOnActive = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onActive(CameraDevice.this);
@@ -97,6 +117,7 @@
     };
 
     private final Runnable mCallOnBusy = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onBusy(CameraDevice.this);
@@ -105,12 +126,14 @@
     };
 
     private final Runnable mCallOnClosed = new Runnable() {
+        @Override
         public void run() {
             mDeviceListener.onClosed(CameraDevice.this);
         }
     };
 
     private final Runnable mCallOnIdle = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onIdle(CameraDevice.this);
@@ -119,6 +142,7 @@
     };
 
     private final Runnable mCallOnDisconnected = new Runnable() {
+        @Override
         public void run() {
             if (!CameraDevice.this.isClosed()) {
                 mDeviceListener.onDisconnected(CameraDevice.this);
@@ -133,7 +157,14 @@
         mCameraId = cameraId;
         mDeviceListener = listener;
         mDeviceHandler = handler;
-        TAG = String.format("CameraDevice-%s-JV", mCameraId);
+
+        final int MAX_TAG_LEN = 23;
+        String tag = String.format("CameraDevice-JV-%s", mCameraId);
+        if (tag.length() > MAX_TAG_LEN) {
+            tag = tag.substring(0, MAX_TAG_LEN);
+        }
+        TAG = tag;
+
         DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     }
 
@@ -249,22 +280,96 @@
     @Override
     public int capture(CaptureRequest request, CaptureListener listener, Handler handler)
             throws CameraAccessException {
-        return submitCaptureRequest(request, listener, handler, /*streaming*/false);
+        if (DEBUG) {
+            Log.d(TAG, "calling capture");
+        }
+        List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+        requestList.add(request);
+        return submitCaptureRequest(requestList, listener, handler, /*streaming*/false);
     }
 
     @Override
     public int captureBurst(List<CaptureRequest> requests, CaptureListener listener,
             Handler handler) throws CameraAccessException {
+        // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
         if (requests.isEmpty()) {
             Log.w(TAG, "Capture burst request list is empty, do nothing!");
             return -1;
         }
-        // TODO
-        throw new UnsupportedOperationException("Burst capture implemented yet");
-
+        return submitCaptureRequest(requests, listener, handler, /*streaming*/false);
     }
 
-    private int submitCaptureRequest(CaptureRequest request, CaptureListener listener,
+    /**
+     * This method checks lastFrameNumber returned from ICameraDeviceUser methods for
+     * starting and stopping repeating request and flushing.
+     *
+     * <p>If lastFrameNumber is NO_FRAMES_CAPTURED, it means that the request was never
+     * sent to HAL. Then onCaptureSequenceCompleted is immediately triggered.
+     * If lastFrameNumber is non-negative, then the requestId and lastFrameNumber pair
+     * is added to the list mFrameNumberRequestPairs.</p>
+     *
+     * @param requestId the request ID of the current repeating request.
+     *
+     * @param lastFrameNumber last frame number returned from binder.
+     */
+    private void checkEarlyTriggerSequenceComplete(
+            final int requestId, final long lastFrameNumber) {
+        // lastFrameNumber being equal to NO_FRAMES_CAPTURED means that the request
+        // was never sent to HAL. Should trigger onCaptureSequenceCompleted immediately.
+        if (lastFrameNumber == CaptureListener.NO_FRAMES_CAPTURED) {
+            final CaptureListenerHolder holder;
+            int index = mCaptureListenerMap.indexOfKey(requestId);
+            holder = (index >= 0) ? mCaptureListenerMap.valueAt(index) : null;
+            if (holder != null) {
+                mCaptureListenerMap.removeAt(index);
+                if (DEBUG) {
+                    Log.v(TAG, String.format(
+                            "remove holder for requestId %d, "
+                            + "because lastFrame is %d.",
+                            requestId, lastFrameNumber));
+                }
+            }
+
+            if (holder != null) {
+                if (DEBUG) {
+                    Log.v(TAG, "immediately trigger onCaptureSequenceCompleted because"
+                            + " request did not reach HAL");
+                }
+
+                Runnable resultDispatch = new Runnable() {
+                    @Override
+                    public void run() {
+                        if (!CameraDevice.this.isClosed()) {
+                            if (DEBUG) {
+                                Log.d(TAG, String.format(
+                                        "early trigger sequence complete for request %d",
+                                        requestId));
+                            }
+                            if (lastFrameNumber < Integer.MIN_VALUE
+                                    || lastFrameNumber > Integer.MAX_VALUE) {
+                                throw new AssertionError(lastFrameNumber + " cannot be cast to int");
+                            }
+                            holder.getListener().onCaptureSequenceCompleted(
+                                    CameraDevice.this,
+                                    requestId,
+                                    (int)lastFrameNumber);
+                        }
+                    }
+                };
+                holder.getHandler().post(resultDispatch);
+            } else {
+                Log.w(TAG, String.format(
+                        "did not register listener to request %d",
+                        requestId));
+            }
+        } else {
+            mFrameNumberRequestPairs.add(
+                    new SimpleEntry<Long, Integer>(lastFrameNumber,
+                            requestId));
+        }
+    }
+
+    private int submitCaptureRequest(List<CaptureRequest> requestList, CaptureListener listener,
             Handler handler, boolean repeating) throws CameraAccessException {
 
         // Need a valid handler, or current thread needs to have a looper, if
@@ -281,21 +386,39 @@
                 stopRepeating();
             }
 
+            LongParcelable lastFrameNumberRef = new LongParcelable();
             try {
-                requestId = mRemoteDevice.submitRequest(request, repeating);
+                requestId = mRemoteDevice.submitRequestList(requestList, repeating,
+                        /*out*/lastFrameNumberRef);
+                if (DEBUG) {
+                    Log.v(TAG, "last frame number " + lastFrameNumberRef.getNumber());
+                }
             } catch (CameraRuntimeException e) {
                 throw e.asChecked();
             } catch (RemoteException e) {
                 // impossible
                 return -1;
             }
+
             if (listener != null) {
-                mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener, request,
-                        handler, repeating));
+                mCaptureListenerMap.put(requestId, new CaptureListenerHolder(listener,
+                        requestList, handler, repeating));
+            } else {
+                if (DEBUG) {
+                    Log.d(TAG, "Listen for request " + requestId + " is null");
+                }
             }
 
+            long lastFrameNumber = lastFrameNumberRef.getNumber();
+
             if (repeating) {
+                if (mRepeatingRequestId != REQUEST_ID_NONE) {
+                    checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+                }
                 mRepeatingRequestId = requestId;
+            } else {
+                mFrameNumberRequestPairs.add(
+                        new SimpleEntry<Long, Integer>(lastFrameNumber, requestId));
             }
 
             if (mIdle) {
@@ -310,18 +433,20 @@
     @Override
     public int setRepeatingRequest(CaptureRequest request, CaptureListener listener,
             Handler handler) throws CameraAccessException {
-        return submitCaptureRequest(request, listener, handler, /*streaming*/true);
+        List<CaptureRequest> requestList = new ArrayList<CaptureRequest>();
+        requestList.add(request);
+        return submitCaptureRequest(requestList, listener, handler, /*streaming*/true);
     }
 
     @Override
     public int setRepeatingBurst(List<CaptureRequest> requests, CaptureListener listener,
             Handler handler) throws CameraAccessException {
+        // TODO: remove this. Throw IAE if the request is null or empty. Need to update API doc.
         if (requests.isEmpty()) {
             Log.w(TAG, "Set Repeating burst request list is empty, do nothing!");
             return -1;
         }
-        // TODO
-        throw new UnsupportedOperationException("Burst capture implemented yet");
+        return submitCaptureRequest(requests, listener, handler, /*streaming*/true);
     }
 
     @Override
@@ -340,7 +465,12 @@
                 }
 
                 try {
-                    mRemoteDevice.cancelRequest(requestId);
+                    LongParcelable lastFrameNumberRef = new LongParcelable();
+                    mRemoteDevice.cancelRequest(requestId, /*out*/lastFrameNumberRef);
+                    long lastFrameNumber = lastFrameNumberRef.getNumber();
+
+                    checkEarlyTriggerSequenceComplete(requestId, lastFrameNumber);
+
                 } catch (CameraRuntimeException e) {
                     throw e.asChecked();
                 } catch (RemoteException e) {
@@ -379,7 +509,13 @@
 
             mDeviceHandler.post(mCallOnBusy);
             try {
-                mRemoteDevice.flush();
+                LongParcelable lastFrameNumberRef = new LongParcelable();
+                mRemoteDevice.flush(/*out*/lastFrameNumberRef);
+                if (mRepeatingRequestId != REQUEST_ID_NONE) {
+                    long lastFrameNumber = lastFrameNumberRef.getNumber();
+                    checkEarlyTriggerSequenceComplete(mRepeatingRequestId, lastFrameNumber);
+                    mRepeatingRequestId = REQUEST_ID_NONE;
+                }
             } catch (CameraRuntimeException e) {
                 throw e.asChecked();
             } catch (RemoteException e) {
@@ -425,18 +561,18 @@
 
         private final boolean mRepeating;
         private final CaptureListener mListener;
-        private final CaptureRequest mRequest;
+        private final List<CaptureRequest> mRequestList;
         private final Handler mHandler;
 
-        CaptureListenerHolder(CaptureListener listener, CaptureRequest request, Handler handler,
-                boolean repeating) {
+        CaptureListenerHolder(CaptureListener listener, List<CaptureRequest> requestList,
+                Handler handler, boolean repeating) {
             if (listener == null || handler == null) {
                 throw new UnsupportedOperationException(
                     "Must have a valid handler and a valid listener");
             }
             mRepeating = repeating;
             mHandler = handler;
-            mRequest = request;
+            mRequestList = new ArrayList<CaptureRequest>(requestList);
             mListener = listener;
         }
 
@@ -448,8 +584,24 @@
             return mListener;
         }
 
+        public CaptureRequest getRequest(int subsequenceId) {
+            if (subsequenceId >= mRequestList.size()) {
+                throw new IllegalArgumentException(
+                        String.format(
+                                "Requested subsequenceId %d is larger than request list size %d.",
+                                subsequenceId, mRequestList.size()));
+            } else {
+                if (subsequenceId < 0) {
+                    throw new IllegalArgumentException(String.format(
+                            "Requested subsequenceId %d is negative", subsequenceId));
+                } else {
+                    return mRequestList.get(subsequenceId);
+                }
+            }
+        }
+
         public CaptureRequest getRequest() {
-            return mRequest;
+            return getRequest(0);
         }
 
         public Handler getHandler() {
@@ -458,6 +610,117 @@
 
     }
 
+    /**
+     * This class tracks the last frame number for submitted requests.
+     */
+    public class FrameNumberTracker {
+
+        private long mCompletedFrameNumber = -1;
+        private final TreeSet<Long> mFutureErrorSet = new TreeSet<Long>();
+
+        private void update() {
+            Iterator<Long> iter = mFutureErrorSet.iterator();
+            while (iter.hasNext()) {
+                long errorFrameNumber = iter.next();
+                if (errorFrameNumber == mCompletedFrameNumber + 1) {
+                    mCompletedFrameNumber++;
+                    iter.remove();
+                } else {
+                    break;
+                }
+            }
+        }
+
+        /**
+         * This function is called every time when a result or an error is received.
+         * @param frameNumber: the frame number corresponding to the result or error
+         * @param isError: true if it is an error, false if it is not an error
+         */
+        public void updateTracker(long frameNumber, boolean isError) {
+            if (isError) {
+                mFutureErrorSet.add(frameNumber);
+            } else {
+                /**
+                 * HAL cannot send an OnResultReceived for frame N unless it knows for
+                 * sure that all frames prior to N have either errored out or completed.
+                 * So if the current frame is not an error, then all previous frames
+                 * should have arrived. The following line checks whether this holds.
+                 */
+                if (frameNumber != mCompletedFrameNumber + 1) {
+                    throw new AssertionError(String.format(
+                            "result frame number %d comes out of order, should be %d + 1",
+                            frameNumber, mCompletedFrameNumber));
+                }
+                mCompletedFrameNumber++;
+            }
+            update();
+        }
+
+        public long getCompletedFrameNumber() {
+            return mCompletedFrameNumber;
+        }
+
+    }
+
+    private void checkAndFireSequenceComplete() {
+        long completedFrameNumber = mFrameNumberTracker.getCompletedFrameNumber();
+        Iterator<SimpleEntry<Long, Integer> > iter = mFrameNumberRequestPairs.iterator();
+        while (iter.hasNext()) {
+            final SimpleEntry<Long, Integer> frameNumberRequestPair = iter.next();
+            if (frameNumberRequestPair.getKey() <= completedFrameNumber) {
+
+                // remove request from mCaptureListenerMap
+                final int requestId = frameNumberRequestPair.getValue();
+                final CaptureListenerHolder holder;
+                synchronized (mLock) {
+                    int index = mCaptureListenerMap.indexOfKey(requestId);
+                    holder = (index >= 0) ? mCaptureListenerMap.valueAt(index)
+                            : null;
+                    if (holder != null) {
+                        mCaptureListenerMap.removeAt(index);
+                        if (DEBUG) {
+                            Log.v(TAG, String.format(
+                                    "remove holder for requestId %d, "
+                                    + "because lastFrame %d is <= %d",
+                                    requestId, frameNumberRequestPair.getKey(),
+                                    completedFrameNumber));
+                        }
+                    }
+                }
+                iter.remove();
+
+                // Call onCaptureSequenceCompleted
+                if (holder != null) {
+                    Runnable resultDispatch = new Runnable() {
+                        @Override
+                        public void run() {
+                            if (!CameraDevice.this.isClosed()){
+                                if (DEBUG) {
+                                    Log.d(TAG, String.format(
+                                            "fire sequence complete for request %d",
+                                            requestId));
+                                }
+
+                                long lastFrameNumber = frameNumberRequestPair.getKey();
+                                if (lastFrameNumber < Integer.MIN_VALUE
+                                        || lastFrameNumber > Integer.MAX_VALUE) {
+                                    throw new AssertionError(lastFrameNumber
+                                            + " cannot be cast to int");
+                                }
+                                holder.getListener().onCaptureSequenceCompleted(
+                                    CameraDevice.this,
+                                    requestId,
+                                    (int)lastFrameNumber);
+                            }
+                        }
+                    };
+                    holder.getHandler().post(resultDispatch);
+                }
+
+            }
+        }
+    }
+
     public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
 
         //
@@ -492,7 +755,7 @@
         }
 
         @Override
-        public void onCameraError(final int errorCode) {
+        public void onCameraError(final int errorCode, CaptureResultExtras resultExtras) {
             Runnable r = null;
             if (isClosed()) return;
 
@@ -507,6 +770,7 @@
                     case ERROR_CAMERA_DEVICE:
                     case ERROR_CAMERA_SERVICE:
                         r = new Runnable() {
+                            @Override
                             public void run() {
                                 if (!CameraDevice.this.isClosed()) {
                                     mDeviceListener.onError(CameraDevice.this, errorCode);
@@ -517,6 +781,14 @@
                 }
                 CameraDevice.this.mDeviceHandler.post(r);
             }
+
+            // Fire onCaptureSequenceCompleted
+            if (DEBUG) {
+                Log.v(TAG, String.format("got error frame %d", resultExtras.getFrameNumber()));
+            }
+            mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/true);
+            checkAndFireSequenceComplete();
+
         }
 
         @Override
@@ -535,7 +807,8 @@
         }
 
         @Override
-        public void onCaptureStarted(int requestId, final long timestamp) {
+        public void onCaptureStarted(final CaptureResultExtras resultExtras, final long timestamp) {
+            int requestId = resultExtras.getRequestId();
             if (DEBUG) {
                 Log.d(TAG, "Capture started for id " + requestId);
             }
@@ -555,11 +828,12 @@
             // Dispatch capture start notice
             holder.getHandler().post(
                 new Runnable() {
+                    @Override
                     public void run() {
                         if (!CameraDevice.this.isClosed()) {
                             holder.getListener().onCaptureStarted(
                                 CameraDevice.this,
-                                holder.getRequest(),
+                                holder.getRequest(resultExtras.getSubsequenceId()),
                                 timestamp);
                         }
                     }
@@ -567,56 +841,46 @@
         }
 
         @Override
-        public void onResultReceived(int requestId, CameraMetadataNative result)
-                throws RemoteException {
+        public void onResultReceived(CameraMetadataNative result,
+                CaptureResultExtras resultExtras) throws RemoteException {
+            int requestId = resultExtras.getRequestId();
             if (DEBUG) {
-                Log.d(TAG, "Received result for id " + requestId);
+                Log.v(TAG, "Received result frame " + resultExtras.getFrameNumber() + " for id "
+                        + requestId);
             }
             final CaptureListenerHolder holder;
+            synchronized (mLock) {
+                holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
+            }
 
             Boolean quirkPartial = result.get(CaptureResult.QUIRKS_PARTIAL_RESULT);
             boolean quirkIsPartialResult = (quirkPartial != null && quirkPartial);
 
-            synchronized (mLock) {
-                // TODO: move this whole map into this class to make it more testable,
-                //        exposing the methods necessary like subscribeToRequest, unsubscribe..
-                // TODO: make class static class
-
-                holder = CameraDevice.this.mCaptureListenerMap.get(requestId);
-
-                // Clean up listener once we no longer expect to see it.
-                if (holder != null && !holder.isRepeating() && !quirkIsPartialResult) {
-                    CameraDevice.this.mCaptureListenerMap.remove(requestId);
-                }
-
-                // TODO: add 'capture sequence completed' callback to the
-                // service, and clean up repeating requests there instead.
-
-                // If we received a result for a repeating request and have
-                // prior repeating requests queued for deletion, remove those
-                // requests from mCaptureListenerMap.
-                if (holder != null && holder.isRepeating() && !quirkIsPartialResult
-                        && mRepeatingRequestIdDeletedList.size() > 0) {
-                    Iterator<Integer> iter = mRepeatingRequestIdDeletedList.iterator();
-                    while (iter.hasNext()) {
-                        int deletedRequestId = iter.next();
-                        if (deletedRequestId < requestId) {
-                            CameraDevice.this.mCaptureListenerMap.remove(deletedRequestId);
-                            iter.remove();
-                        }
-                    }
-                }
-
+            // Update tracker (increment counter) when it's not a partial result.
+            if (!quirkIsPartialResult) {
+                mFrameNumberTracker.updateTracker(resultExtras.getFrameNumber(), /*error*/false);
             }
 
             // Check if we have a listener for this
             if (holder == null) {
+                if (DEBUG) {
+                    Log.d(TAG,
+                            "holder is null, early return at frame "
+                                    + resultExtras.getFrameNumber());
+                }
                 return;
             }
 
-            if (isClosed()) return;
+            if (isClosed()) {
+                if (DEBUG) {
+                    Log.d(TAG,
+                            "camera is closed, early return at frame "
+                                    + resultExtras.getFrameNumber());
+                }
+                return;
+            }
 
-            final CaptureRequest request = holder.getRequest();
+            final CaptureRequest request = holder.getRequest(resultExtras.getSubsequenceId());
             final CaptureResult resultAsCapture = new CaptureResult(result, request, requestId);
 
             Runnable resultDispatch = null;
@@ -651,6 +915,11 @@
             }
 
             holder.getHandler().post(resultDispatch);
+
+            // Fire onCaptureSequenceCompleted
+            if (!quirkIsPartialResult) {
+                checkAndFireSequenceComplete();
+            }
         }
 
     }
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index a517bc5..79673b3 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -437,6 +437,14 @@
      * The behavior of the virtual display depends on the flags that are provided
      * to this method.  By default, virtual displays are created to be private,
      * non-presentation and unsecure.  Permissions may be required to use certain flags.
+     * </p><p>
+     * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may
+     * be attached or detached dynamically using {@link VirtualDisplay#setSurface}.
+     * Previously, the surface had to be non-null when {@link #createVirtualDisplay}
+     * was called and could not be changed for the lifetime of the display.
+     * </p><p>
+     * Detaching the surface that backs a virtual display has a similar effect to
+     * turning off the screen.
      * </p>
      *
      * @param name The name of the virtual display, must be non-empty.
@@ -444,7 +452,7 @@
      * @param height The height of the virtual display in pixels, must be greater than 0.
      * @param densityDpi The density of the virtual display in dpi, must be greater than 0.
      * @param surface The surface to which the content of the virtual display should
-     * be rendered, must be non-null.
+     * be rendered, or null if there is none initially.
      * @param flags A combination of virtual display flags:
      * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION},
      * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, or {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}.
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 3417430..a8d55e8 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -377,9 +377,6 @@
             throw new IllegalArgumentException("width, height, and densityDpi must be "
                     + "greater than 0");
         }
-        if (surface == null) {
-            throw new IllegalArgumentException("surface must not be null");
-        }
 
         Binder token = new Binder();
         int displayId;
@@ -404,7 +401,15 @@
             }
             return null;
         }
-        return new VirtualDisplay(this, display, token);
+        return new VirtualDisplay(this, display, token, surface);
+    }
+
+    public void setVirtualDisplaySurface(IBinder token, Surface surface) {
+        try {
+            mDm.setVirtualDisplaySurface(token, surface);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed to set virtual display surface.", ex);
+        }
     }
 
     public void releaseVirtualDisplay(IBinder token) {
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 03fa1d5..cec90cd 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -58,16 +58,6 @@
     public abstract boolean isProximitySensorAvailable();
 
     /**
-     * Called by the power manager to blank all displays.
-     */
-    public abstract void blankAllDisplaysFromPowerManager();
-
-    /**
-     * Called by the power manager to unblank all displays.
-     */
-    public abstract void unblankAllDisplaysFromPowerManager();
-
-    /**
      * Returns information about the specified logical display.
      *
      * @param displayId The logical display id.
@@ -254,12 +244,10 @@
         void onStateChanged();
         void onProximityPositive();
         void onProximityNegative();
+        void onDisplayStateChange(int state); // one of the Display state constants
 
         void acquireSuspendBlocker();
         void releaseSuspendBlocker();
-
-        void blankAllDisplays();
-        void unblankAllDisplays();
     }
 
     /**
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 68eb13f..23c58c8 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -63,5 +63,8 @@
             String name, int width, int height, int densityDpi, in Surface surface, int flags);
 
     // No permissions required but must be same Uid as the creator.
+    void setVirtualDisplaySurface(in IBinder token, in Surface surface);
+
+    // No permissions required but must be same Uid as the creator.
     void releaseVirtualDisplay(in IBinder token);
 }
diff --git a/core/java/android/hardware/display/VirtualDisplay.java b/core/java/android/hardware/display/VirtualDisplay.java
index 01e5bac..691d6a0 100644
--- a/core/java/android/hardware/display/VirtualDisplay.java
+++ b/core/java/android/hardware/display/VirtualDisplay.java
@@ -17,15 +17,18 @@
 
 import android.os.IBinder;
 import android.view.Display;
+import android.view.Surface;
 
 /**
  * Represents a virtual display. The content of a virtual display is rendered to a
  * {@link android.view.Surface} that you must provide to {@link DisplayManager#createVirtualDisplay
  * createVirtualDisplay()}.
- * <p>Because a virtual display renders to a surface provided by the application, it will be
+ * <p>
+ * Because a virtual display renders to a surface provided by the application, it will be
  * released automatically when the process terminates and all remaining windows on it will
- * be forcibly removed. However, you should also explicitly call {@link #release} when you're
- * done with it.
+ * be forcibly removed.  However, you should also explicitly call {@link #release} when
+ * you're done with it.
+ * </p>
  *
  * @see DisplayManager#createVirtualDisplay
  */
@@ -33,11 +36,14 @@
     private final DisplayManagerGlobal mGlobal;
     private final Display mDisplay;
     private IBinder mToken;
+    private Surface mSurface;
 
-    VirtualDisplay(DisplayManagerGlobal global, Display display, IBinder token) {
+    VirtualDisplay(DisplayManagerGlobal global, Display display, IBinder token,
+            Surface surface) {
         mGlobal = global;
         mDisplay = display;
         mToken = token;
+        mSurface = surface;
     }
 
     /**
@@ -48,6 +54,32 @@
     }
 
     /**
+     * Gets the surface that backs the virtual display.
+     */
+    public Surface getSurface() {
+        return mSurface;
+    }
+
+    /**
+     * Sets the surface that backs the virtual display.
+     * <p>
+     * Detaching the surface that backs a virtual display has a similar effect to
+     * turning off the screen.
+     * </p><p>
+     * It is still the caller's responsibility to destroy the surface after it has
+     * been detached.
+     * </p>
+     *
+     * @param surface The surface to set, or null to detach the surface from the virtual display.
+     */
+    public void setSurface(Surface surface) {
+        if (mSurface != surface) {
+            mGlobal.setVirtualDisplaySurface(mToken, surface);
+            mSurface = surface;
+        }
+    }
+
+    /**
      * Releases the virtual display and destroys its underlying surface.
      * <p>
      * All remaining windows on the virtual display will be forcibly removed
@@ -63,6 +95,7 @@
 
     @Override
     public String toString() {
-        return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken + "}";
+        return "VirtualDisplay{display=" + mDisplay + ", token=" + mToken
+                + ", surface=" + mSurface + "}";
     }
 }
diff --git a/core/java/android/hardware/hdmi/HdmiCecClient.java b/core/java/android/hardware/hdmi/HdmiCecClient.java
index 1f382e6..cd86cd8 100644
--- a/core/java/android/hardware/hdmi/HdmiCecClient.java
+++ b/core/java/android/hardware/hdmi/HdmiCecClient.java
@@ -88,7 +88,7 @@
     }
 
     /**
-     * Send &lt;TextViewOn&gt; message.
+     * Send &lt;Text View On&gt; message.
      */
     public void sendTextViewOn() {
         try {
@@ -99,7 +99,7 @@
     }
 
     /**
-     * Send &lt;ImageViewOn&gt; message.
+     * Send &lt;Image View On&gt; message.
      */
     public void sendImageViewOn() {
         try {
@@ -110,6 +110,20 @@
     }
 
     /**
+     * Send &lt;Give Device Power Status&gt; message.
+     *
+     * @param address logical address of the device to send the message to, such as
+     *        {@link HdmiCec#ADDR_TV}.
+     */
+    public void sendGiveDevicePowerStatus(int address) {
+        try {
+            mService.sendGiveDevicePowerStatus(mBinder, address);
+        } catch (RemoteException e) {
+            Log.e(TAG, "sendGiveDevicePowerStatus threw exception ", e);
+        }
+    }
+
+    /**
      * Returns true if the TV or attached display is powered on.
      * <p>
      * The result of this method is only meaningful on playback devices (where the device
diff --git a/core/java/android/hardware/hdmi/IHdmiCecService.aidl b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
index b5df131..ecdd345 100644
--- a/core/java/android/hardware/hdmi/IHdmiCecService.aidl
+++ b/core/java/android/hardware/hdmi/IHdmiCecService.aidl
@@ -33,6 +33,7 @@
     void sendInactiveSource(IBinder b);
     void sendImageViewOn(IBinder b);
     void sendTextViewOn(IBinder b);
+    void sendGiveDevicePowerStatus(IBinder b, int address);
     boolean isTvOn(IBinder b);
     void sendMessage(IBinder b, in HdmiCecMessage message);
 }
diff --git a/core/java/android/hardware/input/InputManager.java b/core/java/android/hardware/input/InputManager.java
index 0c0dfe9..b5efa8e 100644
--- a/core/java/android/hardware/input/InputManager.java
+++ b/core/java/android/hardware/input/InputManager.java
@@ -857,7 +857,7 @@
          * @hide
          */
         @Override
-        public void vibrate(int owningUid, String owningPackage, long milliseconds,
+        public void vibrate(int uid, String opPkg, long milliseconds,
                 int streamHint) {
             vibrate(new long[] { 0, milliseconds}, -1);
         }
@@ -866,7 +866,7 @@
          * @hide
          */
         @Override
-        public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+        public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
                 int streamHint) {
             if (repeat >= pattern.length) {
                 throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/hardware/input/InputManagerInternal.java b/core/java/android/hardware/input/InputManagerInternal.java
index 8be94d0..6a392dd 100644
--- a/core/java/android/hardware/input/InputManagerInternal.java
+++ b/core/java/android/hardware/input/InputManagerInternal.java
@@ -25,12 +25,18 @@
  * @hide Only for use within the system server.
  */
 public abstract class InputManagerInternal {
+    public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
+
     /**
-     * Sets information about the displays as needed by the input system.
-     * The input system should copy this information if required.
+     * Called by the display manager to set information about the displays as needed
+     * by the input system.  The input system must copy this information to retain it.
      */
     public abstract void setDisplayViewports(DisplayViewport defaultViewport,
             DisplayViewport externalTouchViewport);
 
-    public abstract boolean injectInputEvent(InputEvent event, int displayId, int mode);
+    /**
+     * Called by the power manager to tell the input manager whether it should start
+     * watching for wake events.
+     */
+    public abstract void setInteractive(boolean interactive);
 }
diff --git a/core/java/android/hardware/location/GeofenceHardware.java b/core/java/android/hardware/location/GeofenceHardware.java
index 21de9f5..4c074e9 100644
--- a/core/java/android/hardware/location/GeofenceHardware.java
+++ b/core/java/android/hardware/location/GeofenceHardware.java
@@ -79,7 +79,7 @@
      */
     public static final int MONITOR_UNSUPPORTED = 2;
 
-    // The following constants need to match geofence flags in gps.h
+    // The following constants need to match geofence flags in gps.h and fused_location.h
     /**
      * The constant to indicate that the user has entered the geofence.
      */
@@ -92,7 +92,7 @@
 
     /**
      * The constant to indicate that the user is uncertain with respect to a
-     * geofence.                                                  nn
+     * geofence.
      */
     public static final int GEOFENCE_UNCERTAIN = 1<<2L;
 
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index c51d1a7..505ef9c 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -255,7 +255,9 @@
     public static final int CURSOR_ANCHOR_MONITOR_MODE_NONE = 0x0;
 
     /**
-     * The IME expects that {@link #onUpdateCursor(Rect)} is called back.
+     * Passing this flag into a call to {@link #setCursorAnchorMonitorMode(int)} will result in
+     * the cursor rectangle being provided in screen coordinates to subsequent
+     * {@link #onUpdateCursor(Rect)} callbacks.
      */
     public static final int CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT = 0x1;
 
@@ -1703,9 +1705,11 @@
     }
 
     /**
-     * Called when the application has reported a new location of its text
-     * cursor.  This is only called if explicitly requested by the input method.
-     * The default implementation does nothing.
+     * Called when the application has reported a new location of its text cursor.  This is only
+     * called if explicitly requested by the input method.  The default implementation does nothing.
+     * @param newCursor The new cursor position, in screen coordinates if the input method calls
+     * {@link #setCursorAnchorMonitorMode} with {@link #CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT}.
+     * Otherwise, this is in local coordinates.
      */
     public void onUpdateCursor(Rect newCursor) {
         // Intentionally empty
diff --git a/core/java/android/net/INetworkScoreService.aidl b/core/java/android/net/INetworkScoreService.aidl
new file mode 100644
index 0000000..a72d9a0
--- /dev/null
+++ b/core/java/android/net/INetworkScoreService.aidl
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import android.net.ScoredNetwork;
+
+/**
+ * A service for updating network scores from a network scorer application.
+ * @hide
+ */
+interface INetworkScoreService
+{
+    /**
+     * Update scores.
+     * @return whether the update was successful.
+     * @throws SecurityException if the caller is not the current active scorer.
+     */
+    boolean updateScores(in ScoredNetwork[] networks);
+
+    /**
+     * Clear all scores.
+     * @return whether the clear was successful.
+     * @throws SecurityException if the caller is neither the current active scorer nor the scorer
+     * manager.
+     */
+    boolean clearScores();
+
+    /**
+     * Set the active scorer and clear existing scores.
+     * @param packageName the package name of the new scorer to use.
+     * @return true if the operation succeeded, or false if the new package is not a valid scorer.
+     * @throws SecurityException if the caller is not the scorer manager.
+     */
+    boolean setActiveScorer(in String packageName);
+}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 22543e3..a725bec 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -24,13 +24,13 @@
 import java.net.InterfaceAddress;
 import java.net.UnknownHostException;
 
-import static libcore.io.OsConstants.IFA_F_DADFAILED;
-import static libcore.io.OsConstants.IFA_F_DEPRECATED;
-import static libcore.io.OsConstants.IFA_F_TENTATIVE;
-import static libcore.io.OsConstants.RT_SCOPE_HOST;
-import static libcore.io.OsConstants.RT_SCOPE_LINK;
-import static libcore.io.OsConstants.RT_SCOPE_SITE;
-import static libcore.io.OsConstants.RT_SCOPE_UNIVERSE;
+import static android.system.OsConstants.IFA_F_DADFAILED;
+import static android.system.OsConstants.IFA_F_DEPRECATED;
+import static android.system.OsConstants.IFA_F_TENTATIVE;
+import static android.system.OsConstants.RT_SCOPE_HOST;
+import static android.system.OsConstants.RT_SCOPE_LINK;
+import static android.system.OsConstants.RT_SCOPE_SITE;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
 
 /**
  * Identifies an IP address on a network link.
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index 119e533..643e8c2 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -22,9 +22,9 @@
 import java.io.FileDescriptor;
 import java.net.SocketOptions;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.OsConstants;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 
 /**
  * Socket implementation used for android.net.LocalSocket and
@@ -248,7 +248,7 @@
                     throw new IllegalStateException("unknown sockType");
             }
             try {
-                fd = Libcore.os.socket(OsConstants.AF_UNIX, osType, 0);
+                fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
                 mFdCreatedInternally = true;
             } catch (ErrnoException e) {
                 e.rethrowAsIOException();
@@ -268,7 +268,7 @@
                 return;
             }
             try {
-                Libcore.os.close(fd);
+                Os.close(fd);
             } catch (ErrnoException e) {
                 e.rethrowAsIOException();
             }
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index a470e88..30b61c5 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -54,7 +54,7 @@
 public class MobileDataStateTracker extends BaseNetworkStateTracker {
 
     private static final String TAG = "MobileDataStateTracker";
-    private static final boolean DBG = true;
+    private static final boolean DBG = false;
     private static final boolean VDBG = false;
 
     private PhoneConstants.DataState mMobileDataState;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/net/NetworkKey.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/net/NetworkKey.aidl
index 0377123..637075f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/net/NetworkKey.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.net;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable NetworkKey;
diff --git a/core/java/android/net/NetworkKey.java b/core/java/android/net/NetworkKey.java
new file mode 100644
index 0000000..bc19658
--- /dev/null
+++ b/core/java/android/net/NetworkKey.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Information which identifies a specific network.
+ *
+ * @hide
+ */
+// NOTE: Ideally, we would abstract away the details of what identifies a network of a specific
+// type, so that all networks appear the same and can be scored without concern to the network type
+// itself. However, because no such cross-type identifier currently exists in the Android framework,
+// and because systems might obtain information about networks from sources other than Android
+// devices, we need to provide identifying details about each specific network type (wifi, cell,
+// etc.) so that clients can pull out these details depending on the type of network.
+public class NetworkKey implements Parcelable {
+
+    /** A wifi network, for which {@link #wifiKey} will be populated. */
+    public static final int TYPE_WIFI = 1;
+
+    /**
+     * The type of this network.
+     * @see #TYPE_WIFI
+     */
+    public final int type;
+
+    /**
+     * Information identifying a Wi-Fi network. Only set when {@link #type} equals
+     * {@link #TYPE_WIFI}.
+     */
+    public final WifiKey wifiKey;
+
+    /**
+     * Construct a new {@link NetworkKey} for a Wi-Fi network.
+     * @param wifiKey the {@link WifiKey} identifying this Wi-Fi network.
+     */
+    public NetworkKey(WifiKey wifiKey) {
+        this.type = TYPE_WIFI;
+        this.wifiKey = wifiKey;
+    }
+
+    private NetworkKey(Parcel in) {
+        type = in.readInt();
+        switch (type) {
+            case TYPE_WIFI:
+                wifiKey = WifiKey.CREATOR.createFromParcel(in);
+                break;
+            default:
+                throw new IllegalArgumentException("Parcel has unknown type: " + type);
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(type);
+        switch (type) {
+            case TYPE_WIFI:
+                wifiKey.writeToParcel(out, flags);
+                break;
+            default:
+                throw new IllegalStateException("NetworkKey has unknown type " + type);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        NetworkKey that = (NetworkKey) o;
+
+        return type == that.type && Objects.equals(wifiKey, that.wifiKey);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, wifiKey);
+    }
+
+    @Override
+    public String toString() {
+        switch (type) {
+            case TYPE_WIFI:
+                return wifiKey.toString();
+            default:
+                // Don't throw an exception here in case someone is logging this object in a catch
+                // block for debugging purposes.
+                return "InvalidKey";
+        }
+    }
+
+    public static final Parcelable.Creator<NetworkKey> CREATOR =
+            new Parcelable.Creator<NetworkKey>() {
+                @Override
+                public NetworkKey createFromParcel(Parcel in) {
+                    return new NetworkKey(in);
+                }
+
+                @Override
+                public NetworkKey[] newArray(int size) {
+                    return new NetworkKey[size];
+                }
+            };
+}
diff --git a/core/java/android/net/NetworkScoreManager.java b/core/java/android/net/NetworkScoreManager.java
new file mode 100644
index 0000000..6dd56d9
--- /dev/null
+++ b/core/java/android/net/NetworkScoreManager.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
+/**
+ * Class that manages communication between network subsystems and a network scorer.
+ *
+ * <p>You can get an instance of this class by calling
+ * {@link android.content.Context#getSystemService(String)}:
+ *
+ * <pre>NetworkScoreManager manager =
+ *     (NetworkScoreManager) getSystemService(Context.NETWORK_SCORE_SERVICE)</pre>
+ *
+ * <p>A network scorer is any application which:
+ * <ul>
+ * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+ * <li>Includes a receiver for {@link #ACTION_SCORE_NETWORKS} guarded by the
+ *     {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission which scores networks
+ *     and (eventually) calls {@link #updateScores} with the results.
+ * </ul>
+ *
+ * <p>The system keeps track of an active scorer application; at any time, only this application
+ * will receive {@link #ACTION_SCORE_NETWORKS} broadcasts and will be permitted to call
+ * {@link #updateScores}. Applications may determine the current active scorer with
+ * {@link #getActiveScorerPackage()} and request to change the active scorer by sending an
+ * {@link #ACTION_CHANGE_ACTIVE} broadcast with another scorer.
+ *
+ * @hide
+ */
+public class NetworkScoreManager {
+    /**
+     * Activity action: ask the user to change the active network scorer. This will show a dialog
+     * that asks the user whether they want to replace the current active scorer with the one
+     * specified in {@link #EXTRA_PACKAGE_NAME}. The activity will finish with RESULT_OK if the
+     * active scorer was changed or RESULT_CANCELED if it failed for any reason.
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CHANGE_ACTIVE = "android.net.scoring.CHANGE_ACTIVE";
+
+    /**
+     * Extra used with {@link #ACTION_CHANGE_ACTIVE} to specify the new scorer package. Set with
+     * {@link android.content.Intent#putExtra(String, String)}.
+     */
+    public static final String EXTRA_PACKAGE_NAME = "packageName";
+
+    /**
+     * Broadcast action: new network scores are being requested. This intent will only be delivered
+     * to the current active scorer app. That app is responsible for scoring the networks and
+     * calling {@link #updateScores} when complete. The networks to score are specified in
+     * {@link #EXTRA_NETWORKS_TO_SCORE}, and will generally consist of all networks which have been
+     * configured by the user as well as any open networks.
+     *
+     * <p class="note">This is a protected intent that can only be sent by the system.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String ACTION_SCORE_NETWORKS = "android.net.scoring.SCORE_NETWORKS";
+
+    /**
+     * Extra used with {@link #ACTION_SCORE_NETWORKS} to specify the networks to be scored, as an
+     * array of {@link NetworkKey}s. Can be obtained with
+     * {@link android.content.Intent#getParcelableArrayExtra(String)}}.
+     */
+    public static final String EXTRA_NETWORKS_TO_SCORE = "networksToScore";
+
+    private final Context mContext;
+    private final INetworkScoreService mService;
+
+    /** @hide */
+    public NetworkScoreManager(Context context) {
+        mContext = context;
+        IBinder iBinder = ServiceManager.getService(Context.NETWORK_SCORE_SERVICE);
+        mService = INetworkScoreService.Stub.asInterface(iBinder);
+    }
+
+    /**
+     * Obtain the package name of the current active network scorer.
+     *
+     * <p>At any time, only one scorer application will receive {@link #ACTION_SCORE_NETWORKS}
+     * broadcasts and be allowed to call {@link #updateScores}. Applications may use this method to
+     * determine the current scorer and offer the user the ability to select a different scorer via
+     * the {@link #ACTION_CHANGE_ACTIVE} intent.
+     * @return the full package name of the current active scorer, or null if there is no active
+     *     scorer.
+     */
+    public String getActiveScorerPackage() {
+        return NetworkScorerAppManager.getActiveScorer(mContext);
+    }
+
+    /**
+     * Update network scores.
+     *
+     * <p>This may be called at any time to re-score active networks. Scores will generally be
+     * updated quickly, but if this method is called too frequently, the scores may be held and
+     * applied at a later time.
+     *
+     * @param networks the networks which have been scored by the scorer.
+     * @return whether the update was successful.
+     * @throws SecurityException if the caller is not the active scorer.
+     */
+    public boolean updateScores(ScoredNetwork[] networks) throws SecurityException {
+        try {
+            return mService.updateScores(networks);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Clear network scores.
+     *
+     * <p>Should be called when all scores need to be invalidated, i.e. because the scoring
+     * algorithm has changed and old scores can no longer be compared to future scores.
+     *
+     * <p>Note that scores will be cleared automatically when the active scorer changes, as scores
+     * from one scorer cannot be compared to those from another scorer.
+     *
+     * @return whether the clear was successful.
+     * @throws SecurityException if the caller is not the active scorer or privileged.
+     */
+    public boolean clearScores() throws SecurityException {
+        try {
+            return mService.clearScores();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Set the active scorer to a new package and clear existing scores.
+     *
+     * @return true if the operation succeeded, or false if the new package is not a valid scorer.
+     * @throws SecurityException if the caller does not hold the
+     *      {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission indicating that
+     *      it can manage scorer applications.
+     * @hide
+     */
+    public boolean setActiveScorer(String packageName) throws SecurityException {
+        try {
+            return mService.setActiveScorer(packageName);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/net/NetworkScorerAppManager.java b/core/java/android/net/NetworkScorerAppManager.java
new file mode 100644
index 0000000..3660e7a
--- /dev/null
+++ b/core/java/android/net/NetworkScorerAppManager.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.Manifest.permission;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Internal class for managing the primary network scorer application.
+ *
+ * @hide
+ */
+public final class NetworkScorerAppManager {
+    private static final String TAG = "NetworkScorerAppManager";
+
+    private static final Intent SCORE_INTENT =
+            new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
+
+    /** This class cannot be instantiated. */
+    private NetworkScorerAppManager() {}
+
+    /**
+     * Returns the list of available scorer app package names.
+     *
+     * <p>A network scorer is any application which:
+     * <ul>
+     * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+     * <li>Includes a receiver for {@link NetworkScoreManager#ACTION_SCORE_NETWORKS} guarded by the
+     *     {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+     * </ul>
+     *
+     * @return the list of scorers, or the empty list if there are no valid scorers.
+     */
+    public static Collection<String> getAllValidScorers(Context context) {
+        List<String> scorers = new ArrayList<>();
+
+        PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> receivers = pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */);
+        for (ResolveInfo receiver : receivers) {
+            // This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo
+            final ActivityInfo receiverInfo = receiver.activityInfo;
+            if (receiverInfo == null) {
+                // Should never happen with queryBroadcastReceivers, but invalid nonetheless.
+                continue;
+            }
+            if (!permission.BROADCAST_SCORE_NETWORKS.equals(receiverInfo.permission)) {
+                // Receiver doesn't require the BROADCAST_SCORE_NETWORKS permission, which means
+                // anyone could trigger network scoring and flood the framework with score requests.
+                continue;
+            }
+            if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) !=
+                    PackageManager.PERMISSION_GRANTED) {
+                // Application doesn't hold the SCORE_NETWORKS permission, so the user never
+                // approved it as a network scorer.
+                continue;
+            }
+            scorers.add(receiverInfo.packageName);
+        }
+
+        return scorers;
+    }
+
+    /**
+     * Get the application package name to use for scoring networks.
+     *
+     * @return the scorer package or null if scoring is disabled (including if no scorer was ever
+     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
+     *     it was disabled or uninstalled).
+     */
+    public static String getActiveScorer(Context context) {
+        String scorerPackage = Settings.Global.getString(context.getContentResolver(),
+                Global.NETWORK_SCORER_APP);
+        if (isPackageValidScorer(context, scorerPackage)) {
+            return scorerPackage;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Set the specified package as the default scorer application.
+     *
+     * <p>The caller must have permission to write to {@link Settings.Global}.
+     *
+     * @param context the context of the calling application
+     * @param packageName the packageName of the new scorer to use. If null, scoring will be
+     *     disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
+     * @return true if the scorer was changed, or false if the package is not a valid scorer.
+     */
+    public static boolean setActiveScorer(Context context, String packageName) {
+        String oldPackageName = Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.NETWORK_SCORER_APP);
+        if (TextUtils.equals(oldPackageName, packageName)) {
+            // No change.
+            return true;
+        }
+
+        Log.i(TAG, "Changing network scorer from " + oldPackageName + " to " + packageName);
+
+        if (packageName == null) {
+            Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP,
+                    null);
+            return true;
+        } else {
+            // We only make the change if the new package is valid.
+            if (isPackageValidScorer(context, packageName)) {
+                Settings.Global.putString(context.getContentResolver(),
+                        Settings.Global.NETWORK_SCORER_APP, packageName);
+                return true;
+            } else {
+                Log.w(TAG, "Requested network scorer is not valid: " + packageName);
+                return false;
+            }
+        }
+    }
+
+    /** Determine whether the application with the given UID is the enabled scorer. */
+    public static boolean isCallerActiveScorer(Context context, int callingUid) {
+        String defaultApp = getActiveScorer(context);
+        if (defaultApp == null) {
+            return false;
+        }
+        AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        try {
+            appOpsMgr.checkPackage(callingUid, defaultApp);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    /** Returns true if the given package is a valid scorer. */
+    public static boolean isPackageValidScorer(Context context, String packageName) {
+        Collection<String> applications = getAllValidScorers(context);
+        return packageName != null && applications.contains(packageName);
+    }
+}
diff --git a/core/java/android/net/RssiCurve.java b/core/java/android/net/RssiCurve.java
new file mode 100644
index 0000000..33e81c2
--- /dev/null
+++ b/core/java/android/net/RssiCurve.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Arrays;
+import java.util.Objects;
+
+/**
+ * A curve defining the network score over a range of RSSI values.
+ *
+ * <p>For each RSSI bucket, the score may be any byte. Scores have no absolute meaning and are only
+ * considered relative to other scores assigned by the same scorer. Networks with no score are all
+ * considered equivalent and ranked below any network with a score.
+ *
+ * <p>For example, consider a curve starting at -110 dBm with a bucket width of 10 and the
+ * following buckets: {@code [-20, -10, 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]}.
+ * This represents a linear curve between -110 dBm and 30 dBm. It scores progressively higher at
+ * stronger signal strengths.
+ *
+ * <p>A network can be assigned a fixed score independent of RSSI by setting
+ * {@link #rssiBuckets} to a one-byte array whose element is the fixed score. {@link #start}
+ * should be set to the lowest RSSI value at which this fixed score should apply, and
+ * {@link #bucketWidth} should be set such that {@code start + bucketWidth} is equal to the
+ * highest RSSI value at which this fixed score should apply.
+ *
+ * <p>Note that RSSI values below -110 dBm or above 30 dBm are unlikely to cause any difference
+ * in connectivity behavior from those endpoints. That is, the connectivity framework will treat
+ * a network with a -120 dBm signal exactly as it would treat one with a -110 dBm signal.
+ * Therefore, graphs which specify scores outside this range may be truncated to this range by
+ * the system.
+ *
+ * @see ScoredNetwork
+ * @hide
+ */
+public class RssiCurve implements Parcelable {
+
+    /** The starting dBm of the curve. */
+    public final int start;
+
+    /** The width of each RSSI bucket, in dBm. */
+    public final int bucketWidth;
+
+    /** The score for each RSSI bucket. */
+    public final byte[] rssiBuckets;
+
+    /**
+     * Construct a new {@link RssiCurve}.
+     *
+     * @param start the starting dBm of the curve.
+     * @param bucketWidth the width of each RSSI bucket, in dBm.
+     * @param rssiBuckets the score for each RSSI bucket.
+     */
+    public RssiCurve(int start, int bucketWidth, byte[] rssiBuckets) {
+        this.start = start;
+        this.bucketWidth = bucketWidth;
+        if (rssiBuckets == null || rssiBuckets.length == 0) {
+            throw new IllegalArgumentException("rssiBuckets must be at least one element large.");
+        }
+        this.rssiBuckets = rssiBuckets;
+    }
+
+    private RssiCurve(Parcel in) {
+        start = in.readInt();
+        bucketWidth = in.readInt();
+        int bucketCount = in.readInt();
+        rssiBuckets = new byte[bucketCount];
+        in.readByteArray(rssiBuckets);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(start);
+        out.writeInt(bucketWidth);
+        out.writeInt(rssiBuckets.length);
+        out.writeByteArray(rssiBuckets);
+    }
+
+    /**
+     * Determine if two RSSI curves are defined in the same way.
+     *
+     * <p>Note that two curves can be equivalent but defined differently, e.g. if one bucket in one
+     * curve is split into two buckets in another. For the purpose of this method, these curves are
+     * not considered equal to each other.
+     */
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        RssiCurve rssiCurve = (RssiCurve) o;
+
+        return start == rssiCurve.start &&
+                bucketWidth == rssiCurve.bucketWidth &&
+                Arrays.equals(rssiBuckets, rssiCurve.rssiBuckets);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(start, bucketWidth, rssiBuckets);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("RssiCurve[start=")
+                .append(start)
+                .append(",bucketWidth=")
+                .append(bucketWidth);
+
+        sb.append(",buckets=");
+        for (int i = 0; i < rssiBuckets.length; i++) {
+            sb.append(rssiBuckets[i]);
+            if (i < rssiBuckets.length - 1) {
+                sb.append(",");
+            }
+        }
+        sb.append("]");
+
+        return sb.toString();
+    }
+
+    public static final Creator<RssiCurve> CREATOR =
+            new Creator<RssiCurve>() {
+                @Override
+                public RssiCurve createFromParcel(Parcel in) {
+                    return new RssiCurve(in);
+                }
+
+                @Override
+                public RssiCurve[] newArray(int size) {
+                    return new RssiCurve[size];
+                }
+            };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/net/ScoredNetwork.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/net/ScoredNetwork.aidl
index 0377123..f83db11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/net/ScoredNetwork.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.net;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable ScoredNetwork;
diff --git a/core/java/android/net/ScoredNetwork.java b/core/java/android/net/ScoredNetwork.java
new file mode 100644
index 0000000..7902313
--- /dev/null
+++ b/core/java/android/net/ScoredNetwork.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * A network identifier along with a score for the quality of that network.
+ *
+ * @hide
+ */
+public class ScoredNetwork implements Parcelable {
+
+    /** A {@link NetworkKey} uniquely identifying this network. */
+    public final NetworkKey networkKey;
+
+    /**
+     * The {@link RssiCurve} representing the scores for this network based on the RSSI.
+     *
+     * <p>This field is optional and may be set to null to indicate that no score is available for
+     * this network at this time. Such networks, along with networks for which the scorer has not
+     * responded, are always prioritized below scored networks, regardless of the score.
+     */
+    public final RssiCurve rssiCurve;
+
+    /**
+     * Construct a new {@link ScoredNetwork}.
+     *
+     * @param networkKey the {@link NetworkKey} uniquely identifying this network.
+     * @param rssiCurve the {@link RssiCurve} representing the scores for this network based on the
+     *     RSSI. This field is optional, and may be skipped to represent a network which the scorer
+     *     has opted not to score at this time. Passing a null value here is strongly preferred to
+     *     not returning any {@link ScoredNetwork} for a given {@link NetworkKey} because it
+     *     indicates to the system not to request scores for this network in the future, although
+     *     the scorer may choose to issue an out-of-band update at any time.
+     */
+    public ScoredNetwork(NetworkKey networkKey, RssiCurve rssiCurve) {
+        this.networkKey = networkKey;
+        this.rssiCurve = rssiCurve;
+    }
+
+    private ScoredNetwork(Parcel in) {
+        networkKey = NetworkKey.CREATOR.createFromParcel(in);
+        if (in.readByte() == 1) {
+            rssiCurve = RssiCurve.CREATOR.createFromParcel(in);
+        } else {
+            rssiCurve = null;
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        networkKey.writeToParcel(out, flags);
+        if (rssiCurve != null) {
+            out.writeByte((byte) 1);
+            rssiCurve.writeToParcel(out, flags);
+        } else {
+            out.writeByte((byte) 0);
+        }
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        ScoredNetwork that = (ScoredNetwork) o;
+
+        return Objects.equals(networkKey, that.networkKey) &&
+                Objects.equals(rssiCurve, that.rssiCurve);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(networkKey, rssiCurve);
+    }
+
+    @Override
+    public String toString() {
+        return "ScoredNetwork[key=" + networkKey + ",score=" + rssiCurve + "]";
+    }
+
+    public static final Parcelable.Creator<ScoredNetwork> CREATOR =
+            new Parcelable.Creator<ScoredNetwork>() {
+                @Override
+                public ScoredNetwork createFromParcel(Parcel in) {
+                    return new ScoredNetwork(in);
+                }
+
+                @Override
+                public ScoredNetwork[] newArray(int size) {
+                    return new ScoredNetwork[size];
+                }
+            };
+}
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index a7a8a0a..ce70455 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -21,6 +21,7 @@
 import android.os.Parcelable;
 import android.os.StrictMode;
 import android.util.Log;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
@@ -32,8 +33,10 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Locale;
+import java.util.Objects;
 import java.util.RandomAccess;
 import java.util.Set;
+
 import libcore.net.UriCodec;
 
 /**
@@ -2338,4 +2341,29 @@
             StrictMode.onFileUriExposed(location);
         }
     }
+
+    /**
+     * Test if this is a path prefix match against the given Uri. Verifies that
+     * scheme, authority, and atomic path segments match.
+     *
+     * @hide
+     */
+    public boolean isPathPrefixMatch(Uri prefix) {
+        if (!Objects.equals(getScheme(), prefix.getScheme())) return false;
+        if (!Objects.equals(getAuthority(), prefix.getAuthority())) return false;
+
+        List<String> seg = getPathSegments();
+        List<String> prefixSeg = prefix.getPathSegments();
+
+        final int prefixSize = prefixSeg.size();
+        if (seg.size() < prefixSize) return false;
+
+        for (int i = 0; i < prefixSize; i++) {
+            if (!Objects.equals(seg.get(i), prefixSeg.get(i))) {
+                return false;
+            }
+        }
+
+        return true;
+    }
 }
diff --git a/core/java/android/net/WifiKey.java b/core/java/android/net/WifiKey.java
new file mode 100644
index 0000000..9e92e89
--- /dev/null
+++ b/core/java/android/net/WifiKey.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+import java.util.regex.Pattern;
+
+/**
+ * Information identifying a Wi-Fi network.
+ * @see NetworkKey
+ *
+ * @hide
+ */
+public class WifiKey implements Parcelable {
+
+    // Patterns used for validation.
+    private static final Pattern SSID_PATTERN = Pattern.compile("(\".*\")|(0x[\\p{XDigit}]+)");
+    private static final Pattern BSSID_PATTERN =
+            Pattern.compile("([\\p{XDigit}]{2}:){5}[\\p{XDigit}]{2}");
+
+    /**
+     * The service set identifier (SSID) of an 802.11 network. If the SSID can be decoded as
+     * UTF-8, it will be surrounded by double quotation marks. Otherwise, it will be a string of
+     * hex digits starting with 0x.
+     */
+    public final String ssid;
+
+    /**
+     * The basic service set identifier (BSSID) of an access point for this network. This will
+     * be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX}, where each X is a
+     * hexadecimal digit.
+     */
+    public final String bssid;
+
+    /**
+     * Construct a new {@link WifiKey} for the given Wi-Fi SSID/BSSID pair.
+     *
+     * @param ssid the service set identifier (SSID) of an 802.11 network. If the SSID can be
+     *         decoded as UTF-8, it should be surrounded by double quotation marks. Otherwise,
+     *         it should be a string of hex digits starting with 0x.
+     * @param bssid the basic service set identifier (BSSID) of this network's access point.
+     *         This should be in the form of a six-byte MAC address: {@code XX:XX:XX:XX:XX:XX},
+     *         where each X is a hexadecimal digit.
+     * @throws IllegalArgumentException if either the SSID or BSSID is invalid.
+     */
+    public WifiKey(String ssid, String bssid) {
+        if (!SSID_PATTERN.matcher(ssid).matches()) {
+            throw new IllegalArgumentException("Invalid ssid: " + ssid);
+        }
+        if (!BSSID_PATTERN.matcher(bssid).matches()) {
+            throw new IllegalArgumentException("Invalid bssid: " + bssid);
+        }
+        this.ssid = ssid;
+        this.bssid = bssid;
+    }
+
+    private WifiKey(Parcel in) {
+        ssid = in.readString();
+        bssid = in.readString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(ssid);
+        out.writeString(bssid);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        WifiKey wifiKey = (WifiKey) o;
+
+        return Objects.equals(ssid, wifiKey.ssid) && Objects.equals(bssid, wifiKey.bssid);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(ssid, bssid);
+    }
+
+    @Override
+    public String toString() {
+        return "WifiKey[SSID=" + ssid + ",BSSID=" + bssid + "]";
+    }
+
+    public static final Creator<WifiKey> CREATOR =
+            new Creator<WifiKey>() {
+                @Override
+                public WifiKey createFromParcel(Parcel in) {
+                    return new WifiKey(in);
+                }
+
+                @Override
+                public WifiKey[] newArray(int size) {
+                    return new WifiKey[size];
+                }
+            };
+}
diff --git a/core/java/android/net/nsd/NsdServiceInfo.java b/core/java/android/net/nsd/NsdServiceInfo.java
index 205a21d..6fdb0d0 100644
--- a/core/java/android/net/nsd/NsdServiceInfo.java
+++ b/core/java/android/net/nsd/NsdServiceInfo.java
@@ -18,8 +18,15 @@
 
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.util.Log;
+import android.util.ArrayMap;
 
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.Map;
+
 
 /**
  * A class representing service information for network service discovery
@@ -27,11 +34,13 @@
  */
 public final class NsdServiceInfo implements Parcelable {
 
+    private static final String TAG = "NsdServiceInfo";
+
     private String mServiceName;
 
     private String mServiceType;
 
-    private DnsSdTxtRecord mTxtRecord;
+    private final ArrayMap<String, byte[]> mTxtRecord = new ArrayMap<String, byte[]>();
 
     private InetAddress mHost;
 
@@ -41,10 +50,9 @@
     }
 
     /** @hide */
-    public NsdServiceInfo(String sn, String rt, DnsSdTxtRecord tr) {
+    public NsdServiceInfo(String sn, String rt) {
         mServiceName = sn;
         mServiceType = rt;
-        mTxtRecord = tr;
     }
 
     /** Get the service name */
@@ -67,16 +75,6 @@
         mServiceType = s;
     }
 
-    /** @hide */
-    public DnsSdTxtRecord getTxtRecord() {
-        return mTxtRecord;
-    }
-
-    /** @hide */
-    public void setTxtRecord(DnsSdTxtRecord t) {
-        mTxtRecord = new DnsSdTxtRecord(t);
-    }
-
     /** Get the host address. The host address is valid for a resolved service. */
     public InetAddress getHost() {
         return mHost;
@@ -97,14 +95,134 @@
         mPort = p;
     }
 
+    /** @hide */
+    public void setAttribute(String key, byte[] value) {
+        // Key must be printable US-ASCII, excluding =.
+        for (int i = 0; i < key.length(); ++i) {
+            char character = key.charAt(i);
+            if (character < 0x20 || character > 0x7E) {
+                throw new IllegalArgumentException("Key strings must be printable US-ASCII");
+            } else if (character == 0x3D) {
+                throw new IllegalArgumentException("Key strings must not include '='");
+            }
+        }
+
+        // Key length + value length must be < 255.
+        if (key.length() + (value == null ? 0 : value.length) >= 255) {
+            throw new IllegalArgumentException("Key length + value length must be < 255 bytes");
+        }
+
+        // Warn if key is > 9 characters, as recommended by RFC 6763 section 6.4.
+        if (key.length() > 9) {
+            Log.w(TAG, "Key lengths > 9 are discouraged: " + key);
+        }
+
+        // Check against total TXT record size limits.
+        // Arbitrary 400 / 1300 byte limits taken from RFC 6763 section 6.2.
+        int txtRecordSize = getTxtRecordSize();
+        int futureSize = txtRecordSize + key.length() + (value == null ? 0 : value.length) + 2;
+        if (futureSize > 1300) {
+            throw new IllegalArgumentException("Total length of attributes must be < 1300 bytes");
+        } else if (futureSize > 400) {
+            Log.w(TAG, "Total length of all attributes exceeds 400 bytes; truncation may occur");
+        }
+
+        mTxtRecord.put(key, value);
+    }
+
+    /**
+     * Add a service attribute as a key/value pair.
+     *
+     * <p> Service attributes are included as DNS-SD TXT record pairs.
+     *
+     * <p> The key must be US-ASCII printable characters, excluding the '=' character.  Values may
+     * be UTF-8 strings or null.  The total length of key + value must be less than 255 bytes.
+     *
+     * <p> Keys should be short, ideally no more than 9 characters, and unique per instance of
+     * {@link NsdServiceInfo}.  Calling {@link #setAttribute} twice with the same key will overwrite
+     * first value.
+     */
+    public void setAttribute(String key, String value) {
+        try {
+            setAttribute(key, value == null ? (byte []) null : value.getBytes("UTF-8"));
+        } catch (UnsupportedEncodingException e) {
+            throw new IllegalArgumentException("Value must be UTF-8");
+        }
+    }
+
+    /** Remove an attribute by key */
+    public void removeAttribute(String key) {
+        mTxtRecord.remove(key);
+    }
+
+    /**
+     * Retrive attributes as a map of String keys to byte[] values.
+     *
+     * <p> The returned map is unmodifiable; changes must be made through {@link #setAttribute} and
+     * {@link #removeAttribute}.
+     */
+    public Map<String, byte[]> getAttributes() {
+        return Collections.unmodifiableMap(mTxtRecord);
+    }
+
+    private int getTxtRecordSize() {
+        int txtRecordSize = 0;
+        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+            txtRecordSize += 2;  // One for the length byte, one for the = between key and value.
+            txtRecordSize += entry.getKey().length();
+            byte[] value = entry.getValue();
+            txtRecordSize += value == null ? 0 : value.length;
+        }
+        return txtRecordSize;
+    }
+
+    /** @hide */
+    public byte[] getTxtRecord() {
+        int txtRecordSize = getTxtRecordSize();
+        if (txtRecordSize == 0) {
+            return null;
+        }
+
+        byte[] txtRecord = new byte[txtRecordSize];
+        int ptr = 0;
+        for (Map.Entry<String, byte[]> entry : mTxtRecord.entrySet()) {
+            String key = entry.getKey();
+            byte[] value = entry.getValue();
+
+            // One byte to record the length of this key/value pair.
+            txtRecord[ptr++] = (byte) (key.length() + (value == null ? 0 : value.length) + 1);
+
+            // The key, in US-ASCII.
+            // Note: use the StandardCharsets const here because it doesn't raise exceptions and we
+            // already know the key is ASCII at this point.
+            System.arraycopy(key.getBytes(StandardCharsets.US_ASCII), 0, txtRecord, ptr,
+                    key.length());
+            ptr += key.length();
+
+            // US-ASCII '=' character.
+            txtRecord[ptr++] = (byte)'=';
+
+            // The value, as any raw bytes.
+            if (value != null) {
+                System.arraycopy(value, 0, txtRecord, ptr, value.length);
+                ptr += value.length;
+            }
+        }
+        return txtRecord;
+    }
+
     public String toString() {
         StringBuffer sb = new StringBuffer();
 
-        sb.append("name: ").append(mServiceName).
-            append("type: ").append(mServiceType).
-            append("host: ").append(mHost).
-            append("port: ").append(mPort).
-            append("txtRecord: ").append(mTxtRecord);
+        sb.append("name: ").append(mServiceName)
+                .append(", type: ").append(mServiceType)
+                .append(", host: ").append(mHost)
+                .append(", port: ").append(mPort);
+
+        byte[] txtRecord = getTxtRecord();
+        if (txtRecord != null) {
+            sb.append(", txtRecord: ").append(new String(txtRecord, StandardCharsets.UTF_8));
+        }
         return sb.toString();
     }
 
@@ -117,14 +235,27 @@
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeString(mServiceName);
         dest.writeString(mServiceType);
-        dest.writeParcelable(mTxtRecord, flags);
         if (mHost != null) {
-            dest.writeByte((byte)1);
+            dest.writeInt(1);
             dest.writeByteArray(mHost.getAddress());
         } else {
-            dest.writeByte((byte)0);
+            dest.writeInt(0);
         }
         dest.writeInt(mPort);
+
+        // TXT record key/value pairs.
+        dest.writeInt(mTxtRecord.size());
+        for (String key : mTxtRecord.keySet()) {
+            byte[] value = mTxtRecord.get(key);
+            if (value != null) {
+                dest.writeInt(1);
+                dest.writeInt(value.length);
+                dest.writeByteArray(value);
+            } else {
+                dest.writeInt(0);
+            }
+            dest.writeString(key);
+        }
     }
 
     /** Implement the Parcelable interface */
@@ -134,15 +265,26 @@
                 NsdServiceInfo info = new NsdServiceInfo();
                 info.mServiceName = in.readString();
                 info.mServiceType = in.readString();
-                info.mTxtRecord = in.readParcelable(null);
 
-                if (in.readByte() == 1) {
+                if (in.readInt() == 1) {
                     try {
                         info.mHost = InetAddress.getByAddress(in.createByteArray());
                     } catch (java.net.UnknownHostException e) {}
                 }
 
                 info.mPort = in.readInt();
+
+                // TXT record key/value pairs.
+                int recordCount = in.readInt();
+                for (int i = 0; i < recordCount; ++i) {
+                    byte[] valueArray = null;
+                    if (in.readInt() == 1) {
+                        int valueLength = in.readInt();
+                        valueArray = new byte[valueLength];
+                        in.readByteArray(valueArray);
+                    }
+                    info.mTxtRecord.put(in.readString(), valueArray);
+                }
                 return info;
             }
 
diff --git a/core/java/android/nfc/INfcCardEmulation.aidl b/core/java/android/nfc/INfcCardEmulation.aidl
index b8a5ba7..ae9796b 100644
--- a/core/java/android/nfc/INfcCardEmulation.aidl
+++ b/core/java/android/nfc/INfcCardEmulation.aidl
@@ -17,6 +17,7 @@
 package android.nfc;
 
 import android.content.ComponentName;
+import android.nfc.cardemulation.AidGroup;
 import android.nfc.cardemulation.ApduServiceInfo;
 import android.os.RemoteCallback;
 
@@ -29,5 +30,8 @@
     boolean isDefaultServiceForAid(int userHandle, in ComponentName service, String aid);
     boolean setDefaultServiceForCategory(int userHandle, in ComponentName service, String category);
     boolean setDefaultForNextTap(int userHandle, in ComponentName service);
+    boolean registerAidGroupForService(int userHandle, in ComponentName service, in AidGroup aidGroup);
+    AidGroup getAidGroupForService(int userHandle, in ComponentName service, String category);
+    boolean removeAidGroupForService(int userHandle, in ComponentName service, String category);
     List<ApduServiceInfo> getServices(int userHandle, in String category);
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/nfc/cardemulation/AidGroup.aidl
similarity index 69%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/nfc/cardemulation/AidGroup.aidl
index 0377123..56d6fa5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/nfc/cardemulation/AidGroup.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 The Android Open Source Project
+ * Copyright (C) 2013 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,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.nfc.cardemulation;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable AidGroup;
diff --git a/core/java/android/nfc/cardemulation/AidGroup.java b/core/java/android/nfc/cardemulation/AidGroup.java
new file mode 100644
index 0000000..2820f40
--- /dev/null
+++ b/core/java/android/nfc/cardemulation/AidGroup.java
@@ -0,0 +1,165 @@
+package android.nfc.cardemulation;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+/**
+ * The AidGroup class represents a group of ISO/IEC 7816-4
+ * Application Identifiers (AIDs) for a specific application
+ * category, along with a description resource describing
+ * the group.
+ */
+public final class AidGroup implements Parcelable {
+    /**
+     * The maximum number of AIDs that can be present in any one group.
+     */
+    public static final int MAX_NUM_AIDS = 256;
+
+    static final String TAG = "AidGroup";
+
+    final ArrayList<String> aids;
+    final String category;
+    final String description;
+
+    /**
+     * Creates a new AidGroup object.
+     *
+     * @param aids The list of AIDs present in the group
+     * @param category The category of this group
+     */
+    public AidGroup(ArrayList<String> aids, String category) {
+        if (aids == null || aids.size() == 0) {
+            throw new IllegalArgumentException("No AIDS in AID group.");
+        }
+        if (aids.size() > MAX_NUM_AIDS) {
+            throw new IllegalArgumentException("Too many AIDs in AID group.");
+        }
+        if (!isValidCategory(category)) {
+            throw new IllegalArgumentException("Category specified is not valid.");
+        }
+        this.aids = aids;
+        this.category = category;
+        this.description = null;
+    }
+
+    AidGroup(String category, String description) {
+        this.aids = new ArrayList<String>();
+        this.category = category;
+        this.description = description;
+    }
+
+    /**
+     * @return the category of this AID group
+     */
+    public String getCategory() {
+        return category;
+    }
+
+    /**
+     * @return the list of  AIDs in this group
+     */
+    public ArrayList<String> getAids() {
+        return aids;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder out = new StringBuilder("Category: " + category +
+                  ", AIDs:");
+        for (String aid : aids) {
+            out.append(aid);
+            out.append(", ");
+        }
+        return out.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(category);
+        dest.writeInt(aids.size());
+        if (aids.size() > 0) {
+            dest.writeStringList(aids);
+        }
+    }
+
+    public static final Parcelable.Creator<AidGroup> CREATOR =
+            new Parcelable.Creator<AidGroup>() {
+
+        @Override
+        public AidGroup createFromParcel(Parcel source) {
+            String category = source.readString();
+            int listSize = source.readInt();
+            ArrayList<String> aidList = new ArrayList<String>();
+            if (listSize > 0) {
+                source.readStringList(aidList);
+            }
+            return new AidGroup(aidList, category);
+        }
+
+        @Override
+        public AidGroup[] newArray(int size) {
+            return new AidGroup[size];
+        }
+    };
+
+    /**
+     * @hide
+     * Note: description is not serialized, since it's not localized
+     * and resource identifiers don't make sense to persist.
+     */
+    static public AidGroup createFromXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String category = parser.getAttributeValue(null, "category");
+        ArrayList<String> aids = new ArrayList<String>();
+        int eventType = parser.getEventType();
+        int minDepth = parser.getDepth();
+        while (eventType != XmlPullParser.END_DOCUMENT && parser.getDepth() >= minDepth) {
+            if (eventType == XmlPullParser.START_TAG) {
+                String tagName = parser.getName();
+                if (tagName.equals("aid")) {
+                    String aid = parser.getAttributeValue(null, "value");
+                    if (aid != null) {
+                        aids.add(aid);
+                    }
+                } else {
+                    Log.d(TAG, "Ignorning unexpected tag: " + tagName);
+                }
+            }
+            eventType = parser.next();
+        }
+        if (category != null && aids.size() > 0) {
+            return new AidGroup(aids, category);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void writeAsXml(XmlSerializer out) throws IOException {
+        out.attribute(null, "category", category);
+        for (String aid : aids) {
+            out.startTag(null, "aid");
+            out.attribute(null, "value", aid);
+            out.endTag(null, "aid");
+        }
+    }
+
+    boolean isValidCategory(String category) {
+        return CardEmulation.CATEGORY_PAYMENT.equals(category) ||
+                CardEmulation.CATEGORY_OTHER.equals(category);
+    }
+}
diff --git a/core/java/android/nfc/cardemulation/ApduServiceInfo.java b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
index d7ef4bc..94f35ed 100644
--- a/core/java/android/nfc/cardemulation/ApduServiceInfo.java
+++ b/core/java/android/nfc/cardemulation/ApduServiceInfo.java
@@ -35,9 +35,12 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
+import java.io.FileDescriptor;
 import java.io.IOException;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.Map;
 
 /**
  * @hide
@@ -56,24 +59,19 @@
     final String mDescription;
 
     /**
-     * Convenience AID list
-     */
-    final ArrayList<String> mAids;
-
-    /**
      * Whether this service represents AIDs running on the host CPU
      */
     final boolean mOnHost;
 
     /**
-     * All AID groups this service handles
+     * Mapping from category to static AID group
      */
-    final ArrayList<AidGroup> mAidGroups;
+    final HashMap<String, AidGroup> mStaticAidGroups;
 
     /**
-     * Convenience hashmap
+     * Mapping from category to dynamic AID group
      */
-    final HashMap<String, AidGroup> mCategoryToGroup;
+    final HashMap<String, AidGroup> mDynamicAidGroups;
 
     /**
      * Whether this service should only be started when the device is unlocked.
@@ -86,26 +84,33 @@
     final int mBannerResourceId;
 
     /**
+     * The uid of the package the service belongs to
+     */
+    final int mUid;
+    /**
      * @hide
      */
     public ApduServiceInfo(ResolveInfo info, boolean onHost, String description,
-            ArrayList<AidGroup> aidGroups, boolean requiresUnlock, int bannerResource) {
+            ArrayList<AidGroup> staticAidGroups, ArrayList<AidGroup> dynamicAidGroups,
+            boolean requiresUnlock, int bannerResource, int uid) {
         this.mService = info;
         this.mDescription = description;
-        this.mAidGroups = aidGroups;
-        this.mAids = new ArrayList<String>();
-        this.mCategoryToGroup = new HashMap<String, AidGroup>();
+        this.mStaticAidGroups = new HashMap<String, AidGroup>();
+        this.mDynamicAidGroups = new HashMap<String, AidGroup>();
         this.mOnHost = onHost;
         this.mRequiresDeviceUnlock = requiresUnlock;
-        for (AidGroup aidGroup : aidGroups) {
-            this.mCategoryToGroup.put(aidGroup.category, aidGroup);
-            this.mAids.addAll(aidGroup.aids);
+        for (AidGroup aidGroup : staticAidGroups) {
+            this.mStaticAidGroups.put(aidGroup.category, aidGroup);
+        }
+        for (AidGroup aidGroup : dynamicAidGroups) {
+            this.mDynamicAidGroups.put(aidGroup.category, aidGroup);
         }
         this.mBannerResourceId = bannerResource;
+        this.mUid = uid;
     }
 
-    public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost)
-            throws XmlPullParserException, IOException {
+    public ApduServiceInfo(PackageManager pm, ResolveInfo info, boolean onHost) throws
+            XmlPullParserException, IOException {
         ServiceInfo si = info.serviceInfo;
         XmlResourceParser parser = null;
         try {
@@ -163,10 +168,10 @@
                 sa.recycle();
             }
 
-            mAidGroups = new ArrayList<AidGroup>();
-            mCategoryToGroup = new HashMap<String, AidGroup>();
-            mAids = new ArrayList<String>();
+            mStaticAidGroups = new HashMap<String, AidGroup>();
+            mDynamicAidGroups = new HashMap<String, AidGroup>();
             mOnHost = onHost;
+
             final int depth = parser.getDepth();
             AidGroup currentGroup = null;
 
@@ -179,14 +184,14 @@
                     final TypedArray groupAttrs = res.obtainAttributes(attrs,
                             com.android.internal.R.styleable.AidGroup);
                     // Get category of AID group
-                    String groupDescription = groupAttrs.getString(
-                            com.android.internal.R.styleable.AidGroup_description);
                     String groupCategory = groupAttrs.getString(
                             com.android.internal.R.styleable.AidGroup_category);
+                    String groupDescription = groupAttrs.getString(
+                            com.android.internal.R.styleable.AidGroup_description);
                     if (!CardEmulation.CATEGORY_PAYMENT.equals(groupCategory)) {
                         groupCategory = CardEmulation.CATEGORY_OTHER;
                     }
-                    currentGroup = mCategoryToGroup.get(groupCategory);
+                    currentGroup = mStaticAidGroups.get(groupCategory);
                     if (currentGroup != null) {
                         if (!CardEmulation.CATEGORY_OTHER.equals(groupCategory)) {
                             Log.e(TAG, "Not allowing multiple aid-groups in the " +
@@ -200,9 +205,8 @@
                 } else if (eventType == XmlPullParser.END_TAG && "aid-group".equals(tagName) &&
                         currentGroup != null) {
                     if (currentGroup.aids.size() > 0) {
-                        if (!mCategoryToGroup.containsKey(currentGroup.category)) {
-                            mAidGroups.add(currentGroup);
-                            mCategoryToGroup.put(currentGroup.category, currentGroup);
+                        if (!mStaticAidGroups.containsKey(currentGroup.category)) {
+                            mStaticAidGroups.put(currentGroup.category, currentGroup);
                         }
                     } else {
                         Log.e(TAG, "Not adding <aid-group> with empty or invalid AIDs");
@@ -216,7 +220,6 @@
                             toUpperCase();
                     if (isValidAid(aid) && !currentGroup.aids.contains(aid)) {
                         currentGroup.aids.add(aid);
-                        mAids.add(aid);
                     } else {
                         Log.e(TAG, "Ignoring invalid or duplicate aid: " + aid);
                     }
@@ -228,6 +231,8 @@
         } finally {
             if (parser != null) parser.close();
         }
+        // Set uid
+        mUid = si.applicationInfo.uid;
     }
 
     public ComponentName getComponent() {
@@ -235,16 +240,58 @@
                 mService.serviceInfo.name);
     }
 
+    /**
+     * Returns a consolidated list of AIDs from the AID groups
+     * registered by this service. Note that if a service has both
+     * a static (manifest-based) AID group for a category and a dynamic
+     * AID group, only the dynamically registered AIDs will be returned
+     * for that category.
+     * @return List of AIDs registered by the service
+     */
     public ArrayList<String> getAids() {
-        return mAids;
+        final ArrayList<String> aids = new ArrayList<String>();
+        for (AidGroup group : getAidGroups()) {
+            aids.addAll(group.aids);
+        }
+        return aids;
     }
 
+    /**
+     * Returns the registered AID group for this category.
+     */
+    public AidGroup getDynamicAidGroupForCategory(String category) {
+        return mDynamicAidGroups.get(category);
+    }
+
+    public boolean removeDynamicAidGroupForCategory(String category) {
+        return (mDynamicAidGroups.remove(category) != null);
+    }
+
+    /**
+     * Returns a consolidated list of AID groups
+     * registered by this service. Note that if a service has both
+     * a static (manifest-based) AID group for a category and a dynamic
+     * AID group, only the dynamically registered AID group will be returned
+     * for that category.
+     * @return List of AIDs registered by the service
+     */
     public ArrayList<AidGroup> getAidGroups() {
-        return mAidGroups;
+        final ArrayList<AidGroup> groups = new ArrayList<AidGroup>();
+        for (Map.Entry<String, AidGroup> entry : mDynamicAidGroups.entrySet()) {
+            groups.add(entry.getValue());
+        }
+        for (Map.Entry<String, AidGroup> entry : mStaticAidGroups.entrySet()) {
+            if (!mDynamicAidGroups.containsKey(entry.getKey())) {
+                // Consolidate AID groups - don't return static ones
+                // if a dynamic group exists for the category.
+                groups.add(entry.getValue());
+            }
+        }
+        return groups;
     }
 
     public boolean hasCategory(String category) {
-        return mCategoryToGroup.containsKey(category);
+        return (mStaticAidGroups.containsKey(category) || mDynamicAidGroups.containsKey(category));
     }
 
     public boolean isOnHost() {
@@ -259,6 +306,14 @@
         return mDescription;
     }
 
+    public int getUid() {
+        return mUid;
+    }
+
+    public void setOrReplaceDynamicAidGroup(AidGroup aidGroup) {
+        mDynamicAidGroups.put(aidGroup.getCategory(), aidGroup);
+    }
+
     public CharSequence loadLabel(PackageManager pm) {
         return mService.loadLabel(pm);
     }
@@ -304,8 +359,12 @@
         StringBuilder out = new StringBuilder("ApduService: ");
         out.append(getComponent());
         out.append(", description: " + mDescription);
-        out.append(", AID Groups: ");
-        for (AidGroup aidGroup : mAidGroups) {
+        out.append(", Static AID Groups: ");
+        for (AidGroup aidGroup : mStaticAidGroups.values()) {
+            out.append(aidGroup.toString());
+        }
+        out.append(", Dynamic AID Groups: ");
+        for (AidGroup aidGroup : mDynamicAidGroups.values()) {
             out.append(aidGroup.toString());
         }
         return out.toString();
@@ -336,12 +395,17 @@
         mService.writeToParcel(dest, flags);
         dest.writeString(mDescription);
         dest.writeInt(mOnHost ? 1 : 0);
-        dest.writeInt(mAidGroups.size());
-        if (mAidGroups.size() > 0) {
-            dest.writeTypedList(mAidGroups);
+        dest.writeInt(mStaticAidGroups.size());
+        if (mStaticAidGroups.size() > 0) {
+            dest.writeTypedList(new ArrayList<AidGroup>(mStaticAidGroups.values()));
+        }
+        dest.writeInt(mDynamicAidGroups.size());
+        if (mDynamicAidGroups.size() > 0) {
+            dest.writeTypedList(new ArrayList<AidGroup>(mDynamicAidGroups.values()));
         }
         dest.writeInt(mRequiresDeviceUnlock ? 1 : 0);
         dest.writeInt(mBannerResourceId);
+        dest.writeInt(mUid);
     };
 
     public static final Parcelable.Creator<ApduServiceInfo> CREATOR =
@@ -351,14 +415,21 @@
             ResolveInfo info = ResolveInfo.CREATOR.createFromParcel(source);
             String description = source.readString();
             boolean onHost = (source.readInt() != 0) ? true : false;
-            ArrayList<AidGroup> aidGroups = new ArrayList<AidGroup>();
-            int numGroups = source.readInt();
-            if (numGroups > 0) {
-                source.readTypedList(aidGroups, AidGroup.CREATOR);
+            ArrayList<AidGroup> staticAidGroups = new ArrayList<AidGroup>();
+            int numStaticGroups = source.readInt();
+            if (numStaticGroups > 0) {
+                source.readTypedList(staticAidGroups, AidGroup.CREATOR);
+            }
+            ArrayList<AidGroup> dynamicAidGroups = new ArrayList<AidGroup>();
+            int numDynamicGroups = source.readInt();
+            if (numDynamicGroups > 0) {
+                source.readTypedList(dynamicAidGroups, AidGroup.CREATOR);
             }
             boolean requiresUnlock = (source.readInt() != 0) ? true : false;
             int bannerResource = source.readInt();
-            return new ApduServiceInfo(info, onHost, description, aidGroups, requiresUnlock, bannerResource);
+            int uid = source.readInt();
+            return new ApduServiceInfo(info, onHost, description, staticAidGroups,
+                    dynamicAidGroups, requiresUnlock, bannerResource, uid);
         }
 
         @Override
@@ -367,76 +438,22 @@
         }
     };
 
-    public static class AidGroup implements Parcelable {
-        final ArrayList<String> aids;
-        final String category;
-        final String description;
-
-        AidGroup(ArrayList<String> aids, String category, String description) {
-            this.aids = aids;
-            this.category = category;
-            this.description = description;
-        }
-
-        AidGroup(String category, String description) {
-            this.aids = new ArrayList<String>();
-            this.category = category;
-            this.description = description;
-        }
-
-        public String getCategory() {
-            return category;
-        }
-
-        public ArrayList<String> getAids() {
-            return aids;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder out = new StringBuilder("Category: " + category +
-                      ", description: " + description + ", AIDs:");
-            for (String aid : aids) {
-                out.append(aid);
-                out.append(", ");
-            }
-            return out.toString();
-        }
-
-        @Override
-        public int describeContents() {
-            return 0;
-        }
-
-        @Override
-        public void writeToParcel(Parcel dest, int flags) {
-            dest.writeString(category);
-            dest.writeString(description);
-            dest.writeInt(aids.size());
-            if (aids.size() > 0) {
-                dest.writeStringList(aids);
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("    " + getComponent() +
+                " (Description: " + getDescription() + ")");
+        pw.println("    Static AID groups:");
+        for (AidGroup group : mStaticAidGroups.values()) {
+            pw.println("        Category: " + group.category);
+            for (String aid : group.aids) {
+                pw.println("            AID: " + aid);
             }
         }
-
-        public static final Parcelable.Creator<ApduServiceInfo.AidGroup> CREATOR =
-                new Parcelable.Creator<ApduServiceInfo.AidGroup>() {
-
-            @Override
-            public AidGroup createFromParcel(Parcel source) {
-                String category = source.readString();
-                String description = source.readString();
-                int listSize = source.readInt();
-                ArrayList<String> aidList = new ArrayList<String>();
-                if (listSize > 0) {
-                    source.readStringList(aidList);
-                }
-                return new AidGroup(aidList, category, description);
+        pw.println("    Dynamic AID groups:");
+        for (AidGroup group : mDynamicAidGroups.values()) {
+            pw.println("        Category: " + group.category);
+            for (String aid : group.aids) {
+                pw.println("            AID: " + aid);
             }
-
-            @Override
-            public AidGroup[] newArray(int size) {
-                return new AidGroup[size];
-            }
-        };
+        }
     }
 }
diff --git a/core/java/android/nfc/cardemulation/CardEmulation.java b/core/java/android/nfc/cardemulation/CardEmulation.java
index 58d9616..41f039c 100644
--- a/core/java/android/nfc/cardemulation/CardEmulation.java
+++ b/core/java/android/nfc/cardemulation/CardEmulation.java
@@ -168,6 +168,10 @@
         if (manager == null) {
             // Get card emu service
             INfcCardEmulation service = adapter.getCardEmulationService();
+            if (service == null) {
+                Log.e(TAG, "This device does not implement the INfcCardEmulation interface.");
+                throw new UnsupportedOperationException();
+            }
             manager = new CardEmulation(context, service);
             sCardEmus.put(context, manager);
         }
@@ -271,6 +275,109 @@
     }
 
     /**
+     * Registers a group of AIDs for the specified service.
+     *
+     * <p>If an AID group for that category was previously
+     * registered for this service (either statically
+     * through the manifest, or dynamically by using this API),
+     * that AID group will be replaced with this one.
+     *
+     * <p>Note that you can only register AIDs for a service that
+     * is running under the same UID as you are. Typically
+     * this means you need to call this from the same
+     * package as the service itself, though UIDs can also
+     * be shared between packages using shared UIDs.
+     *
+     * @param service The component name of the service
+     * @param aidGroup The group of AIDs to be registered
+     * @return whether the registration was successful.
+     */
+    public boolean registerAidGroupForService(ComponentName service, AidGroup aidGroup) {
+        try {
+            return sService.registerAidGroupForService(UserHandle.myUserId(), service, aidGroup);
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return false;
+            }
+            try {
+                return sService.registerAidGroupForService(UserHandle.myUserId(), service,
+                        aidGroup);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return false;
+            }
+        }
+    }
+
+    /**
+     * Retrieves the currently registered AID group for the specified
+     * category for a service.
+     *
+     * <p>Note that this will only return AID groups that were dynamically
+     * registered using {@link #registerAidGroupForService(ComponentName, AidGroup)}
+     * method. It will *not* return AID groups that were statically registered
+     * in the manifest.
+     *
+     * @param service The component name of the service
+     * @param category The category of the AID group to be returned, e.g. {@link #CATEGORY_PAYMENT}
+     * @return The AID group, or null if it couldn't be found
+     */
+    public AidGroup getAidGroupForService(ComponentName service, String category) {
+        try {
+            return sService.getAidGroupForService(UserHandle.myUserId(), service, category);
+        } catch (RemoteException e) {
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+            try {
+                return sService.getAidGroupForService(UserHandle.myUserId(), service, category);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return null;
+            }
+        }
+    }
+
+    /**
+     * Removes a registered AID group for the specified category for the
+     * service provided.
+     *
+     * <p>Note that this will only remove AID groups that were dynamically
+     * registered using the {@link #registerAidGroupForService(ComponentName, AidGroup)}
+     * method. It will *not* remove AID groups that were statically registered in
+     * the manifest. If a dynamically registered AID group is removed using
+     * this method, and a statically registered AID group for the same category
+     * exists in the manifest, that AID group will become active again.
+     *
+     * @param service The component name of the service
+     * @param category The category of the AID group to be removed, e.g. {@link #CATEGORY_PAYMENT}
+     * @return whether the group was successfully removed.
+     */
+    public boolean removeAidGroupForService(ComponentName service, String category) {
+        try {
+            return sService.removeAidGroupForService(UserHandle.myUserId(), service, category);
+        } catch (RemoteException e) {
+            // Try one more time
+            recoverService();
+            if (sService == null) {
+                Log.e(TAG, "Failed to recover CardEmulationService.");
+                return false;
+            }
+            try {
+                return sService.removeAidGroupForService(UserHandle.myUserId(), service, category);
+            } catch (RemoteException ee) {
+                Log.e(TAG, "Failed to reach CardEmulationService.");
+                return false;
+            }
+        }
+    }
+
+    /**
      * @hide
      */
     public boolean setDefaultServiceForCategory(ComponentName service, String category) {
diff --git a/core/java/android/os/BatteryManager.java b/core/java/android/os/BatteryManager.java
index 2e38960..f339e52 100644
--- a/core/java/android/os/BatteryManager.java
+++ b/core/java/android/os/BatteryManager.java
@@ -16,9 +16,15 @@
 
 package android.os;
 
+import android.os.BatteryProperty;
+import android.os.IBatteryPropertiesRegistrar;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+
 /**
  * The BatteryManager class contains strings and constants used for values
- * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent.
+ * in the {@link android.content.Intent#ACTION_BATTERY_CHANGED} Intent, and
+ * provides a method for querying battery and charging properties.
  */
 public class BatteryManager {
     /**
@@ -121,4 +127,30 @@
     /** @hide */
     public static final int BATTERY_PLUGGED_ANY =
             BATTERY_PLUGGED_AC | BATTERY_PLUGGED_USB | BATTERY_PLUGGED_WIRELESS;
+
+    private IBatteryPropertiesRegistrar mBatteryPropertiesRegistrar;
+
+    /**
+     * Return the requested battery property.
+     *
+     * @param id identifier from {@link BatteryProperty} of the requested property
+     * @return a {@link BatteryProperty} object that returns the property value, or null on error
+     */
+    public BatteryProperty getProperty(int id) throws RemoteException {
+        if (mBatteryPropertiesRegistrar == null) {
+            IBinder b = ServiceManager.getService("batteryproperties");
+            mBatteryPropertiesRegistrar =
+                IBatteryPropertiesRegistrar.Stub.asInterface(b);
+
+            if (mBatteryPropertiesRegistrar == null)
+                return null;
+        }
+
+        BatteryProperty prop = new BatteryProperty(Integer.MIN_VALUE);
+        if ((mBatteryPropertiesRegistrar.getProperty(id, prop) == 0) &&
+            (prop.getInt() != Integer.MIN_VALUE))
+            return prop;
+        else
+            return null;
+    }
 }
diff --git a/core/java/android/os/BatteryProperty.java b/core/java/android/os/BatteryProperty.java
index 76b0dc4..ec73952 100644
--- a/core/java/android/os/BatteryProperty.java
+++ b/core/java/android/os/BatteryProperty.java
@@ -19,22 +19,67 @@
 import android.os.Parcelable;
 
 /**
- * {@hide}
+ * Battery properties that may be queried using
+ * {@link BatteryManager#getProperty
+ * BatteryManager.getProperty()}
  */
 public class BatteryProperty implements Parcelable {
     /*
      * Battery property identifiers.  These must match the values in
      * frameworks/native/include/batteryservice/BatteryService.h
      */
-    public static final int BATTERY_PROP_CHARGE_COUNTER = 1;
-    public static final int BATTERY_PROP_CURRENT_NOW = 2;
-    public static final int BATTERY_PROP_CURRENT_AVG = 3;
-    public static final int BATTERY_PROP_CAPACITY = 4;
+    /** Battery capacity in microampere-hours, as an integer. */
+    public static final int CHARGE_COUNTER = 1;
 
-    public int valueInt;
+    /**
+     * Instantaneous battery current in microamperes, as an integer.  Positive
+     * values indicate net current entering the battery from a charge source,
+     * negative values indicate net current discharging from the battery.
+     */
+    public static final int CURRENT_NOW = 2;
 
+    /**
+     * Average battery current in microamperes, as an integer.  Positive
+     * values indicate net current entering the battery from a charge source,
+     * negative values indicate net current discharging from the battery.
+     * The time period over which the average is computed may depend on the
+     * fuel gauge hardware and its configuration.
+     */
+    public static final int CURRENT_AVERAGE = 3;
+
+    /**
+     * Remaining battery capacity as an integer percentage of total capacity
+     * (with no fractional part).
+     */
+    public static final int CAPACITY = 4;
+
+    private int mValueInt;
+
+    /**
+     * @hide
+     */
+    public BatteryProperty(int value) {
+        mValueInt = value;
+    }
+
+    /**
+     * @hide
+     */
     public BatteryProperty() {
-        valueInt = Integer.MIN_VALUE;
+        mValueInt = Integer.MIN_VALUE;
+    }
+
+    /**
+     * Return the value of a property of integer type previously queried
+     * via {@link BatteryManager#getProperty
+     * BatteryManager.getProperty()}.  If the platform does
+     * not provide the property queried, this value will be
+     * Integer.MIN_VALUE.
+     *
+     * @return The queried property value, or Integer.MIN_VALUE if not supported.
+     */
+    public int getInt() {
+        return mValueInt;
     }
 
     /*
@@ -47,11 +92,11 @@
     }
 
     public void readFromParcel(Parcel p) {
-        valueInt = p.readInt();
+        mValueInt = p.readInt();
     }
 
     public void writeToParcel(Parcel p, int flags) {
-        p.writeInt(valueInt);
+        p.writeInt(mValueInt);
     }
 
     public static final Parcelable.Creator<BatteryProperty> CREATOR
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 426f21e..9e9820f 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -130,8 +130,8 @@
     // NOTE: Update this list if you add/change any stats above.
     // These characters are supposed to represent "total", "last", "current", 
     // and "unplugged". They were shortened for efficiency sake.
-    private static final String[] STAT_NAMES = { "t", "l", "c", "u" };
-    
+    private static final String[] STAT_NAMES = { "l", "c", "u" };
+
     /**
      * Bump the version on this if the checkin format changes.
      */
@@ -173,6 +173,8 @@
     private static final String BLUETOOTH_STATE_COUNT_DATA = "bsc";
     private static final String POWER_USE_SUMMARY_DATA = "pws";
     private static final String POWER_USE_ITEM_DATA = "pwi";
+    private static final String DISCHARGE_STEP_DATA = "dsd";
+    private static final String CHARGE_STEP_DATA = "csd";
 
     private final StringBuilder mFormatBuilder = new StringBuilder(32);
     private final Formatter mFormatter = new Formatter(mFormatBuilder);
@@ -186,7 +188,7 @@
          * Returns the count associated with this Counter for the
          * selected type of statistics.
          *
-         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
+         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          */
         public abstract int getCountLocked(int which);
 
@@ -205,7 +207,7 @@
          * Returns the count associated with this Counter for the
          * selected type of statistics.
          *
-         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
+         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          */
         public abstract long getCountLocked(int which);
 
@@ -224,7 +226,7 @@
          * Returns the count associated with this Timer for the
          * selected type of statistics.
          *
-         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
+         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          */
         public abstract int getCountLocked(int which);
 
@@ -233,7 +235,7 @@
          * selected type of statistics.
          *
          * @param elapsedRealtimeUs current elapsed realtime of system in microseconds
-         * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT
+         * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT
          * @return a time in microseconds
          */
         public abstract long getTotalTimeLocked(long elapsedRealtimeUs, int which);
@@ -385,27 +387,27 @@
             /**
              * Returns the total time (in 1/100 sec) spent executing in user code.
              *
-             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
             public abstract long getUserTime(int which);
 
             /**
              * Returns the total time (in 1/100 sec) spent executing in system code.
              *
-             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
             public abstract long getSystemTime(int which);
 
             /**
              * Returns the number of times the process has been started.
              *
-             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
             public abstract int getStarts(int which);
 
             /**
              * Returns the cpu time spent in microseconds while the process was in the foreground.
-             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              * @return foreground cpu time in microseconds
              */
             public abstract long getForegroundTime(int which);
@@ -414,7 +416,7 @@
              * Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
              * @param speedStep the index of the CPU speed. This is not the actual speed of the
              * CPU.
-             * @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              * @see BatteryStats#getCpuSpeedSteps()
              */
             public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
@@ -433,7 +435,7 @@
              * Returns the number of times this package has done something that could wake up the
              * device from sleep.
              *
-             * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+             * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
              */
             public abstract int getWakeups(int which);
 
@@ -451,7 +453,7 @@
                  * Returns the amount of time spent started.
                  *
                  * @param batteryUptime elapsed uptime on battery in microseconds.
-                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  * @return
                  */
                 public abstract long getStartTime(long batteryUptime, int which);
@@ -459,14 +461,14 @@
                 /**
                  * Returns the total number of times startService() has been called.
                  *
-                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  */
                 public abstract int getStarts(int which);
 
                 /**
                  * Returns the total number times the service has been launched.
                  *
-                 * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+                 * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
                  */
                 public abstract int getLaunches(int which);
             }
@@ -1285,7 +1287,7 @@
      * Returns the total, last, or current battery uptime in microseconds.
      *
      * @param curTime the elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeBatteryUptime(long curTime, int which);
 
@@ -1293,7 +1295,7 @@
      * Returns the total, last, or current battery realtime in microseconds.
      *
      * @param curTime the current elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeBatteryRealtime(long curTime, int which);
 
@@ -1301,7 +1303,7 @@
      * Returns the total, last, or current battery screen off uptime in microseconds.
      *
      * @param curTime the elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeBatteryScreenOffUptime(long curTime, int which);
 
@@ -1309,7 +1311,7 @@
      * Returns the total, last, or current battery screen off realtime in microseconds.
      *
      * @param curTime the current elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeBatteryScreenOffRealtime(long curTime, int which);
 
@@ -1317,18 +1319,62 @@
      * Returns the total, last, or current uptime in microseconds.
      *
      * @param curTime the current elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeUptime(long curTime, int which);
 
     /**
      * Returns the total, last, or current realtime in microseconds.
-     * *
+     *
      * @param curTime the current elapsed realtime in microseconds.
-     * @param which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      */
     public abstract long computeRealtime(long curTime, int which);
-    
+
+    /**
+     * Compute an approximation for how much run time (in microseconds) is remaining on
+     * the battery.  Returns -1 if no time can be computed: either there is not
+     * enough current data to make a decision, or the battery is currently
+     * charging.
+     *
+     * @param curTime The current elepsed realtime in microseconds.
+     */
+    public abstract long computeBatteryTimeRemaining(long curTime);
+
+    /**
+     * Return the historical number of discharge steps we currently have.
+     */
+    public abstract int getNumDischargeStepDurations();
+
+    /**
+     * Return the array of discharge step durations; the number of valid
+     * items in it is returned by {@link #getNumDischargeStepDurations()}.
+     * These values are in milliseconds.
+     */
+    public abstract long[] getDischargeStepDurationsArray();
+
+    /**
+     * Compute an approximation for how much time (in microseconds) remains until the battery
+     * is fully charged.  Returns -1 if no time can be computed: either there is not
+     * enough current data to make a decision, or the battery is currently
+     * discharging.
+     *
+     * @param curTime The current elepsed realtime in microseconds.
+     */
+    public abstract long computeChargeTimeRemaining(long curTime);
+
+    /**
+     * Return the historical number of charge steps we currently have.
+     */
+    public abstract int getNumChargeStepDurations();
+
+    /**
+     * Return the array of charge step durations; the number of valid
+     * items in it is returned by {@link #getNumChargeStepDurations()}.
+     * These values are in milliseconds.
+     */
+    public abstract long[] getChargeStepDurationsArray();
+
     public abstract Map<String, ? extends LongCounter> getWakeupReasonStats();
 
     public abstract Map<String, ? extends Timer> getKernelWakelockStats();
@@ -1430,7 +1476,7 @@
      * @param timer a Timer object contining the wakelock times.
      * @param elapsedRealtimeUs the current on-battery time in microseconds.
      * @param name the name of the wakelock.
-     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      * @param linePrefix a String to be prepended to each line of output.
      * @return the line prefix
      */
@@ -1464,7 +1510,7 @@
      * @param timer a Timer object contining the wakelock times.
      * @param elapsedRealtimeUs the current time in microseconds.
      * @param name the name of the wakelock.
-     * @param which which one of STATS_TOTAL, STATS_LAST, or STATS_CURRENT.
+     * @param which which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
      * @param linePrefix a String to be prepended to each line of output.
      * @return the line prefix
      */
@@ -1682,7 +1728,7 @@
             }
         }
         
-        BatteryStatsHelper helper = new BatteryStatsHelper(context);
+        BatteryStatsHelper helper = new BatteryStatsHelper(context, false);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
         List<BatterySipper> sippers = helper.getUsageList();
@@ -1929,6 +1975,8 @@
         final long whichBatteryScreenOffUptime = computeBatteryScreenOffUptime(rawUptime, which);
         final long whichBatteryScreenOffRealtime = computeBatteryScreenOffRealtime(rawRealtime,
                 which);
+        final long batteryTimeRemaining = computeBatteryTimeRemaining(rawRealtime);
+        final long chargeTimeRemaining = computeChargeTimeRemaining(rawRealtime);
 
         StringBuilder sb = new StringBuilder(128);
         
@@ -1963,7 +2011,20 @@
                 sb.append("realtime, ");
                 formatTimeMs(sb, totalUptime / 1000);
                 sb.append("uptime");
-        pw.println(sb.toString());
+        if (batteryTimeRemaining >= 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Battery time remaining: ");
+                    formatTimeMs(sb, batteryTimeRemaining / 1000);
+            pw.println(sb.toString());
+        }
+        if (chargeTimeRemaining >= 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                    sb.append("  Charge time remaining: ");
+                    formatTimeMs(sb, chargeTimeRemaining / 1000);
+            pw.println(sb.toString());
+        }
         pw.print("  Start clock time: ");
         pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
 
@@ -2268,7 +2329,7 @@
             pw.println();
         }
 
-        BatteryStatsHelper helper = new BatteryStatsHelper(context);
+        BatteryStatsHelper helper = new BatteryStatsHelper(context, false);
         helper.create(this);
         helper.refreshStats(which, UserHandle.USER_ALL);
         List<BatterySipper> sippers = helper.getUsageList();
@@ -2861,29 +2922,21 @@
         int oldTemp = -1;
         int oldVolt = -1;
         long lastTime = -1;
+        long firstTime = -1;
 
-        public void printNextItem(PrintWriter pw, HistoryItem rec, long now, boolean checkin,
+        public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin,
                 boolean verbose) {
             if (!checkin) {
                 pw.print("  ");
-                if (now >= 0) {
-                    TimeUtils.formatDuration(rec.time-now, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
-                } else {
-                    TimeUtils.formatDuration(rec.time, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
-                }
+                TimeUtils.formatDuration(rec.time - baseTime, pw, TimeUtils.HUNDRED_DAY_FIELD_LEN);
                 pw.print(" (");
                 pw.print(rec.numReadInts);
                 pw.print(") ");
             } else {
                 if (lastTime < 0) {
-                    if (now >= 0) {
-                        pw.print("@");
-                        pw.print(rec.time-now);
-                    } else {
-                        pw.print(rec.time);
-                    }
+                    pw.print(rec.time - baseTime);
                 } else {
-                    pw.print(rec.time-lastTime);
+                    pw.print(rec.time - lastTime);
                 }
                 lastTime = rec.time;
             }
@@ -3093,6 +3146,28 @@
         pw.print(suffix);
     }
 
+    private static boolean dumpDurationSteps(PrintWriter pw, String header, long[] steps,
+            int count, boolean checkin) {
+        if (count <= 0) {
+            return false;
+        }
+        if (!checkin) {
+            pw.println(header);
+        }
+        String[] lineArgs = new String[1];
+        for (int i=0; i<count; i++) {
+            if (checkin) {
+                lineArgs[0] = Long.toString(steps[i]);
+                dumpLine(pw, 0 /* uid */, "i" /* category */, header, (Object[])lineArgs);
+            } else {
+                pw.print("  #"); pw.print(i); pw.print(": ");
+                TimeUtils.formatDuration(steps[i], pw);
+                pw.println();
+            }
+        }
+        return true;
+    }
+
     public static final int DUMP_UNPLUGGED_ONLY = 1<<0;
     public static final int DUMP_CHARGED_ONLY = 1<<1;
     public static final int DUMP_HISTORY_ONLY = 1<<2;
@@ -3132,10 +3207,27 @@
                     pw.println("):");
                     HistoryPrinter hprinter = new HistoryPrinter();
                     long lastTime = -1;
+                    long baseTime = -1;
+                    boolean printed = false;
                     while (getNextHistoryLocked(rec)) {
                         lastTime = rec.time;
+                        if (baseTime < 0) {
+                            baseTime = lastTime;
+                        }
                         if (rec.time >= histStart) {
-                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, false,
+                            if (histStart >= 0 && !printed) {
+                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+                                    printed = true;
+                                } else if (rec.currentTime != 0) {
+                                    printed = true;
+                                    byte cmd = rec.cmd;
+                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+                                    hprinter.printNextItem(pw, rec, baseTime, false,
+                                            (flags&DUMP_VERBOSE) != 0);
+                                    rec.cmd = cmd;
+                                }
+                            }
+                            hprinter.printNextItem(pw, rec, baseTime, false,
                                     (flags&DUMP_VERBOSE) != 0);
                         }
                     }
@@ -3152,8 +3244,12 @@
                 try {
                     pw.println("Old battery History:");
                     HistoryPrinter hprinter = new HistoryPrinter();
+                    long baseTime = -1;
                     while (getNextOldHistoryLocked(rec)) {
-                        hprinter.printNextItem(pw, rec, now, false, (flags&DUMP_VERBOSE) != 0);
+                        if (baseTime < 0) {
+                            baseTime = rec.time;
+                        }
+                        hprinter.printNextItem(pw, rec, baseTime, false, (flags&DUMP_VERBOSE) != 0);
                     }
                     pw.println();
                 } finally {
@@ -3191,7 +3287,27 @@
                 }
             }
             if (didPid) {
-                pw.println("");
+                pw.println();
+            }
+            if (dumpDurationSteps(pw, "Discharge step durations:", getDischargeStepDurationsArray(),
+                    getNumDischargeStepDurations(), false)) {
+                long timeRemaining = computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+                if (timeRemaining >= 0) {
+                    pw.print("  Estimated discharge time remaining: ");
+                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
+                    pw.println();
+                }
+                pw.println();
+            }
+            if (dumpDurationSteps(pw, "Charge step durations:", getChargeStepDurationsArray(),
+                    getNumChargeStepDurations(), false)) {
+                long timeRemaining = computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+                if (timeRemaining >= 0) {
+                    pw.print("  Estimated charge time remaining: ");
+                    TimeUtils.formatDuration(timeRemaining / 1000, pw);
+                    pw.println();
+                }
+                pw.println();
             }
         }
 
@@ -3200,7 +3316,7 @@
             pw.println("  System starts: " + getStartCount()
                     + ", currently on battery: " + getIsOnBattery());
             dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
-            pw.println("");
+            pw.println();
         }
         if (!filtering || (flags&DUMP_UNPLUGGED_ONLY) != 0) {
             pw.println("Statistics since last unplugged:");
@@ -3226,20 +3342,42 @@
                         pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
                         pw.print(HISTORY_STRING_POOL); pw.print(',');
                         pw.print(i);
-                        pw.print(',');
-                        pw.print(getHistoryTagPoolString(i));
-                        pw.print(',');
+                        pw.print(",");
                         pw.print(getHistoryTagPoolUid(i));
+                        pw.print(",\"");
+                        String str = getHistoryTagPoolString(i);
+                        str = str.replace("\\", "\\\\");
+                        str = str.replace("\"", "\\\"");
+                        pw.print(str);
+                        pw.print("\"");
                         pw.println();
                     }
                     HistoryPrinter hprinter = new HistoryPrinter();
                     long lastTime = -1;
+                    long baseTime = -1;
+                    boolean printed = false;
                     while (getNextHistoryLocked(rec)) {
                         lastTime = rec.time;
+                        if (baseTime < 0) {
+                            baseTime = lastTime;
+                        }
                         if (rec.time >= histStart) {
+                            if (histStart >= 0 && !printed) {
+                                if (rec.cmd == HistoryItem.CMD_CURRENT_TIME) {
+                                    printed = true;
+                                } else if (rec.currentTime != 0) {
+                                    printed = true;
+                                    byte cmd = rec.cmd;
+                                    rec.cmd = HistoryItem.CMD_CURRENT_TIME;
+                                    pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
+                                    pw.print(HISTORY_DATA); pw.print(',');
+                                    hprinter.printNextItem(pw, rec, baseTime, true, false);
+                                    rec.cmd = cmd;
+                                }
+                            }
                             pw.print(BATTERY_STATS_CHECKIN_VERSION); pw.print(',');
                             pw.print(HISTORY_DATA); pw.print(',');
-                            hprinter.printNextItem(pw, rec, histStart >= 0 ? -1 : now, true, false);
+                            hprinter.printNextItem(pw, rec, baseTime, true, false);
                         }
                     }
                     if (histStart >= 0) {
@@ -3282,6 +3420,12 @@
                 }
             }
         }
+        if (!filtering) {
+            dumpDurationSteps(pw, DISCHARGE_STEP_DATA, getDischargeStepDurationsArray(),
+                    getNumDischargeStepDurations(), true);
+            dumpDurationSteps(pw, CHARGE_STEP_DATA, getChargeStepDurationsArray(),
+                    getNumChargeStepDurations(), true);
+        }
         if (!filtering || (flags&DUMP_CHARGED_ONLY) != 0) {
             dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
         }
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index c8051aa..1ca6b90 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -16,12 +16,17 @@
 
 package android.os;
 
+import android.text.TextUtils;
+import android.util.Slog;
+
 import com.android.internal.telephony.TelephonyProperties;
 
 /**
  * Information about the current build, extracted from system properties.
  */
 public class Build {
+    private static final String TAG = "Build";
+
     /** Value used for when a build property is unknown. */
     public static final String UNKNOWN = "unknown";
 
@@ -74,7 +79,40 @@
 
     /** A hardware serial number, if available.  Alphanumeric only, case-insensitive. */ 
     public static final String SERIAL = getString("ro.serialno");
-  
+
+    /**
+     * An ordered list of ABIs supported by this device. The most preferred ABI is the first
+     * element in the list.
+     *
+     * See {@link #SUPPORTED_32_BIT_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
+     *
+     * @hide
+     */
+    public static final String[] SUPPORTED_ABIS = getString("ro.product.cpu.abilist").split(",");
+
+    /**
+     * An ordered list of <b>32 bit</b> ABIs supported by this device. The most preferred ABI
+     * is the first element in the list.
+     *
+     * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_64_BIT_ABIS}.
+     *
+     * @hide
+     */
+    public static final String[] SUPPORTED_32_BIT_ABIS = getString("ro.product.cpu.abilist32")
+            .split(",");
+
+    /**
+     * An ordered list of <b>64 bit</b> ABIs supported by this device. The most preferred ABI
+     * is the first element in the list.
+     *
+     * See {@link #SUPPORTED_ABIS} and {@link #SUPPORTED_32_BIT_ABIS}.
+     *
+     * @hide
+     */
+    public static final String[] SUPPORTED_64_BIT_ABIS = getString("ro.product.cpu.abilist64")
+            .split(",");
+
+
     /** Various version strings. */
     public static class VERSION {
         /**
@@ -111,14 +149,22 @@
          */
         public static final String CODENAME = getString("ro.build.version.codename");
 
+        private static final String[] ALL_CODENAMES
+                = getString("ro.build.version.all_codenames").split(",");
+
         /**
-         * The SDK version to use when accessing resources.
-         * Use the current SDK version code.  If we are a development build,
-         * also allow the previous SDK version + 1.
          * @hide
          */
-        public static final int RESOURCES_SDK_INT = SDK_INT
-                + ("REL".equals(CODENAME) ? 0 : 1);
+        public static final String[] ACTIVE_CODENAMES = "REL".equals(ALL_CODENAMES[0])
+                ? new String[0] : ALL_CODENAMES;
+
+        /**
+         * The SDK version to use when accessing resources.
+         * Use the current SDK version code.  For every active development codename
+         * we are operating under, we bump the assumed resource platform version by 1.
+         * @hide
+         */
+        public static final int RESOURCES_SDK_INT = SDK_INT + ACTIVE_CODENAMES.length;
     }
 
     /**
@@ -469,13 +515,18 @@
         public static final int KITKAT = 19;
 
         /**
+         * Android 4.5: KitKat for watches, snacks on the run.
+         */
+        public static final int KITKAT_WATCH = CUR_DEVELOPMENT; // STOPSHIP: update API level
+
+        /**
          * L!
          *
          * <p>Applications targeting this or a later release will get these
          * new changes in behavior:</p>
          * <ul>
          * <li> {@link android.content.Context#bindService Context.bindService} now
-         * requires an explicit Intent, and will throw an exception if given an explicit
+         * requires an explicit Intent, and will throw an exception if given an implicit
          * Intent.</li>
          * </ul>
          */
@@ -489,7 +540,43 @@
     public static final String TAGS = getString("ro.build.tags");
 
     /** A string that uniquely identifies this build.  Do not attempt to parse this value. */
-    public static final String FINGERPRINT = getString("ro.build.fingerprint");
+    public static final String FINGERPRINT = deriveFingerprint();
+
+    /**
+     * Some devices split the fingerprint components between multiple
+     * partitions, so we might derive the fingerprint at runtime.
+     */
+    private static String deriveFingerprint() {
+        String finger = SystemProperties.get("ro.build.fingerprint");
+        if (TextUtils.isEmpty(finger)) {
+            finger = getString("ro.product.brand") + '/' +
+                    getString("ro.product.name") + '/' +
+                    getString("ro.product.device") + ':' +
+                    getString("ro.build.version.release") + '/' +
+                    getString("ro.build.id") + '/' +
+                    getString("ro.build.version.incremental") + ':' +
+                    getString("ro.build.type") + '/' +
+                    getString("ro.build.tags");
+        }
+        return finger;
+    }
+
+    /**
+     * Ensure that raw fingerprint system property is defined. If it was derived
+     * dynamically by {@link #deriveFingerprint()} this is where we push the
+     * derived value into the property service.
+     *
+     * @hide
+     */
+    public static void ensureFingerprintProperty() {
+        if (TextUtils.isEmpty(SystemProperties.get("ro.build.fingerprint"))) {
+            try {
+                SystemProperties.set("ro.build.fingerprint", FINGERPRINT);
+            } catch (IllegalArgumentException e) {
+                Slog.e(TAG, "Failed to set fingerprint property", e);
+            }
+        }
+    }
 
     // The following properties only make sense for internal engineering builds.
     public static final long TIME = getLong("ro.build.date.utc") * 1000;
diff --git a/core/java/android/os/Bundle.java b/core/java/android/os/Bundle.java
index af57507..c85e418 100644
--- a/core/java/android/os/Bundle.java
+++ b/core/java/android/os/Bundle.java
@@ -17,7 +17,6 @@
 package android.os;
 
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.SparseArray;
 
 import java.io.Serializable;
@@ -29,47 +28,25 @@
  * A mapping from String values to various Parcelable types.
  *
  */
-public final class Bundle implements Parcelable, Cloneable {
-    private static final String TAG = "Bundle";
-    static final boolean DEBUG = false;
+public final class Bundle extends CommonBundle {
     public static final Bundle EMPTY;
-
-    static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
     static final Parcel EMPTY_PARCEL;
 
     static {
         EMPTY = new Bundle();
         EMPTY.mMap = ArrayMap.EMPTY;
-        EMPTY_PARCEL = Parcel.obtain();
+        EMPTY_PARCEL = CommonBundle.EMPTY_PARCEL;
     }
 
-    // Invariant - exactly one of mMap / mParcelledData will be null
-    // (except inside a call to unparcel)
-
-    /* package */ ArrayMap<String, Object> mMap = null;
-
-    /*
-     * If mParcelledData is non-null, then mMap will be null and the
-     * data are stored as a Parcel containing a Bundle.  When the data
-     * are unparcelled, mParcelledData willbe set to null.
-     */
-    /* package */ Parcel mParcelledData = null;
-
     private boolean mHasFds = false;
     private boolean mFdsKnown = true;
     private boolean mAllowFds = true;
 
     /**
-     * The ClassLoader used when unparcelling data from mParcelledData.
-     */
-    private ClassLoader mClassLoader;
-
-    /**
      * Constructs a new, empty Bundle.
      */
     public Bundle() {
-        mMap = new ArrayMap<String, Object>();
-        mClassLoader = getClass().getClassLoader();
+        super();
     }
 
     /**
@@ -79,11 +56,17 @@
      * @param parcelledData a Parcel containing a Bundle
      */
     Bundle(Parcel parcelledData) {
-        readFromParcel(parcelledData);
+        super(parcelledData);
+
+        mHasFds = mParcelledData.hasFileDescriptors();
+        mFdsKnown = true;
     }
 
     /* package */ Bundle(Parcel parcelledData, int length) {
-        readFromParcelInner(parcelledData, length);
+        super(parcelledData, length);
+
+        mHasFds = mParcelledData.hasFileDescriptors();
+        mFdsKnown = true;
     }
 
     /**
@@ -94,8 +77,7 @@
      * inside of the Bundle.
      */
     public Bundle(ClassLoader loader) {
-        mMap = new ArrayMap<String, Object>();
-        mClassLoader = loader;
+        super(loader);
     }
 
     /**
@@ -105,8 +87,7 @@
      * @param capacity the initial capacity of the Bundle
      */
     public Bundle(int capacity) {
-        mMap = new ArrayMap<String, Object>(capacity);
-        mClassLoader = getClass().getClassLoader();
+        super(capacity);
     }
 
     /**
@@ -116,27 +97,20 @@
      * @param b a Bundle to be copied.
      */
     public Bundle(Bundle b) {
-        if (b.mParcelledData != null) {
-            if (b.mParcelledData == EMPTY_PARCEL) {
-                mParcelledData = EMPTY_PARCEL;
-            } else {
-                mParcelledData = Parcel.obtain();
-                mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
-                mParcelledData.setDataPosition(0);
-            }
-        } else {
-            mParcelledData = null;
-        }
-
-        if (b.mMap != null) {
-            mMap = new ArrayMap<String, Object>(b.mMap);
-        } else {
-            mMap = null;
-        }
+        super(b);
 
         mHasFds = b.mHasFds;
         mFdsKnown = b.mFdsKnown;
-        mClassLoader = b.mClassLoader;
+    }
+
+    /**
+     * Constructs a Bundle containing a copy of the mappings from the given
+     * PersistableBundle.
+     *
+     * @param b a Bundle to be copied.
+     */
+    public Bundle(PersistableBundle b) {
+        super(b);
     }
 
     /**
@@ -145,37 +119,17 @@
      * @hide
      */
     public static Bundle forPair(String key, String value) {
-        // TODO: optimize this case.
         Bundle b = new Bundle(1);
         b.putString(key, value);
         return b;
     }
 
     /**
-     * TODO: optimize this later (getting just the value part of a Bundle
-     * with a single pair) once Bundle.forPair() above is implemented
-     * with a special single-value Map implementation/serialization.
-     *
-     * Note: value in single-pair Bundle may be null.
-     *
      * @hide
      */
+    @Override
     public String getPairValue() {
-        unparcel();
-        int size = mMap.size();
-        if (size > 1) {
-            Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
-        }
-        if (size == 0) {
-            return null;
-        }
-        Object o = mMap.valueAt(0);
-        try {
-            return (String) o;
-        } catch (ClassCastException e) {
-            typeWarning("getPairValue()", o, "String", e);
-            return null;
-        }
+        return super.getPairValue();
     }
 
     /**
@@ -184,15 +138,17 @@
      * @param loader An explicit ClassLoader to use when instantiating objects
      * inside of the Bundle.
      */
+    @Override
     public void setClassLoader(ClassLoader loader) {
-        mClassLoader = loader;
+        super.setClassLoader(loader);
     }
 
     /**
      * Return the ClassLoader currently associated with this Bundle.
      */
+    @Override
     public ClassLoader getClassLoader() {
-        return mClassLoader;
+        return super.getClassLoader();
     }
 
     /** @hide */
@@ -212,52 +168,11 @@
     }
 
     /**
-     * If the underlying data are stored as a Parcel, unparcel them
-     * using the currently assigned class loader.
-     */
-    /* package */ synchronized void unparcel() {
-        if (mParcelledData == null) {
-            if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
-                    + ": no parcelled data");
-            return;
-        }
-
-        if (mParcelledData == EMPTY_PARCEL) {
-            if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
-                    + ": empty");
-            if (mMap == null) {
-                mMap = new ArrayMap<String, Object>(1);
-            } else {
-                mMap.erase();
-            }
-            mParcelledData = null;
-            return;
-        }
-
-        int N = mParcelledData.readInt();
-        if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
-                + ": reading " + N + " maps");
-        if (N < 0) {
-            return;
-        }
-        if (mMap == null) {
-            mMap = new ArrayMap<String, Object>(N);
-        } else {
-            mMap.erase();
-            mMap.ensureCapacity(N);
-        }
-        mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
-        mParcelledData.recycle();
-        mParcelledData = null;
-        if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
-                + " final map: " + mMap);
-    }
-
-    /**
      * @hide
      */
+    @Override
     public boolean isParcelled() {
-        return mParcelledData != null;
+        return super.isParcelled();
     }
 
     /**
@@ -265,25 +180,26 @@
      *
      * @return the number of mappings as an int.
      */
+    @Override
     public int size() {
-        unparcel();
-        return mMap.size();
+        return super.size();
     }
 
     /**
      * Returns true if the mapping of this Bundle is empty, false otherwise.
      */
+    @Override
     public boolean isEmpty() {
-        unparcel();
-        return mMap.isEmpty();
+        return super.isEmpty();
     }
 
     /**
      * Removes all elements from the mapping of this Bundle.
      */
+    @Override
     public void clear() {
-        unparcel();
-        mMap.clear();
+        super.clear();
+
         mHasFds = false;
         mFdsKnown = true;
     }
@@ -295,9 +211,9 @@
      * @param key a String key
      * @return true if the key is part of the mapping, false otherwise
      */
+    @Override
     public boolean containsKey(String key) {
-        unparcel();
-        return mMap.containsKey(key);
+        return super.containsKey(key);
     }
 
     /**
@@ -306,9 +222,9 @@
      * @param key a String key
      * @return an Object, or null
      */
+    @Override
     public Object get(String key) {
-        unparcel();
-        return mMap.get(key);
+        return super.get(key);
     }
 
     /**
@@ -316,24 +232,33 @@
      *
      * @param key a String key
      */
+    @Override
     public void remove(String key) {
-        unparcel();
-        mMap.remove(key);
+        super.remove(key);
     }
 
     /**
      * Inserts all mappings from the given Bundle into this Bundle.
      *
-     * @param map a Bundle
+     * @param bundle a Bundle
      */
-    public void putAll(Bundle map) {
+    public void putAll(Bundle bundle) {
         unparcel();
-        map.unparcel();
-        mMap.putAll(map.mMap);
+        bundle.unparcel();
+        mMap.putAll(bundle.mMap);
 
         // fd state is now known if and only if both bundles already knew
-        mHasFds |= map.mHasFds;
-        mFdsKnown = mFdsKnown && map.mFdsKnown;
+        mHasFds |= bundle.mHasFds;
+        mFdsKnown = mFdsKnown && bundle.mFdsKnown;
+    }
+
+    /**
+     * Inserts all mappings from the given PersistableBundle into this Bundle.
+     *
+     * @param bundle a PersistableBundle
+     */
+    public void putAll(PersistableBundle bundle) {
+        super.putAll(bundle);
     }
 
     /**
@@ -341,9 +266,9 @@
      *
      * @return a Set of String keys
      */
+    @Override
     public Set<String> keySet() {
-        unparcel();
-        return mMap.keySet();
+        return super.keySet();
     }
 
     /**
@@ -352,7 +277,7 @@
     public boolean hasFileDescriptors() {
         if (!mFdsKnown) {
             boolean fdFound = false;    // keep going until we find one or run out of data
-            
+
             if (mParcelledData != null) {
                 if (mParcelledData.hasFileDescriptors()) {
                     fdFound = true;
@@ -390,8 +315,7 @@
                         ArrayList array = (ArrayList) obj;
                         // an ArrayList here might contain either Strings or
                         // Parcelables; only look inside for Parcelables
-                        if ((array.size() > 0)
-                                && (array.get(0) instanceof Parcelable)) {
+                        if (!array.isEmpty() && (array.get(0) instanceof Parcelable)) {
                             for (int n = array.size() - 1; n >= 0; n--) {
                                 Parcelable p = (Parcelable) array.get(n);
                                 if (p != null && ((p.describeContents()
@@ -410,7 +334,7 @@
         }
         return mHasFds;
     }
-    
+
     /**
      * Inserts a Boolean value into the mapping of this Bundle, replacing
      * any existing value for the given key.  Either key or value may be null.
@@ -418,9 +342,9 @@
      * @param key a String, or null
      * @param value a Boolean, or null
      */
+    @Override
     public void putBoolean(String key, boolean value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putBoolean(key, value);
     }
 
     /**
@@ -430,9 +354,9 @@
      * @param key a String, or null
      * @param value a byte
      */
+    @Override
     public void putByte(String key, byte value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putByte(key, value);
     }
 
     /**
@@ -442,9 +366,9 @@
      * @param key a String, or null
      * @param value a char, or null
      */
+    @Override
     public void putChar(String key, char value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putChar(key, value);
     }
 
     /**
@@ -454,9 +378,9 @@
      * @param key a String, or null
      * @param value a short
      */
+    @Override
     public void putShort(String key, short value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putShort(key, value);
     }
 
     /**
@@ -466,9 +390,9 @@
      * @param key a String, or null
      * @param value an int, or null
      */
+    @Override
     public void putInt(String key, int value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putInt(key, value);
     }
 
     /**
@@ -478,9 +402,9 @@
      * @param key a String, or null
      * @param value a long
      */
+    @Override
     public void putLong(String key, long value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putLong(key, value);
     }
 
     /**
@@ -490,9 +414,9 @@
      * @param key a String, or null
      * @param value a float
      */
+    @Override
     public void putFloat(String key, float value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putFloat(key, value);
     }
 
     /**
@@ -502,9 +426,9 @@
      * @param key a String, or null
      * @param value a double
      */
+    @Override
     public void putDouble(String key, double value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putDouble(key, value);
     }
 
     /**
@@ -514,9 +438,9 @@
      * @param key a String, or null
      * @param value a String, or null
      */
+    @Override
     public void putString(String key, String value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putString(key, value);
     }
 
     /**
@@ -526,9 +450,9 @@
      * @param key a String, or null
      * @param value a CharSequence, or null
      */
+    @Override
     public void putCharSequence(String key, CharSequence value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putCharSequence(key, value);
     }
 
     /**
@@ -567,7 +491,7 @@
      * @param value an ArrayList of Parcelable objects, or null
      */
     public void putParcelableArrayList(String key,
-        ArrayList<? extends Parcelable> value) {
+            ArrayList<? extends Parcelable> value) {
         unparcel();
         mMap.put(key, value);
         mFdsKnown = false;
@@ -602,9 +526,9 @@
      * @param key a String, or null
      * @param value an ArrayList<Integer> object, or null
      */
+    @Override
     public void putIntegerArrayList(String key, ArrayList<Integer> value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putIntegerArrayList(key, value);
     }
 
     /**
@@ -614,9 +538,9 @@
      * @param key a String, or null
      * @param value an ArrayList<String> object, or null
      */
+    @Override
     public void putStringArrayList(String key, ArrayList<String> value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putStringArrayList(key, value);
     }
 
     /**
@@ -626,9 +550,9 @@
      * @param key a String, or null
      * @param value an ArrayList<CharSequence> object, or null
      */
+    @Override
     public void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putCharSequenceArrayList(key, value);
     }
 
     /**
@@ -638,9 +562,9 @@
      * @param key a String, or null
      * @param value a Serializable object, or null
      */
+    @Override
     public void putSerializable(String key, Serializable value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putSerializable(key, value);
     }
 
     /**
@@ -650,9 +574,9 @@
      * @param key a String, or null
      * @param value a boolean array object, or null
      */
+    @Override
     public void putBooleanArray(String key, boolean[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putBooleanArray(key, value);
     }
 
     /**
@@ -662,9 +586,9 @@
      * @param key a String, or null
      * @param value a byte array object, or null
      */
+    @Override
     public void putByteArray(String key, byte[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putByteArray(key, value);
     }
 
     /**
@@ -674,9 +598,9 @@
      * @param key a String, or null
      * @param value a short array object, or null
      */
+    @Override
     public void putShortArray(String key, short[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putShortArray(key, value);
     }
 
     /**
@@ -686,9 +610,9 @@
      * @param key a String, or null
      * @param value a char array object, or null
      */
+    @Override
     public void putCharArray(String key, char[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putCharArray(key, value);
     }
 
     /**
@@ -698,9 +622,9 @@
      * @param key a String, or null
      * @param value an int array object, or null
      */
+    @Override
     public void putIntArray(String key, int[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putIntArray(key, value);
     }
 
     /**
@@ -710,9 +634,9 @@
      * @param key a String, or null
      * @param value a long array object, or null
      */
+    @Override
     public void putLongArray(String key, long[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putLongArray(key, value);
     }
 
     /**
@@ -722,9 +646,9 @@
      * @param key a String, or null
      * @param value a float array object, or null
      */
+    @Override
     public void putFloatArray(String key, float[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putFloatArray(key, value);
     }
 
     /**
@@ -734,9 +658,9 @@
      * @param key a String, or null
      * @param value a double array object, or null
      */
+    @Override
     public void putDoubleArray(String key, double[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putDoubleArray(key, value);
     }
 
     /**
@@ -746,9 +670,9 @@
      * @param key a String, or null
      * @param value a String array object, or null
      */
+    @Override
     public void putStringArray(String key, String[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putStringArray(key, value);
     }
 
     /**
@@ -758,9 +682,9 @@
      * @param key a String, or null
      * @param value a CharSequence array object, or null
      */
+    @Override
     public void putCharSequenceArray(String key, CharSequence[] value) {
-        unparcel();
-        mMap.put(key, value);
+        super.putCharSequenceArray(key, value);
     }
 
     /**
@@ -776,6 +700,17 @@
     }
 
     /**
+     * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a Bundle object, or null
+     */
+    public void putPersistableBundle(String key, PersistableBundle value) {
+        super.putPersistableBundle(key, value);
+    }
+
+    /**
      * Inserts an {@link IBinder} value into the mapping of this Bundle, replacing
      * any existing value for the given key.  Either key or value may be null.
      *
@@ -817,33 +752,9 @@
      * @param key a String
      * @return a boolean value
      */
+    @Override
     public boolean getBoolean(String key) {
-        unparcel();
-        if (DEBUG) Log.d(TAG, "Getting boolean in "
-                + Integer.toHexString(System.identityHashCode(this)));
-        return getBoolean(key, false);
-    }
-
-    // Log a message if the value was non-null but not of the expected type
-    private void typeWarning(String key, Object value, String className,
-        Object defaultValue, ClassCastException e) {
-        StringBuilder sb = new StringBuilder();
-        sb.append("Key ");
-        sb.append(key);
-        sb.append(" expected ");
-        sb.append(className);
-        sb.append(" but value was a ");
-        sb.append(value.getClass().getName());
-        sb.append(".  The default value ");
-        sb.append(defaultValue);
-        sb.append(" was returned.");
-        Log.w(TAG, sb.toString());
-        Log.w(TAG, "Attempt to cast generated internal exception:", e);
-    }
-
-    private void typeWarning(String key, Object value, String className,
-        ClassCastException e) {
-        typeWarning(key, value, className, "<null>", e);
+        return super.getBoolean(key);
     }
 
     /**
@@ -854,18 +765,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a boolean value
      */
+    @Override
     public boolean getBoolean(String key, boolean defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Boolean) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Boolean", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getBoolean(key, defaultValue);
     }
 
     /**
@@ -875,9 +777,9 @@
      * @param key a String
      * @return a byte value
      */
+    @Override
     public byte getByte(String key) {
-        unparcel();
-        return getByte(key, (byte) 0);
+        return super.getByte(key);
     }
 
     /**
@@ -888,18 +790,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a byte value
      */
+    @Override
     public Byte getByte(String key, byte defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Byte) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Byte", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getByte(key, defaultValue);
     }
 
     /**
@@ -909,9 +802,9 @@
      * @param key a String
      * @return a char value
      */
+    @Override
     public char getChar(String key) {
-        unparcel();
-        return getChar(key, (char) 0);
+        return super.getChar(key);
     }
 
     /**
@@ -922,18 +815,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a char value
      */
+    @Override
     public char getChar(String key, char defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Character) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Character", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getChar(key, defaultValue);
     }
 
     /**
@@ -943,9 +827,9 @@
      * @param key a String
      * @return a short value
      */
+    @Override
     public short getShort(String key) {
-        unparcel();
-        return getShort(key, (short) 0);
+        return super.getShort(key);
     }
 
     /**
@@ -956,18 +840,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a short value
      */
+    @Override
     public short getShort(String key, short defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Short) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Short", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getShort(key, defaultValue);
     }
 
     /**
@@ -977,9 +852,9 @@
      * @param key a String
      * @return an int value
      */
+    @Override
     public int getInt(String key) {
-        unparcel();
-        return getInt(key, 0);
+        return super.getInt(key);
     }
 
     /**
@@ -990,18 +865,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return an int value
      */
+    @Override
     public int getInt(String key, int defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Integer) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Integer", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getInt(key, defaultValue);
     }
 
     /**
@@ -1011,9 +877,9 @@
      * @param key a String
      * @return a long value
      */
+    @Override
     public long getLong(String key) {
-        unparcel();
-        return getLong(key, 0L);
+        return super.getLong(key);
     }
 
     /**
@@ -1024,18 +890,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a long value
      */
+    @Override
     public long getLong(String key, long defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Long) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Long", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getLong(key, defaultValue);
     }
 
     /**
@@ -1045,9 +902,9 @@
      * @param key a String
      * @return a float value
      */
+    @Override
     public float getFloat(String key) {
-        unparcel();
-        return getFloat(key, 0.0f);
+        return super.getFloat(key);
     }
 
     /**
@@ -1058,18 +915,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a float value
      */
+    @Override
     public float getFloat(String key, float defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Float) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Float", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getFloat(key, defaultValue);
     }
 
     /**
@@ -1079,9 +927,9 @@
      * @param key a String
      * @return a double value
      */
+    @Override
     public double getDouble(String key) {
-        unparcel();
-        return getDouble(key, 0.0);
+        return super.getDouble(key);
     }
 
     /**
@@ -1092,18 +940,9 @@
      * @param defaultValue Value to return if key does not exist
      * @return a double value
      */
+    @Override
     public double getDouble(String key, double defaultValue) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return defaultValue;
-        }
-        try {
-            return (Double) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Double", defaultValue, e);
-            return defaultValue;
-        }
+        return super.getDouble(key, defaultValue);
     }
 
     /**
@@ -1114,15 +953,9 @@
      * @param key a String, or null
      * @return a String value, or null
      */
+    @Override
     public String getString(String key) {
-        unparcel();
-        final Object o = mMap.get(key);
-        try {
-            return (String) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "String", e);
-            return null;
-        }
+        return super.getString(key);
     }
 
     /**
@@ -1134,9 +967,9 @@
      * @return the String value associated with the given key, or defaultValue
      *     if no valid String object is currently mapped to that key.
      */
+    @Override
     public String getString(String key, String defaultValue) {
-        final String s = getString(key);
-        return (s == null) ? defaultValue : s;
+        return super.getString(key, defaultValue);
     }
 
     /**
@@ -1147,15 +980,9 @@
      * @param key a String, or null
      * @return a CharSequence value, or null
      */
+    @Override
     public CharSequence getCharSequence(String key) {
-        unparcel();
-        final Object o = mMap.get(key);
-        try {
-            return (CharSequence) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "CharSequence", e);
-            return null;
-        }
+        return super.getCharSequence(key);
     }
 
     /**
@@ -1167,9 +994,9 @@
      * @return the CharSequence value associated with the given key, or defaultValue
      *     if no valid CharSequence object is currently mapped to that key.
      */
+    @Override
     public CharSequence getCharSequence(String key, CharSequence defaultValue) {
-        final CharSequence cs = getCharSequence(key);
-        return (cs == null) ? defaultValue : cs;
+        return super.getCharSequence(key, defaultValue);
     }
 
     /**
@@ -1200,6 +1027,18 @@
      * value is explicitly associated with the key.
      *
      * @param key a String, or null
+     * @return a PersistableBundle value, or null
+     */
+    public PersistableBundle getPersistableBundle(String key) {
+        return super.getPersistableBundle(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
      * @return a Parcelable value, or null
      */
     public <T extends Parcelable> T getParcelable(String key) {
@@ -1291,18 +1130,9 @@
      * @param key a String, or null
      * @return a Serializable value, or null
      */
+    @Override
     public Serializable getSerializable(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (Serializable) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "Serializable", e);
-            return null;
-        }
+        return super.getSerializable(key);
     }
 
     /**
@@ -1313,18 +1143,9 @@
      * @param key a String, or null
      * @return an ArrayList<String> value, or null
      */
+    @Override
     public ArrayList<Integer> getIntegerArrayList(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (ArrayList<Integer>) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "ArrayList<Integer>", e);
-            return null;
-        }
+        return super.getIntegerArrayList(key);
     }
 
     /**
@@ -1335,18 +1156,9 @@
      * @param key a String, or null
      * @return an ArrayList<String> value, or null
      */
+    @Override
     public ArrayList<String> getStringArrayList(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (ArrayList<String>) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "ArrayList<String>", e);
-            return null;
-        }
+        return super.getStringArrayList(key);
     }
 
     /**
@@ -1357,18 +1169,9 @@
      * @param key a String, or null
      * @return an ArrayList<CharSequence> value, or null
      */
+    @Override
     public ArrayList<CharSequence> getCharSequenceArrayList(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (ArrayList<CharSequence>) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "ArrayList<CharSequence>", e);
-            return null;
-        }
+        return super.getCharSequenceArrayList(key);
     }
 
     /**
@@ -1379,18 +1182,9 @@
      * @param key a String, or null
      * @return a boolean[] value, or null
      */
+    @Override
     public boolean[] getBooleanArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (boolean[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "byte[]", e);
-            return null;
-        }
+        return super.getBooleanArray(key);
     }
 
     /**
@@ -1401,18 +1195,9 @@
      * @param key a String, or null
      * @return a byte[] value, or null
      */
+    @Override
     public byte[] getByteArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (byte[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "byte[]", e);
-            return null;
-        }
+        return super.getByteArray(key);
     }
 
     /**
@@ -1423,18 +1208,9 @@
      * @param key a String, or null
      * @return a short[] value, or null
      */
+    @Override
     public short[] getShortArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (short[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "short[]", e);
-            return null;
-        }
+        return super.getShortArray(key);
     }
 
     /**
@@ -1445,18 +1221,9 @@
      * @param key a String, or null
      * @return a char[] value, or null
      */
+    @Override
     public char[] getCharArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (char[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "char[]", e);
-            return null;
-        }
+        return super.getCharArray(key);
     }
 
     /**
@@ -1467,18 +1234,9 @@
      * @param key a String, or null
      * @return an int[] value, or null
      */
+    @Override
     public int[] getIntArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (int[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "int[]", e);
-            return null;
-        }
+        return super.getIntArray(key);
     }
 
     /**
@@ -1489,18 +1247,9 @@
      * @param key a String, or null
      * @return a long[] value, or null
      */
+    @Override
     public long[] getLongArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (long[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "long[]", e);
-            return null;
-        }
+        return super.getLongArray(key);
     }
 
     /**
@@ -1511,18 +1260,9 @@
      * @param key a String, or null
      * @return a float[] value, or null
      */
+    @Override
     public float[] getFloatArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (float[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "float[]", e);
-            return null;
-        }
+        return super.getFloatArray(key);
     }
 
     /**
@@ -1533,18 +1273,9 @@
      * @param key a String, or null
      * @return a double[] value, or null
      */
+    @Override
     public double[] getDoubleArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (double[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "double[]", e);
-            return null;
-        }
+        return super.getDoubleArray(key);
     }
 
     /**
@@ -1555,18 +1286,9 @@
      * @param key a String, or null
      * @return a String[] value, or null
      */
+    @Override
     public String[] getStringArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (String[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "String[]", e);
-            return null;
-        }
+        return super.getStringArray(key);
     }
 
     /**
@@ -1577,18 +1299,9 @@
      * @param key a String, or null
      * @return a CharSequence[] value, or null
      */
+    @Override
     public CharSequence[] getCharSequenceArray(String key) {
-        unparcel();
-        Object o = mMap.get(key);
-        if (o == null) {
-            return null;
-        }
-        try {
-            return (CharSequence[]) o;
-        } catch (ClassCastException e) {
-            typeWarning(key, o, "CharSequence[]", e);
-            return null;
-        }
+        return super.getCharSequenceArray(key);
     }
 
     /**
@@ -1641,10 +1354,12 @@
 
     public static final Parcelable.Creator<Bundle> CREATOR =
         new Parcelable.Creator<Bundle>() {
+        @Override
         public Bundle createFromParcel(Parcel in) {
             return in.readBundle();
         }
 
+        @Override
         public Bundle[] newArray(int size) {
             return new Bundle[size];
         }
@@ -1653,6 +1368,7 @@
     /**
      * Report the nature of this Parcelable's contents
      */
+    @Override
     public int describeContents() {
         int mask = 0;
         if (hasFileDescriptors()) {
@@ -1660,44 +1376,17 @@
         }
         return mask;
     }
-    
+
     /**
      * Writes the Bundle contents to a Parcel, typically in order for
      * it to be passed through an IBinder connection.
      * @param parcel The parcel to copy this bundle to.
      */
+    @Override
     public void writeToParcel(Parcel parcel, int flags) {
         final boolean oldAllowFds = parcel.pushAllowFds(mAllowFds);
         try {
-            if (mParcelledData != null) {
-                if (mParcelledData == EMPTY_PARCEL) {
-                    parcel.writeInt(0);
-                } else {
-                    int length = mParcelledData.dataSize();
-                    parcel.writeInt(length);
-                    parcel.writeInt(BUNDLE_MAGIC);
-                    parcel.appendFrom(mParcelledData, 0, length);
-                }
-            } else {
-                // Special case for empty bundles.
-                if (mMap == null || mMap.size() <= 0) {
-                    parcel.writeInt(0);
-                    return;
-                }
-                int lengthPos = parcel.dataPosition();
-                parcel.writeInt(-1); // dummy, will hold length
-                parcel.writeInt(BUNDLE_MAGIC);
-    
-                int startPos = parcel.dataPosition();
-                parcel.writeArrayMapInternal(mMap);
-                int endPos = parcel.dataPosition();
-    
-                // Backpatch length
-                parcel.setDataPosition(lengthPos);
-                int length = endPos - startPos;
-                parcel.writeInt(length);
-                parcel.setDataPosition(endPos);
-            }
+            super.writeToParcelInner(parcel, flags);
         } finally {
             parcel.restoreAllowFds(oldAllowFds);
         }
@@ -1709,41 +1398,8 @@
      * @param parcel The parcel to overwrite this bundle from.
      */
     public void readFromParcel(Parcel parcel) {
-        int length = parcel.readInt();
-        if (length < 0) {
-            throw new RuntimeException("Bad length in parcel: " + length);
-        }
-        readFromParcelInner(parcel, length);
-    }
-
-    void readFromParcelInner(Parcel parcel, int length) {
-        if (length == 0) {
-            // Empty Bundle or end of data.
-            mParcelledData = EMPTY_PARCEL;
-            mHasFds = false;
-            mFdsKnown = true;
-            return;
-        }
-        int magic = parcel.readInt();
-        if (magic != BUNDLE_MAGIC) {
-            //noinspection ThrowableInstanceNeverThrown
-            throw new IllegalStateException("Bad magic number for Bundle: 0x"
-                    + Integer.toHexString(magic));
-        }
-
-        // Advance within this Parcel
-        int offset = parcel.dataPosition();
-        parcel.setDataPosition(offset + length);
-
-        Parcel p = Parcel.obtain();
-        p.setDataPosition(0);
-        p.appendFrom(parcel, offset, length);
-        if (DEBUG) Log.d(TAG, "Retrieving "  + Integer.toHexString(System.identityHashCode(this))
-                + ": " + length + " bundle bytes starting at " + offset);
-        p.setDataPosition(0);
-
-        mParcelledData = p;
-        mHasFds = p.hasFileDescriptors();
+        super.readFromParcelInner(parcel);
+        mHasFds = mParcelledData.hasFileDescriptors();
         mFdsKnown = true;
     }
 
@@ -1759,4 +1415,5 @@
         }
         return "Bundle[" + mMap.toString() + "]";
     }
+
 }
diff --git a/core/java/android/os/CommonBundle.java b/core/java/android/os/CommonBundle.java
new file mode 100644
index 0000000..e11f170
--- /dev/null
+++ b/core/java/android/os/CommonBundle.java
@@ -0,0 +1,1384 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.ArrayMap;
+import android.util.Log;
+import android.util.SparseArray;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * A mapping from String values to various types.
+ */
+abstract class CommonBundle implements Parcelable, Cloneable {
+    private static final String TAG = "Bundle";
+    static final boolean DEBUG = false;
+
+    static final int BUNDLE_MAGIC = 0x4C444E42; // 'B' 'N' 'D' 'L'
+    static final Parcel EMPTY_PARCEL;
+
+    static {
+        EMPTY_PARCEL = Parcel.obtain();
+    }
+
+    // Invariant - exactly one of mMap / mParcelledData will be null
+    // (except inside a call to unparcel)
+
+    ArrayMap<String, Object> mMap = null;
+
+    /*
+     * If mParcelledData is non-null, then mMap will be null and the
+     * data are stored as a Parcel containing a Bundle.  When the data
+     * are unparcelled, mParcelledData willbe set to null.
+     */
+    Parcel mParcelledData = null;
+
+    /**
+     * The ClassLoader used when unparcelling data from mParcelledData.
+     */
+    private ClassLoader mClassLoader;
+
+    /**
+     * Constructs a new, empty Bundle that uses a specific ClassLoader for
+     * instantiating Parcelable and Serializable objects.
+     *
+     * @param loader An explicit ClassLoader to use when instantiating objects
+     * inside of the Bundle.
+     * @param capacity Initial size of the ArrayMap.
+     */
+    CommonBundle(ClassLoader loader, int capacity) {
+        mMap = capacity > 0 ?
+                new ArrayMap<String, Object>(capacity) : new ArrayMap<String, Object>();
+        mClassLoader = loader == null ? getClass().getClassLoader() : loader;
+    }
+
+    /**
+     * Constructs a new, empty Bundle.
+     */
+    CommonBundle() {
+        this((ClassLoader) null, 0);
+    }
+
+    /**
+     * Constructs a Bundle whose data is stored as a Parcel.  The data
+     * will be unparcelled on first contact, using the assigned ClassLoader.
+     *
+     * @param parcelledData a Parcel containing a Bundle
+     */
+    CommonBundle(Parcel parcelledData) {
+        readFromParcelInner(parcelledData);
+    }
+
+    CommonBundle(Parcel parcelledData, int length) {
+        readFromParcelInner(parcelledData, length);
+    }
+
+    /**
+     * Constructs a new, empty Bundle that uses a specific ClassLoader for
+     * instantiating Parcelable and Serializable objects.
+     *
+     * @param loader An explicit ClassLoader to use when instantiating objects
+     * inside of the Bundle.
+     */
+    CommonBundle(ClassLoader loader) {
+        this(loader, 0);
+    }
+
+    /**
+     * Constructs a new, empty Bundle sized to hold the given number of
+     * elements. The Bundle will grow as needed.
+     *
+     * @param capacity the initial capacity of the Bundle
+     */
+    CommonBundle(int capacity) {
+        this((ClassLoader) null, capacity);
+    }
+
+    /**
+     * Constructs a Bundle containing a copy of the mappings from the given
+     * Bundle.
+     *
+     * @param b a Bundle to be copied.
+     */
+    CommonBundle(CommonBundle b) {
+        if (b.mParcelledData != null) {
+            if (b.mParcelledData == EMPTY_PARCEL) {
+                mParcelledData = EMPTY_PARCEL;
+            } else {
+                mParcelledData = Parcel.obtain();
+                mParcelledData.appendFrom(b.mParcelledData, 0, b.mParcelledData.dataSize());
+                mParcelledData.setDataPosition(0);
+            }
+        } else {
+            mParcelledData = null;
+        }
+
+        if (b.mMap != null) {
+            mMap = new ArrayMap<String, Object>(b.mMap);
+        } else {
+            mMap = null;
+        }
+
+        mClassLoader = b.mClassLoader;
+    }
+
+    /**
+     * TODO: optimize this later (getting just the value part of a Bundle
+     * with a single pair) once Bundle.forPair() above is implemented
+     * with a special single-value Map implementation/serialization.
+     *
+     * Note: value in single-pair Bundle may be null.
+     *
+     * @hide
+     */
+    String getPairValue() {
+        unparcel();
+        int size = mMap.size();
+        if (size > 1) {
+            Log.w(TAG, "getPairValue() used on Bundle with multiple pairs.");
+        }
+        if (size == 0) {
+            return null;
+        }
+        Object o = mMap.valueAt(0);
+        try {
+            return (String) o;
+        } catch (ClassCastException e) {
+            typeWarning("getPairValue()", o, "String", e);
+            return null;
+        }
+    }
+
+    /**
+     * Changes the ClassLoader this Bundle uses when instantiating objects.
+     *
+     * @param loader An explicit ClassLoader to use when instantiating objects
+     * inside of the Bundle.
+     */
+    void setClassLoader(ClassLoader loader) {
+        mClassLoader = loader;
+    }
+
+    /**
+     * Return the ClassLoader currently associated with this Bundle.
+     */
+    ClassLoader getClassLoader() {
+        return mClassLoader;
+    }
+
+    /**
+     * If the underlying data are stored as a Parcel, unparcel them
+     * using the currently assigned class loader.
+     */
+    /* package */ synchronized void unparcel() {
+        if (mParcelledData == null) {
+            if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+                    + ": no parcelled data");
+            return;
+        }
+
+        if (mParcelledData == EMPTY_PARCEL) {
+            if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+                    + ": empty");
+            if (mMap == null) {
+                mMap = new ArrayMap<String, Object>(1);
+            } else {
+                mMap.erase();
+            }
+            mParcelledData = null;
+            return;
+        }
+
+        int N = mParcelledData.readInt();
+        if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+                + ": reading " + N + " maps");
+        if (N < 0) {
+            return;
+        }
+        if (mMap == null) {
+            mMap = new ArrayMap<String, Object>(N);
+        } else {
+            mMap.erase();
+            mMap.ensureCapacity(N);
+        }
+        mParcelledData.readArrayMapInternal(mMap, N, mClassLoader);
+        mParcelledData.recycle();
+        mParcelledData = null;
+        if (DEBUG) Log.d(TAG, "unparcel " + Integer.toHexString(System.identityHashCode(this))
+                + " final map: " + mMap);
+    }
+
+    /**
+     * @hide
+     */
+    boolean isParcelled() {
+        return mParcelledData != null;
+    }
+
+    /**
+     * Returns the number of mappings contained in this Bundle.
+     *
+     * @return the number of mappings as an int.
+     */
+    int size() {
+        unparcel();
+        return mMap.size();
+    }
+
+    /**
+     * Returns true if the mapping of this Bundle is empty, false otherwise.
+     */
+    boolean isEmpty() {
+        unparcel();
+        return mMap.isEmpty();
+    }
+
+    /**
+     * Removes all elements from the mapping of this Bundle.
+     */
+    void clear() {
+        unparcel();
+        mMap.clear();
+    }
+
+    /**
+     * Returns true if the given key is contained in the mapping
+     * of this Bundle.
+     *
+     * @param key a String key
+     * @return true if the key is part of the mapping, false otherwise
+     */
+    boolean containsKey(String key) {
+        unparcel();
+        return mMap.containsKey(key);
+    }
+
+    /**
+     * Returns the entry with the given key as an object.
+     *
+     * @param key a String key
+     * @return an Object, or null
+     */
+    Object get(String key) {
+        unparcel();
+        return mMap.get(key);
+    }
+
+    /**
+     * Removes any entry with the given key from the mapping of this Bundle.
+     *
+     * @param key a String key
+     */
+    void remove(String key) {
+        unparcel();
+        mMap.remove(key);
+    }
+
+    /**
+     * Inserts all mappings from the given PersistableBundle into this CommonBundle.
+     *
+     * @param bundle a PersistableBundle
+     */
+    void putAll(PersistableBundle bundle) {
+        unparcel();
+        bundle.unparcel();
+        mMap.putAll(bundle.mMap);
+    }
+
+    /**
+     * Returns a Set containing the Strings used as keys in this Bundle.
+     *
+     * @return a Set of String keys
+     */
+    Set<String> keySet() {
+        unparcel();
+        return mMap.keySet();
+    }
+
+    /**
+     * Inserts a Boolean value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a Boolean, or null
+     */
+    void putBoolean(String key, boolean value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a byte value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a byte
+     */
+    void putByte(String key, byte value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a char value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a char, or null
+     */
+    void putChar(String key, char value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a short value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a short
+     */
+    void putShort(String key, short value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts an int value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value an int, or null
+     */
+    void putInt(String key, int value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a long value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a long
+     */
+    void putLong(String key, long value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a float value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a float
+     */
+    void putFloat(String key, float value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a double value into the mapping of this Bundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a double
+     */
+    void putDouble(String key, double value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a String value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a String, or null
+     */
+    void putString(String key, String value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a CharSequence value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a CharSequence, or null
+     */
+    void putCharSequence(String key, CharSequence value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts an ArrayList<Integer> value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value an ArrayList<Integer> object, or null
+     */
+    void putIntegerArrayList(String key, ArrayList<Integer> value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts an ArrayList<String> value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value an ArrayList<String> object, or null
+     */
+    void putStringArrayList(String key, ArrayList<String> value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts an ArrayList<CharSequence> value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value an ArrayList<CharSequence> object, or null
+     */
+    void putCharSequenceArrayList(String key, ArrayList<CharSequence> value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a Serializable value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a Serializable object, or null
+     */
+    void putSerializable(String key, Serializable value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a boolean array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a boolean array object, or null
+     */
+    void putBooleanArray(String key, boolean[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a byte array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a byte array object, or null
+     */
+    void putByteArray(String key, byte[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a short array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a short array object, or null
+     */
+    void putShortArray(String key, short[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a char array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a char array object, or null
+     */
+    void putCharArray(String key, char[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts an int array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value an int array object, or null
+     */
+    void putIntArray(String key, int[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a long array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a long array object, or null
+     */
+    void putLongArray(String key, long[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a float array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a float array object, or null
+     */
+    void putFloatArray(String key, float[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a double array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a double array object, or null
+     */
+    void putDoubleArray(String key, double[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a String array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a String array object, or null
+     */
+    void putStringArray(String key, String[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a CharSequence array value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a CharSequence array object, or null
+     */
+    void putCharSequenceArray(String key, CharSequence[] value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a Bundle object, or null
+     */
+    void putPersistableBundle(String key, PersistableBundle value) {
+        unparcel();
+        mMap.put(key, value);
+    }
+
+    /**
+     * Returns the value associated with the given key, or false if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a boolean value
+     */
+    boolean getBoolean(String key) {
+        unparcel();
+        if (DEBUG) Log.d(TAG, "Getting boolean in "
+                + Integer.toHexString(System.identityHashCode(this)));
+        return getBoolean(key, false);
+    }
+
+    // Log a message if the value was non-null but not of the expected type
+    void typeWarning(String key, Object value, String className,
+            Object defaultValue, ClassCastException e) {
+        StringBuilder sb = new StringBuilder();
+        sb.append("Key ");
+        sb.append(key);
+        sb.append(" expected ");
+        sb.append(className);
+        sb.append(" but value was a ");
+        sb.append(value.getClass().getName());
+        sb.append(".  The default value ");
+        sb.append(defaultValue);
+        sb.append(" was returned.");
+        Log.w(TAG, sb.toString());
+        Log.w(TAG, "Attempt to cast generated internal exception:", e);
+    }
+
+    void typeWarning(String key, Object value, String className,
+            ClassCastException e) {
+        typeWarning(key, value, className, "<null>", e);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a boolean value
+     */
+    boolean getBoolean(String key, boolean defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Boolean) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Boolean", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or (byte) 0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a byte value
+     */
+    byte getByte(String key) {
+        unparcel();
+        return getByte(key, (byte) 0);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a byte value
+     */
+    Byte getByte(String key, byte defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Byte) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Byte", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or (char) 0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a char value
+     */
+    char getChar(String key) {
+        unparcel();
+        return getChar(key, (char) 0);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a char value
+     */
+    char getChar(String key, char defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Character) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Character", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or (short) 0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a short value
+     */
+    short getShort(String key) {
+        unparcel();
+        return getShort(key, (short) 0);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a short value
+     */
+    short getShort(String key, short defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Short) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Short", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return an int value
+     */
+    int getInt(String key) {
+        unparcel();
+        return getInt(key, 0);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return an int value
+     */
+    int getInt(String key, int defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Integer) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Integer", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0L if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a long value
+     */
+    long getLong(String key) {
+        unparcel();
+        return getLong(key, 0L);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a long value
+     */
+    long getLong(String key, long defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Long) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Long", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0.0f if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a float value
+     */
+    float getFloat(String key) {
+        unparcel();
+        return getFloat(key, 0.0f);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a float value
+     */
+    float getFloat(String key, float defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Float) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Float", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0.0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a double value
+     */
+    double getDouble(String key) {
+        unparcel();
+        return getDouble(key, 0.0);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a double value
+     */
+    double getDouble(String key, double defaultValue) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return defaultValue;
+        }
+        try {
+            return (Double) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Double", defaultValue, e);
+            return defaultValue;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a String value, or null
+     */
+    String getString(String key) {
+        unparcel();
+        final Object o = mMap.get(key);
+        try {
+            return (String) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "String", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String, or null
+     * @param defaultValue Value to return if key does not exist
+     * @return the String value associated with the given key, or defaultValue
+     *     if no valid String object is currently mapped to that key.
+     */
+    String getString(String key, String defaultValue) {
+        final String s = getString(key);
+        return (s == null) ? defaultValue : s;
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a CharSequence value, or null
+     */
+    CharSequence getCharSequence(String key) {
+        unparcel();
+        final Object o = mMap.get(key);
+        try {
+            return (CharSequence) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "CharSequence", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String, or null
+     * @param defaultValue Value to return if key does not exist
+     * @return the CharSequence value associated with the given key, or defaultValue
+     *     if no valid CharSequence object is currently mapped to that key.
+     */
+    CharSequence getCharSequence(String key, CharSequence defaultValue) {
+        final CharSequence cs = getCharSequence(key);
+        return (cs == null) ? defaultValue : cs;
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a Bundle value, or null
+     */
+    PersistableBundle getPersistableBundle(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (PersistableBundle) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Bundle", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a Serializable value, or null
+     */
+    Serializable getSerializable(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (Serializable) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "Serializable", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return an ArrayList<String> value, or null
+     */
+    ArrayList<Integer> getIntegerArrayList(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (ArrayList<Integer>) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "ArrayList<Integer>", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return an ArrayList<String> value, or null
+     */
+    ArrayList<String> getStringArrayList(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (ArrayList<String>) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "ArrayList<String>", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return an ArrayList<CharSequence> value, or null
+     */
+    ArrayList<CharSequence> getCharSequenceArrayList(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (ArrayList<CharSequence>) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "ArrayList<CharSequence>", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a boolean[] value, or null
+     */
+    boolean[] getBooleanArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (boolean[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "byte[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a byte[] value, or null
+     */
+    byte[] getByteArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (byte[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "byte[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a short[] value, or null
+     */
+    short[] getShortArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (short[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "short[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a char[] value, or null
+     */
+    char[] getCharArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (char[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "char[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return an int[] value, or null
+     */
+    int[] getIntArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (int[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "int[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a long[] value, or null
+     */
+    long[] getLongArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (long[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "long[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a float[] value, or null
+     */
+    float[] getFloatArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (float[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "float[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a double[] value, or null
+     */
+    double[] getDoubleArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (double[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "double[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a String[] value, or null
+     */
+    String[] getStringArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (String[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "String[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a CharSequence[] value, or null
+     */
+    CharSequence[] getCharSequenceArray(String key) {
+        unparcel();
+        Object o = mMap.get(key);
+        if (o == null) {
+            return null;
+        }
+        try {
+            return (CharSequence[]) o;
+        } catch (ClassCastException e) {
+            typeWarning(key, o, "CharSequence[]", e);
+            return null;
+        }
+    }
+
+    /**
+     * Writes the Bundle contents to a Parcel, typically in order for
+     * it to be passed through an IBinder connection.
+     * @param parcel The parcel to copy this bundle to.
+     */
+    void writeToParcelInner(Parcel parcel, int flags) {
+        if (mParcelledData != null) {
+            if (mParcelledData == EMPTY_PARCEL) {
+                parcel.writeInt(0);
+            } else {
+                int length = mParcelledData.dataSize();
+                parcel.writeInt(length);
+                parcel.writeInt(BUNDLE_MAGIC);
+                parcel.appendFrom(mParcelledData, 0, length);
+            }
+        } else {
+            // Special case for empty bundles.
+            if (mMap == null || mMap.size() <= 0) {
+                parcel.writeInt(0);
+                return;
+            }
+            int lengthPos = parcel.dataPosition();
+            parcel.writeInt(-1); // dummy, will hold length
+            parcel.writeInt(BUNDLE_MAGIC);
+
+            int startPos = parcel.dataPosition();
+            parcel.writeArrayMapInternal(mMap);
+            int endPos = parcel.dataPosition();
+
+            // Backpatch length
+            parcel.setDataPosition(lengthPos);
+            int length = endPos - startPos;
+            parcel.writeInt(length);
+            parcel.setDataPosition(endPos);
+        }
+    }
+
+    /**
+     * Reads the Parcel contents into this Bundle, typically in order for
+     * it to be passed through an IBinder connection.
+     * @param parcel The parcel to overwrite this bundle from.
+     */
+    void readFromParcelInner(Parcel parcel) {
+        int length = parcel.readInt();
+        if (length < 0) {
+            throw new RuntimeException("Bad length in parcel: " + length);
+        }
+        readFromParcelInner(parcel, length);
+    }
+
+    private void readFromParcelInner(Parcel parcel, int length) {
+        if (length == 0) {
+            // Empty Bundle or end of data.
+            mParcelledData = EMPTY_PARCEL;
+            return;
+        }
+        int magic = parcel.readInt();
+        if (magic != BUNDLE_MAGIC) {
+            //noinspection ThrowableInstanceNeverThrown
+            throw new IllegalStateException("Bad magic number for Bundle: 0x"
+                    + Integer.toHexString(magic));
+        }
+
+        // Advance within this Parcel
+        int offset = parcel.dataPosition();
+        parcel.setDataPosition(offset + length);
+
+        Parcel p = Parcel.obtain();
+        p.setDataPosition(0);
+        p.appendFrom(parcel, offset, length);
+        if (DEBUG) Log.d(TAG, "Retrieving "  + Integer.toHexString(System.identityHashCode(this))
+                + ": " + length + " bundle bytes starting at " + offset);
+        p.setDataPosition(0);
+
+        mParcelledData = p;
+    }
+}
diff --git a/core/java/android/os/CommonClock.java b/core/java/android/os/CommonClock.java
index 2ecf317..f83a90b 100644
--- a/core/java/android/os/CommonClock.java
+++ b/core/java/android/os/CommonClock.java
@@ -23,6 +23,7 @@
 import android.os.Parcel;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import static android.system.OsConstants.*;
 
 /**
  * Used for accessing the android common time service's common clock and receiving notifications
diff --git a/core/java/android/os/CommonTimeUtils.java b/core/java/android/os/CommonTimeUtils.java
index 20755d9..ba060b8 100644
--- a/core/java/android/os/CommonTimeUtils.java
+++ b/core/java/android/os/CommonTimeUtils.java
@@ -20,7 +20,7 @@
 import java.net.Inet6Address;
 import java.net.InetSocketAddress;
 import java.util.Locale;
-import static libcore.io.OsConstants.*;
+import static android.system.OsConstants.*;
 
 class CommonTimeUtils {
     /**
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index e96398a..e98a26b 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -42,6 +42,7 @@
     private static final String ENV_SECONDARY_STORAGE = "SECONDARY_STORAGE";
     private static final String ENV_ANDROID_ROOT = "ANDROID_ROOT";
     private static final String ENV_OEM_ROOT = "OEM_ROOT";
+    private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -57,6 +58,7 @@
 
     private static final File DIR_ANDROID_ROOT = getDirectory(ENV_ANDROID_ROOT, "/system");
     private static final File DIR_OEM_ROOT = getDirectory(ENV_OEM_ROOT, "/oem");
+    private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_MEDIA_STORAGE = getDirectory(ENV_MEDIA_STORAGE, "/data/media");
 
     private static final String CANONCIAL_EMULATED_STORAGE_TARGET = getCanonicalPathOrNull(
@@ -225,6 +227,15 @@
     }
 
     /**
+     * Return root directory of the "vendor" partition that holds vendor-provided
+     * software that should persist across simple reflashing of the "system" partition.
+     * @hide
+     */
+    public static File getVendorDirectory() {
+        return DIR_VENDOR_ROOT;
+    }
+
+    /**
      * Gets the system directory available for secure storage.
      * If Encrypted File system is enabled, it returns an encrypted directory (/data/secure/system).
      * Otherwise, it returns the unencrypted /data/system directory.
diff --git a/core/java/android/os/FileUtils.java b/core/java/android/os/FileUtils.java
index dc18dee..d71c3e6 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -16,12 +16,12 @@
 
 package android.os;
 
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.Log;
 import android.util.Slog;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -85,7 +85,7 @@
      */
     public static int setPermissions(String path, int mode, int uid, int gid) {
         try {
-            Libcore.os.chmod(path, mode);
+            Os.chmod(path, mode);
         } catch (ErrnoException e) {
             Slog.w(TAG, "Failed to chmod(" + path + "): " + e);
             return e.errno;
@@ -93,7 +93,7 @@
 
         if (uid >= 0 || gid >= 0) {
             try {
-                Libcore.os.chown(path, uid, gid);
+                Os.chown(path, uid, gid);
             } catch (ErrnoException e) {
                 Slog.w(TAG, "Failed to chown(" + path + "): " + e);
                 return e.errno;
@@ -113,7 +113,7 @@
      */
     public static int setPermissions(FileDescriptor fd, int mode, int uid, int gid) {
         try {
-            Libcore.os.fchmod(fd, mode);
+            Os.fchmod(fd, mode);
         } catch (ErrnoException e) {
             Slog.w(TAG, "Failed to fchmod(): " + e);
             return e.errno;
@@ -121,7 +121,7 @@
 
         if (uid >= 0 || gid >= 0) {
             try {
-                Libcore.os.fchown(fd, uid, gid);
+                Os.fchown(fd, uid, gid);
             } catch (ErrnoException e) {
                 Slog.w(TAG, "Failed to fchown(): " + e);
                 return e.errno;
@@ -136,7 +136,7 @@
      */
     public static int getUid(String path) {
         try {
-            return Libcore.os.stat(path).st_uid;
+            return Os.stat(path).st_uid;
         } catch (ErrnoException e) {
             return -1;
         }
@@ -370,8 +370,8 @@
      * attacks.
      */
     public static boolean contains(File dir, File file) {
-        String dirPath = dir.getPath();
-        String filePath = file.getPath();
+        String dirPath = dir.getAbsolutePath();
+        String filePath = file.getAbsolutePath();
 
         if (dirPath.equals(filePath)) {
             return true;
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index be3c0cc..6c7b08d 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -40,8 +40,8 @@
     void wakeUp(long time);
     void goToSleep(long time, int reason);
     void nap(long time);
+    boolean isInteractive();
 
-    boolean isScreenOn();
     void reboot(boolean confirm, String reason, boolean wait);
     void shutdown(boolean confirm, boolean wait);
     void crash(String message);
diff --git a/core/java/android/os/IUserManager.aidl b/core/java/android/os/IUserManager.aidl
index 1192a45..899a958 100644
--- a/core/java/android/os/IUserManager.aidl
+++ b/core/java/android/os/IUserManager.aidl
@@ -29,12 +29,13 @@
 interface IUserManager {
     UserInfo createUser(in String name, int flags);
     UserInfo createProfileForUser(in String name, int flags, int userHandle);
+    void setUserEnabled(int userHandle);
     boolean removeUser(int userHandle);
     void setUserName(int userHandle, String name);
     void setUserIcon(int userHandle, in Bitmap icon);
     Bitmap getUserIcon(int userHandle);
     List<UserInfo> getUsers(boolean excludeDying);
-    List<UserInfo> getProfiles(int userHandle);
+    List<UserInfo> getProfiles(int userHandle, boolean enabledOnly);
     UserInfo getUserInfo(int userHandle);
     boolean isRestricted();
     void setGuestEnabled(boolean enable);
diff --git a/core/java/android/os/IVibratorService.aidl b/core/java/android/os/IVibratorService.aidl
index 4854bc0..4d05e2d 100644
--- a/core/java/android/os/IVibratorService.aidl
+++ b/core/java/android/os/IVibratorService.aidl
@@ -20,8 +20,8 @@
 interface IVibratorService
 {
     boolean hasVibrator();
-    void vibrate(int uid, String packageName, long milliseconds, int streamHint, IBinder token);
-    void vibratePattern(int uid, String packageName, in long[] pattern, int repeat, int streamHint, IBinder token);
+    void vibrate(int uid, String opPkg, long milliseconds, int streamHint, IBinder token);
+    void vibratePattern(int uid, String opPkg, in long[] pattern, int repeat, int streamHint, IBinder token);
     void cancelVibrate(IBinder token);
 }
 
diff --git a/core/java/android/os/NullVibrator.java b/core/java/android/os/NullVibrator.java
index 536da32..7b870ac 100644
--- a/core/java/android/os/NullVibrator.java
+++ b/core/java/android/os/NullVibrator.java
@@ -40,7 +40,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
         vibrate(milliseconds);
     }
 
@@ -48,7 +48,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+    public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
             int streamHint) {
         if (repeat >= pattern.length) {
             throw new ArrayIndexOutOfBoundsException();
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 8e0ff08..95cb9f3 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -223,6 +223,7 @@
     private static final int VAL_SPARSEBOOLEANARRAY = 22;
     private static final int VAL_BOOLEANARRAY = 23;
     private static final int VAL_CHARSEQUENCEARRAY = 24;
+    private static final int VAL_PERSISTABLEBUNDLE = 25;
 
     // The initial int32 in a Binder call's reply Parcel header:
     private static final int EX_SECURITY = -1;
@@ -638,6 +639,19 @@
     }
 
     /**
+     * Flatten a PersistableBundle into the parcel at the current dataPosition(),
+     * growing dataCapacity() if needed.
+     */
+    public final void writePersistableBundle(PersistableBundle val) {
+        if (val == null) {
+            writeInt(-1);
+            return;
+        }
+
+        val.writeToParcel(this, 0);
+    }
+
+    /**
      * Flatten a List into the parcel at the current dataPosition(), growing
      * dataCapacity() if needed.  The List values are written using
      * {@link #writeValue} and must follow the specification there.
@@ -1256,6 +1270,9 @@
         } else if (v instanceof Byte) {
             writeInt(VAL_BYTE);
             writeInt((Byte) v);
+        } else if (v instanceof PersistableBundle) {
+            writeInt(VAL_PERSISTABLEBUNDLE);
+            writePersistableBundle((PersistableBundle) v);
         } else {
             Class<?> clazz = v.getClass();
             if (clazz.isArray() && clazz.getComponentType() == Object.class) {
@@ -1633,6 +1650,35 @@
     }
 
     /**
+     * Read and return a new Bundle object from the parcel at the current
+     * dataPosition().  Returns null if the previously written Bundle object was
+     * null.
+     */
+    public final PersistableBundle readPersistableBundle() {
+        return readPersistableBundle(null);
+    }
+
+    /**
+     * Read and return a new Bundle object from the parcel at the current
+     * dataPosition(), using the given class loader to initialize the class
+     * loader of the Bundle for later retrieval of Parcelable objects.
+     * Returns null if the previously written Bundle object was null.
+     */
+    public final PersistableBundle readPersistableBundle(ClassLoader loader) {
+        int length = readInt();
+        if (length < 0) {
+            if (Bundle.DEBUG) Log.d(TAG, "null bundle: length=" + length);
+            return null;
+        }
+
+        final PersistableBundle bundle = new PersistableBundle(this, length);
+        if (loader != null) {
+            bundle.setClassLoader(loader);
+        }
+        return bundle;
+    }
+
+    /**
      * Read and return a byte[] object from the parcel.
      */
     public final byte[] createByteArray() {
@@ -2082,6 +2128,9 @@
         case VAL_BUNDLE:
             return readBundle(loader); // loading will be deferred
 
+        case VAL_PERSISTABLEBUNDLE:
+            return readPersistableBundle(loader);
+
         default:
             int off = dataPosition() - 4;
             throw new RuntimeException(
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index 86dc8b4..c6b2151 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -16,24 +16,24 @@
 
 package android.os;
 
-import static libcore.io.OsConstants.AF_UNIX;
-import static libcore.io.OsConstants.SEEK_SET;
-import static libcore.io.OsConstants.SOCK_STREAM;
-import static libcore.io.OsConstants.S_ISLNK;
-import static libcore.io.OsConstants.S_ISREG;
+import static android.system.OsConstants.AF_UNIX;
+import static android.system.OsConstants.SEEK_SET;
+import static android.system.OsConstants.SOCK_STREAM;
+import static android.system.OsConstants.S_ISLNK;
+import static android.system.OsConstants.S_ISREG;
 
 import android.content.BroadcastReceiver;
 import android.content.ContentProvider;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
+import android.system.StructStat;
 import android.util.Log;
 
 import dalvik.system.CloseGuard;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 import libcore.io.Memory;
-import libcore.io.OsConstants;
-import libcore.io.StructStat;
 
 import java.io.Closeable;
 import java.io.File;
@@ -42,6 +42,7 @@
 import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InterruptedIOException;
 import java.net.DatagramSocket;
 import java.net.Socket;
 import java.nio.ByteOrder;
@@ -260,7 +261,7 @@
      */
     public static ParcelFileDescriptor dup(FileDescriptor orig) throws IOException {
         try {
-            final FileDescriptor fd = Libcore.os.dup(orig);
+            final FileDescriptor fd = Os.dup(orig);
             return new ParcelFileDescriptor(fd);
         } catch (ErrnoException e) {
             throw e.rethrowAsIOException();
@@ -296,7 +297,7 @@
         original.setInt$(fd);
 
         try {
-            final FileDescriptor dup = Libcore.os.dup(original);
+            final FileDescriptor dup = Os.dup(original);
             return new ParcelFileDescriptor(dup);
         } catch (ErrnoException e) {
             throw e.rethrowAsIOException();
@@ -358,7 +359,7 @@
      */
     public static ParcelFileDescriptor[] createPipe() throws IOException {
         try {
-            final FileDescriptor[] fds = Libcore.os.pipe();
+            final FileDescriptor[] fds = Os.pipe();
             return new ParcelFileDescriptor[] {
                     new ParcelFileDescriptor(fds[0]),
                     new ParcelFileDescriptor(fds[1]) };
@@ -380,7 +381,7 @@
     public static ParcelFileDescriptor[] createReliablePipe() throws IOException {
         try {
             final FileDescriptor[] comm = createCommSocketPair();
-            final FileDescriptor[] fds = Libcore.os.pipe();
+            final FileDescriptor[] fds = Os.pipe();
             return new ParcelFileDescriptor[] {
                     new ParcelFileDescriptor(fds[0], comm[0]),
                     new ParcelFileDescriptor(fds[1], comm[1]) };
@@ -397,7 +398,7 @@
         try {
             final FileDescriptor fd0 = new FileDescriptor();
             final FileDescriptor fd1 = new FileDescriptor();
-            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
+            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
             return new ParcelFileDescriptor[] {
                     new ParcelFileDescriptor(fd0),
                     new ParcelFileDescriptor(fd1) };
@@ -420,7 +421,7 @@
             final FileDescriptor[] comm = createCommSocketPair();
             final FileDescriptor fd0 = new FileDescriptor();
             final FileDescriptor fd1 = new FileDescriptor();
-            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
+            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, fd0, fd1);
             return new ParcelFileDescriptor[] {
                     new ParcelFileDescriptor(fd0, comm[0]),
                     new ParcelFileDescriptor(fd1, comm[1]) };
@@ -433,7 +434,7 @@
         try {
             final FileDescriptor comm1 = new FileDescriptor();
             final FileDescriptor comm2 = new FileDescriptor();
-            Libcore.os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
+            Os.socketpair(AF_UNIX, SOCK_STREAM, 0, comm1, comm2);
             IoUtils.setBlocking(comm1, false);
             IoUtils.setBlocking(comm2, false);
             return new FileDescriptor[] { comm1, comm2 };
@@ -519,7 +520,7 @@
             return mWrapped.getStatSize();
         } else {
             try {
-                final StructStat st = Libcore.os.fstat(mFd);
+                final StructStat st = Os.fstat(mFd);
                 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
                     return st.st_size;
                 } else {
@@ -542,7 +543,7 @@
             return mWrapped.seekTo(pos);
         } else {
             try {
-                return Libcore.os.lseek(mFd, pos, SEEK_SET);
+                return Os.lseek(mFd, pos, SEEK_SET);
             } catch (ErrnoException e) {
                 throw e.rethrowAsIOException();
             }
@@ -694,10 +695,13 @@
                     writePtr += len;
                 }
 
-                Libcore.os.write(mCommFd, buf, 0, writePtr);
+                Os.write(mCommFd, buf, 0, writePtr);
             } catch (ErrnoException e) {
                 // Reporting status is best-effort
                 Log.w(TAG, "Failed to report status: " + e);
+            } catch (InterruptedIOException e) {
+                // Reporting status is best-effort
+                Log.w(TAG, "Failed to report status: " + e);
             }
 
         } finally {
@@ -708,7 +712,7 @@
 
     private static Status readCommStatus(FileDescriptor comm, byte[] buf) {
         try {
-            final int n = Libcore.os.read(comm, buf, 0, buf.length);
+            final int n = Os.read(comm, buf, 0, buf.length);
             if (n == 0) {
                 // EOF means they're dead
                 return new Status(Status.DEAD);
@@ -728,6 +732,9 @@
                 Log.d(TAG, "Failed to read status; assuming dead: " + e);
                 return new Status(Status.DEAD);
             }
+        } catch (InterruptedIOException e) {
+            Log.d(TAG, "Failed to read status; assuming dead: " + e);
+            return new Status(Status.DEAD);
         }
     }
 
diff --git a/core/java/android/os/PersistableBundle.java b/core/java/android/os/PersistableBundle.java
new file mode 100644
index 0000000..c2cd3be
--- /dev/null
+++ b/core/java/android/os/PersistableBundle.java
@@ -0,0 +1,555 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.util.ArrayMap;
+
+import java.util.Set;
+
+/**
+ * A mapping from String values to various types that can be saved to persistent and later
+ * restored.
+ *
+ */
+public final class PersistableBundle extends CommonBundle {
+    public static final PersistableBundle EMPTY;
+    static final Parcel EMPTY_PARCEL;
+
+    static {
+        EMPTY = new PersistableBundle();
+        EMPTY.mMap = ArrayMap.EMPTY;
+        EMPTY_PARCEL = CommonBundle.EMPTY_PARCEL;
+    }
+
+    /**
+     * Constructs a new, empty PersistableBundle.
+     */
+    public PersistableBundle() {
+        super();
+    }
+
+    /**
+     * Constructs a PersistableBundle whose data is stored as a Parcel.  The data
+     * will be unparcelled on first contact, using the assigned ClassLoader.
+     *
+     * @param parcelledData a Parcel containing a PersistableBundle
+     */
+    PersistableBundle(Parcel parcelledData) {
+        super(parcelledData);
+    }
+
+    /* package */ PersistableBundle(Parcel parcelledData, int length) {
+        super(parcelledData, length);
+    }
+
+    /**
+     * Constructs a new, empty PersistableBundle that uses a specific ClassLoader for
+     * instantiating Parcelable and Serializable objects.
+     *
+     * @param loader An explicit ClassLoader to use when instantiating objects
+     * inside of the PersistableBundle.
+     */
+    public PersistableBundle(ClassLoader loader) {
+        super(loader);
+    }
+
+    /**
+     * Constructs a new, empty PersistableBundle sized to hold the given number of
+     * elements. The PersistableBundle will grow as needed.
+     *
+     * @param capacity the initial capacity of the PersistableBundle
+     */
+    public PersistableBundle(int capacity) {
+        super(capacity);
+    }
+
+    /**
+     * Constructs a PersistableBundle containing a copy of the mappings from the given
+     * PersistableBundle.
+     *
+     * @param b a PersistableBundle to be copied.
+     */
+    public PersistableBundle(PersistableBundle b) {
+        super(b);
+    }
+
+    /**
+     * Make a PersistableBundle for a single key/value pair.
+     *
+     * @hide
+     */
+    public static PersistableBundle forPair(String key, String value) {
+        PersistableBundle b = new PersistableBundle(1);
+        b.putString(key, value);
+        return b;
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public String getPairValue() {
+        return super.getPairValue();
+    }
+
+    /**
+     * Changes the ClassLoader this PersistableBundle uses when instantiating objects.
+     *
+     * @param loader An explicit ClassLoader to use when instantiating objects
+     * inside of the PersistableBundle.
+     */
+    @Override
+    public void setClassLoader(ClassLoader loader) {
+        super.setClassLoader(loader);
+    }
+
+    /**
+     * Return the ClassLoader currently associated with this PersistableBundle.
+     */
+    @Override
+    public ClassLoader getClassLoader() {
+        return super.getClassLoader();
+    }
+
+    /**
+     * Clones the current PersistableBundle. The internal map is cloned, but the keys and
+     * values to which it refers are copied by reference.
+     */
+    @Override
+    public Object clone() {
+        return new PersistableBundle(this);
+    }
+
+    /**
+     * @hide
+     */
+    @Override
+    public boolean isParcelled() {
+        return super.isParcelled();
+    }
+
+    /**
+     * Returns the number of mappings contained in this PersistableBundle.
+     *
+     * @return the number of mappings as an int.
+     */
+    @Override
+    public int size() {
+        return super.size();
+    }
+
+    /**
+     * Returns true if the mapping of this PersistableBundle is empty, false otherwise.
+     */
+    @Override
+    public boolean isEmpty() {
+        return super.isEmpty();
+    }
+
+    /**
+     * Removes all elements from the mapping of this PersistableBundle.
+     */
+    @Override
+    public void clear() {
+        super.clear();
+    }
+
+    /**
+     * Returns true if the given key is contained in the mapping
+     * of this PersistableBundle.
+     *
+     * @param key a String key
+     * @return true if the key is part of the mapping, false otherwise
+     */
+    @Override
+    public boolean containsKey(String key) {
+        return super.containsKey(key);
+    }
+
+    /**
+     * Returns the entry with the given key as an object.
+     *
+     * @param key a String key
+     * @return an Object, or null
+     */
+    @Override
+    public Object get(String key) {
+        return super.get(key);
+    }
+
+    /**
+     * Removes any entry with the given key from the mapping of this PersistableBundle.
+     *
+     * @param key a String key
+     */
+    @Override
+    public void remove(String key) {
+        super.remove(key);
+    }
+
+    /**
+     * Inserts all mappings from the given PersistableBundle into this Bundle.
+     *
+     * @param bundle a PersistableBundle
+     */
+    public void putAll(PersistableBundle bundle) {
+        super.putAll(bundle);
+    }
+
+    /**
+     * Returns a Set containing the Strings used as keys in this PersistableBundle.
+     *
+     * @return a Set of String keys
+     */
+    @Override
+    public Set<String> keySet() {
+        return super.keySet();
+    }
+
+    /**
+     * Inserts an int value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value an int, or null
+     */
+    @Override
+    public void putInt(String key, int value) {
+        super.putInt(key, value);
+    }
+
+    /**
+     * Inserts a long value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a long
+     */
+    @Override
+    public void putLong(String key, long value) {
+        super.putLong(key, value);
+    }
+
+    /**
+     * Inserts a double value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.
+     *
+     * @param key a String, or null
+     * @param value a double
+     */
+    @Override
+    public void putDouble(String key, double value) {
+        super.putDouble(key, value);
+    }
+
+    /**
+     * Inserts a String value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a String, or null
+     */
+    @Override
+    public void putString(String key, String value) {
+        super.putString(key, value);
+    }
+
+    /**
+     * Inserts an int array value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value an int array object, or null
+     */
+    @Override
+    public void putIntArray(String key, int[] value) {
+        super.putIntArray(key, value);
+    }
+
+    /**
+     * Inserts a long array value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a long array object, or null
+     */
+    @Override
+    public void putLongArray(String key, long[] value) {
+        super.putLongArray(key, value);
+    }
+
+    /**
+     * Inserts a double array value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a double array object, or null
+     */
+    @Override
+    public void putDoubleArray(String key, double[] value) {
+        super.putDoubleArray(key, value);
+    }
+
+    /**
+     * Inserts a String array value into the mapping of this PersistableBundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a String array object, or null
+     */
+    @Override
+    public void putStringArray(String key, String[] value) {
+        super.putStringArray(key, value);
+    }
+
+    /**
+     * Inserts a PersistableBundle value into the mapping of this Bundle, replacing
+     * any existing value for the given key.  Either key or value may be null.
+     *
+     * @param key a String, or null
+     * @param value a Bundle object, or null
+     */
+    public void putPersistableBundle(String key, PersistableBundle value) {
+        super.putPersistableBundle(key, value);
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return an int value
+     */
+    @Override
+    public int getInt(String key) {
+        return super.getInt(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return an int value
+     */
+    @Override
+    public int getInt(String key, int defaultValue) {
+        return super.getInt(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0L if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a long value
+     */
+    @Override
+    public long getLong(String key) {
+        return super.getLong(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a long value
+     */
+    @Override
+    public long getLong(String key, long defaultValue) {
+        return super.getLong(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or 0.0 if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @return a double value
+     */
+    @Override
+    public double getDouble(String key) {
+        return super.getDouble(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String
+     * @param defaultValue Value to return if key does not exist
+     * @return a double value
+     */
+    @Override
+    public double getDouble(String key, double defaultValue) {
+        return super.getDouble(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a String value, or null
+     */
+    @Override
+    public String getString(String key) {
+        return super.getString(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or defaultValue if
+     * no mapping of the desired type exists for the given key.
+     *
+     * @param key a String, or null
+     * @param defaultValue Value to return if key does not exist
+     * @return the String value associated with the given key, or defaultValue
+     *     if no valid String object is currently mapped to that key.
+     */
+    @Override
+    public String getString(String key, String defaultValue) {
+        return super.getString(key, defaultValue);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a Bundle value, or null
+     */
+    @Override
+    public PersistableBundle getPersistableBundle(String key) {
+        return super.getPersistableBundle(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return an int[] value, or null
+     */
+    @Override
+    public int[] getIntArray(String key) {
+        return super.getIntArray(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a long[] value, or null
+     */
+    @Override
+    public long[] getLongArray(String key) {
+        return super.getLongArray(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a double[] value, or null
+     */
+    @Override
+    public double[] getDoubleArray(String key) {
+        return super.getDoubleArray(key);
+    }
+
+    /**
+     * Returns the value associated with the given key, or null if
+     * no mapping of the desired type exists for the given key or a null
+     * value is explicitly associated with the key.
+     *
+     * @param key a String, or null
+     * @return a String[] value, or null
+     */
+    @Override
+    public String[] getStringArray(String key) {
+        return super.getStringArray(key);
+    }
+
+    public static final Parcelable.Creator<PersistableBundle> CREATOR =
+            new Parcelable.Creator<PersistableBundle>() {
+                @Override
+                public PersistableBundle createFromParcel(Parcel in) {
+                    return in.readPersistableBundle();
+                }
+
+                @Override
+                public PersistableBundle[] newArray(int size) {
+                    return new PersistableBundle[size];
+                }
+            };
+
+    /**
+     * Report the nature of this Parcelable's contents
+     */
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Writes the PersistableBundle contents to a Parcel, typically in order for
+     * it to be passed through an IBinder connection.
+     * @param parcel The parcel to copy this bundle to.
+     */
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        final boolean oldAllowFds = parcel.pushAllowFds(false);
+        try {
+            super.writeToParcelInner(parcel, flags);
+        } finally {
+            parcel.restoreAllowFds(oldAllowFds);
+        }
+    }
+
+    /**
+     * Reads the Parcel contents into this PersistableBundle, typically in order for
+     * it to be passed through an IBinder connection.
+     * @param parcel The parcel to overwrite this bundle from.
+     */
+    public void readFromParcel(Parcel parcel) {
+        super.readFromParcelInner(parcel);
+    }
+
+    @Override
+    synchronized public String toString() {
+        if (mParcelledData != null) {
+            if (mParcelledData == EMPTY_PARCEL) {
+                return "PersistableBundle[EMPTY_PARCEL]";
+            } else {
+                return "PersistableBundle[mParcelledData.dataSize=" +
+                        mParcelledData.dataSize() + "]";
+            }
+        }
+        return "PersistableBundle[" + mMap.toString() + "]";
+    }
+
+}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a195200..f8d7c3e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -601,21 +601,64 @@
     }
 
     /**
-      * Returns whether the screen is currently on.
+      * Returns true if the device is in an interactive state.
       * <p>
-      * Only indicates whether the screen is on.  The screen could be either bright or dim.
+      * For historical reasons, the name of this method refers to the power state of
+      * the screen but it actually describes the overall interactive state of
+      * the device.  This method has been replaced by {@link #isInteractive}.
       * </p><p>
-      * {@samplecode
-      * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
-      * boolean isScreenOn = pm.isScreenOn();
-      * }
+      * The value returned by this method only indicates whether the device is
+      * in an interactive state which may have nothing to do with the screen being
+      * on or off.  To determine the actual state of the screen,
+      * use {@link android.view.Display#getState}.
       * </p>
       *
-      * @return whether the screen is on (bright or dim).
+      * @return True if the device is in an interactive state.
+      *
+      * @deprecated Use {@link #isInteractive} instead.
       */
+    @Deprecated
     public boolean isScreenOn() {
+        return isInteractive();
+    }
+
+    /**
+     * Returns true if the device is in an interactive state.
+     * <p>
+     * When this method returns true, the device is awake and ready to interact
+     * with the user (although this is not a guarantee that the user is actively
+     * interacting with the device just this moment).  The main screen is usually
+     * turned on while in this state.  Certain features, such as the proximity
+     * sensor, may temporarily turn off the screen while still leaving the device in an
+     * interactive state.  Note in particular that the device is still considered
+     * to be interactive while dreaming (since dreams can be interactive) but not
+     * when it is dozing or asleep.
+     * </p><p>
+     * When this method returns false, the device is dozing or asleep and must
+     * be awoken before it will become ready to interact with the user again.  The
+     * main screen is usually turned off while in this state.  Certain features,
+     * such as "ambient mode" may cause the main screen to remain on (albeit in a
+     * low power state) to display system-provided content while the device dozes.
+     * </p><p>
+     * The system will send a {@link android.content.Intent#ACTION_SCREEN_ON screen on}
+     * or {@link android.content.Intent#ACTION_SCREEN_OFF screen off} broadcast
+     * whenever the interactive state of the device changes.  For historical reasons,
+     * the names of these broadcasts refer to the power state of the screen
+     * but they are actually sent in response to changes in the overall interactive
+     * state of the device, as described by this method.
+     * </p><p>
+     * Services may use the non-interactive state as a hint to conserve power
+     * since the user is not present.
+     * </p>
+     *
+     * @return True if the device is in an interactive state.
+     *
+     * @see android.content.Intent#ACTION_SCREEN_ON
+     * @see android.content.Intent#ACTION_SCREEN_OFF
+     */
+    public boolean isInteractive() {
         try {
-            return mService.isScreenOn();
+            return mService.isInteractive();
         } catch (RemoteException e) {
             return false;
         }
diff --git a/core/java/android/os/Process.java b/core/java/android/os/Process.java
index 79ff49c..1b3aa0a 100644
--- a/core/java/android/os/Process.java
+++ b/core/java/android/os/Process.java
@@ -18,6 +18,7 @@
 
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
+import android.system.Os;
 import android.util.Log;
 import com.android.internal.os.Zygote;
 import java.io.BufferedWriter;
@@ -28,7 +29,6 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import libcore.io.Libcore;
 
 /*package*/ class ZygoteStartFailedEx extends Exception {
     /**
@@ -372,7 +372,7 @@
             for (int i = 0; i < tries; i++) {
                 if (i > 0) {
                     try {
-                        Log.i("Zygote", "Zygote not up yet, sleeping...");
+                        Log.i(LOG_TAG, "Zygote not up yet, sleeping...");
                         Thread.sleep(ZYGOTE_RETRY_MILLIS);
                     } catch (InterruptedException ex) {
                         throw new ZygoteStartFailedEx(ex);
@@ -466,6 +466,7 @@
      * @param debugFlags Additional flags.
      * @param targetSdkVersion The target SDK version for the app.
      * @param seInfo null-ok SELinux information for the new process.
+     * @param abi non-null the ABI this app should be started with.
      * @param zygoteArgs Additional arguments to supply to the zygote process.
      * 
      * @return An object that describes the result of the attempt to start the process.
@@ -479,12 +480,12 @@
                                   int debugFlags, int mountExternal,
                                   int targetSdkVersion,
                                   String seInfo,
+                                  String abi,
                                   String[] zygoteArgs) {
         try {
             return startViaZygote(processClass, niceName, uid, gid, gids,
                     debugFlags, mountExternal, targetSdkVersion, seInfo,
-                    null, /* zygoteAbi TODO: Replace this with the real ABI */
-                    zygoteArgs);
+                    abi, zygoteArgs);
         } catch (ZygoteStartFailedEx ex) {
             Log.e(LOG_TAG,
                     "Starting VM process through Zygote failed");
@@ -702,13 +703,6 @@
             primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET, getNumTries(primaryZygoteState));
         }
 
-        // TODO: Revert this temporary change. This is required to test
-        // and submit this change ahead of the package manager changes
-        // that supply this abi.
-        if (abi == null) {
-            return primaryZygoteState;
-        }
-
         if (primaryZygoteState.matches(abi)) {
             return primaryZygoteState;
         }
@@ -737,7 +731,7 @@
      * {@link #killProcess} and {@link #sendSignal}.
      */
     public static final int myPid() {
-        return Libcore.os.getpid();
+        return Os.getpid();
     }
 
     /**
@@ -745,7 +739,7 @@
      * @hide
      */
     public static final int myPpid() {
-        return Libcore.os.getppid();
+        return Os.getppid();
     }
 
     /**
@@ -753,7 +747,7 @@
      * {@link #setThreadPriority(int, int)}.
      */
     public static final int myTid() {
-        return Libcore.os.gettid();
+        return Os.gettid();
     }
 
     /**
@@ -763,7 +757,7 @@
      * a uid identifies a specific app sandbox in a specific user.
      */
     public static final int myUid() {
-        return Libcore.os.getuid();
+        return Os.getuid();
     }
 
     /**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index f671ed9..cdde4c7 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -375,6 +375,7 @@
         final ConditionVariable condition = new ConditionVariable();
 
         Intent intent = new Intent("android.intent.action.MASTER_CLEAR_NOTIFICATION");
+        intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
         context.sendOrderedBroadcastAsUser(intent, UserHandle.OWNER,
                 android.Manifest.permission.MASTER_CLEAR,
                 new BroadcastReceiver() {
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index 9e9521a..13e9a15 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -16,9 +16,9 @@
 
 package android.os;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructStatVfs;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStatVfs;
 
 /**
  * Retrieve overall information about the space on a filesystem. This is a
@@ -41,7 +41,7 @@
 
     private static StructStatVfs doStat(String path) {
         try {
-            return Libcore.os.statvfs(path);
+            return Os.statvfs(path);
         } catch (ErrnoException e) {
             throw new IllegalArgumentException("Invalid path: " + path, e);
         }
diff --git a/core/java/android/os/SystemVibrator.java b/core/java/android/os/SystemVibrator.java
index 13bc4f6..8d9cf54 100644
--- a/core/java/android/os/SystemVibrator.java
+++ b/core/java/android/os/SystemVibrator.java
@@ -58,13 +58,13 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long milliseconds, int streamHint) {
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint) {
         if (mService == null) {
             Log.w(TAG, "Failed to vibrate; no vibrator service.");
             return;
         }
         try {
-            mService.vibrate(owningUid, owningPackage, milliseconds, streamHint, mToken);
+            mService.vibrate(uid, opPkg, milliseconds, streamHint, mToken);
         } catch (RemoteException e) {
             Log.w(TAG, "Failed to vibrate.", e);
         }
@@ -74,7 +74,7 @@
      * @hide
      */
     @Override
-    public void vibrate(int owningUid, String owningPackage, long[] pattern, int repeat,
+    public void vibrate(int uid, String opPkg, long[] pattern, int repeat,
             int streamHint) {
         if (mService == null) {
             Log.w(TAG, "Failed to vibrate; no vibrator service.");
@@ -85,7 +85,7 @@
         // anyway
         if (repeat < pattern.length) {
             try {
-                mService.vibratePattern(owningUid, owningPackage, pattern, repeat, streamHint,
+                mService.vibratePattern(uid, opPkg, pattern, repeat, streamHint,
                         mToken);
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed to vibrate.", e);
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 728c560..1b2b798 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -336,7 +336,7 @@
     /**
      * @hide
      * Sets the value of a specific restriction on a specific user.
-     * Requires the {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Requires the MANAGE_USERS permission.
      * @param key the key of the restriction
      * @param value the value for the restriction
      * @param userHandle the user whose restriction is to be changed.
@@ -437,6 +437,22 @@
     }
 
     /**
+     * Sets the user as enabled, if such an user exists.
+     * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
+     * Note that the default is true, it's only that managed profiles might not be enabled.
+     *
+     * @param userHandle the id of the profile to enable
+     * @hide
+     */
+    public void setUserEnabled(int userHandle) {
+        try {
+            mService.setUserEnabled(userHandle);
+        } catch (RemoteException e) {
+            Log.w(TAG, "Could not enable the profile", e);
+        }
+    }
+
+    /**
      * Return the number of users currently created on the device.
      */
     public int getUserCount() {
@@ -462,6 +478,8 @@
     /**
      * Returns list of the profiles of userHandle including
      * userHandle itself.
+     * Note that it this returns both enabled and not enabled profiles. See
+     * {@link #getUserProfiles()} if you need only the enabled ones.
      *
      * Requires {@link android.Manifest.permission#MANAGE_USERS} permission.
      * @param userHandle profiles of this user will be returned.
@@ -470,7 +488,7 @@
      */
     public List<UserInfo> getProfiles(int userHandle) {
         try {
-            return mService.getProfiles(userHandle);
+            return mService.getProfiles(userHandle, false /* enabledOnly */);
         } catch (RemoteException re) {
             Log.w(TAG, "Could not get user list", re);
             return null;
@@ -484,7 +502,13 @@
      */
     public List<UserHandle> getUserProfiles() {
         ArrayList<UserHandle> profiles = new ArrayList<UserHandle>();
-        List<UserInfo> users = getProfiles(UserHandle.myUserId());
+        List<UserInfo> users = new ArrayList<UserInfo>();
+        try {
+            users = mService.getProfiles(UserHandle.myUserId(), true /* enabledOnly */);
+        } catch (RemoteException re) {
+            Log.w(TAG, "Could not get user list", re);
+            return null;
+        }
         for (UserInfo info : users) {
             UserHandle userHandle = new UserHandle(info.id);
             profiles.add(userHandle);
@@ -492,7 +516,20 @@
         return profiles;
     }
 
-    /** @hide */
+    /**
+     * If the target user is a managed profile of the calling user or the caller
+     * is itself a managed profile, then this returns a badged copy of the given
+     * icon to be able to distinguish it from the original icon.
+     * <P>
+     * If the original drawable is not a BitmapDrawable, then the original
+     * drawable is returned.
+     * </P>
+     *
+     * @param icon The icon to badge.
+     * @param user The target user.
+     * @return A drawable that combines the original icon and a badge as
+     *         determined by the system.
+     */
     public Drawable getBadgedDrawableForUser(Drawable icon, UserHandle user) {
         int badgeResId = getBadgeResIdForUser(user.getIdentifier());
         if (badgeResId == 0) {
diff --git a/core/java/android/os/Vibrator.java b/core/java/android/os/Vibrator.java
index 8845ba3..c1d4d4c 100644
--- a/core/java/android/os/Vibrator.java
+++ b/core/java/android/os/Vibrator.java
@@ -135,7 +135,7 @@
      * Like {@link #vibrate(long, int)}, but allowing the caller to specify that
      * the vibration is owned by someone else.
      */
-    public abstract void vibrate(int owningUid, String owningPackage,
+    public abstract void vibrate(int uid, String opPkg,
             long milliseconds, int streamHint);
 
     /**
@@ -143,7 +143,7 @@
      * Like {@link #vibrate(long[], int, int)}, but allowing the caller to specify that
      * the vibration is owned by someone else.
      */
-    public abstract void vibrate(int owningUid, String owningPackage,
+    public abstract void vibrate(int uid, String opPkg,
             long[] pattern, int repeat, int streamHint);
 
     /**
diff --git a/core/java/android/os/storage/IMountService.java b/core/java/android/os/storage/IMountService.java
index 2ef5b66..939cda9 100644
--- a/core/java/android/os/storage/IMountService.java
+++ b/core/java/android/os/storage/IMountService.java
@@ -625,12 +625,13 @@
                 return _result;
             }
 
-            public int encryptStorage(String password) throws RemoteException {
+            public int encryptStorage(int type, String password) throws RemoteException {
                 Parcel _data = Parcel.obtain();
                 Parcel _reply = Parcel.obtain();
                 int _result;
                 try {
                     _data.writeInterfaceToken(DESCRIPTOR);
+                    _data.writeInt(type);
                     _data.writeString(password);
                     mRemote.transact(Stub.TRANSACTION_encryptStorage, _data, _reply, 0);
                     _reply.readException();
@@ -1210,8 +1211,9 @@
                 }
                 case TRANSACTION_encryptStorage: {
                     data.enforceInterface(DESCRIPTOR);
+                    int type = data.readInt();
                     String password = data.readString();
-                    int result = encryptStorage(password);
+                    int result = encryptStorage(type, password);
                     reply.writeNoException();
                     reply.writeInt(result);
                     return true;
@@ -1495,7 +1497,7 @@
     /**
      * Encrypts storage.
      */
-    public int encryptStorage(String password) throws RemoteException;
+    public int encryptStorage(int type, String password) throws RemoteException;
 
     /**
      * Changes the encryption password.
diff --git a/core/java/android/preference/Preference.java b/core/java/android/preference/Preference.java
index 144c909..56d5617 100644
--- a/core/java/android/preference/Preference.java
+++ b/core/java/android/preference/Preference.java
@@ -533,8 +533,7 @@
      * @see #onCreateView(ViewGroup)
      */
     protected void onBindView(View view) {
-        final TextView titleView = (TextView) view.findViewById(
-                com.android.internal.R.id.title);
+        final TextView titleView = (TextView) view.findViewById(com.android.internal.R.id.title);
         if (titleView != null) {
             final CharSequence title = getTitle();
             if (!TextUtils.isEmpty(title)) {
@@ -557,7 +556,7 @@
             }
         }
 
-        ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
+        final ImageView imageView = (ImageView) view.findViewById(com.android.internal.R.id.icon);
         if (imageView != null) {
             if (mIconResId != 0 || mIcon != null) {
                 if (mIcon == null) {
@@ -570,6 +569,11 @@
             imageView.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
         }
 
+        final View imageFrame = view.findViewById(com.android.internal.R.id.icon_frame);
+        if (imageFrame != null) {
+            imageFrame.setVisibility(mIcon != null ? View.VISIBLE : View.GONE);
+        }
+
         if (mShouldDisableView) {
             setEnabledStateOnViews(view, isEnabled());
         }
diff --git a/core/java/android/preference/PreferenceFragment.java b/core/java/android/preference/PreferenceFragment.java
index 11d8878..ff16f6c 100644
--- a/core/java/android/preference/PreferenceFragment.java
+++ b/core/java/android/preference/PreferenceFragment.java
@@ -329,6 +329,11 @@
         if (preferenceScreen != null) {
             preferenceScreen.bind(getListView());
         }
+        onBindPreferences();
+    }
+
+    /** @hide */
+    protected void onBindPreferences() {
     }
 
     /** @hide */
@@ -337,6 +342,26 @@
         return mList;
     }
 
+    /** @hide */
+    public boolean hasListView() {
+        if (mList != null) {
+            return true;
+        }
+        View root = getView();
+        if (root == null) {
+            return false;
+        }
+        View rawListView = root.findViewById(android.R.id.list);
+        if (!(rawListView instanceof ListView)) {
+            return false;
+        }
+        mList = (ListView)rawListView;
+        if (mList == null) {
+            return false;
+        }
+        return true;
+    }
+
     private void ensureList() {
         if (mList != null) {
             return;
diff --git a/core/java/android/preference/PreferenceGroupAdapter.java b/core/java/android/preference/PreferenceGroupAdapter.java
index c2e1f51..381a5f0 100644
--- a/core/java/android/preference/PreferenceGroupAdapter.java
+++ b/core/java/android/preference/PreferenceGroupAdapter.java
@@ -20,6 +20,7 @@
 import java.util.Collections;
 import java.util.List;
 
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.preference.Preference.OnPreferenceChangeInternalListener;
 import android.view.View;
@@ -91,7 +92,8 @@
         }
     };
 
-    private int mActivatedPosition = -1;
+    private int mHighlightedPosition = -1;
+    private Drawable mHighlightedDrawable;
 
     private static class PreferenceLayout implements Comparable<PreferenceLayout> {
         private int resId;
@@ -212,8 +214,18 @@
         return this.getItem(position).getId();
     }
 
-    public void setActivated(int position) {
-        mActivatedPosition = position;
+    /**
+     * @hide
+     */
+    public void setHighlighted(int position) {
+        mHighlightedPosition = position;
+    }
+
+    /**
+     * @hide
+     */
+    public void setHighlightedDrawable(Drawable drawable) {
+        mHighlightedDrawable = drawable;
     }
 
     public View getView(int position, View convertView, ViewGroup parent) {
@@ -227,7 +239,10 @@
             convertView = null;
         }
         View result = preference.getView(convertView, parent);
-        result.setActivated(position == mActivatedPosition);
+        if (position == mHighlightedPosition && mHighlightedDrawable != null) {
+            result.setBackgroundDrawable(mHighlightedDrawable);
+        }
+        result.setTag(preference.getKey());
         return result;
     }
 
diff --git a/core/java/android/provider/DocumentsContract.java b/core/java/android/provider/DocumentsContract.java
index f0520b5..b907375 100644
--- a/core/java/android/provider/DocumentsContract.java
+++ b/core/java/android/provider/DocumentsContract.java
@@ -17,7 +17,7 @@
 package android.provider;
 
 import static android.net.TrafficStats.KB_IN_BYTES;
-import static libcore.io.OsConstants.SEEK_SET;
+import static android.system.OsConstants.SEEK_SET;
 
 import android.content.ContentProviderClient;
 import android.content.ContentResolver;
@@ -38,11 +38,11 @@
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.OnCloseListener;
 import android.os.RemoteException;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Log;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 import java.io.BufferedInputStream;
 import java.io.File;
@@ -57,6 +57,10 @@
  * <p>
  * To create a document provider, extend {@link DocumentsProvider}, which
  * provides a foundational implementation of this contract.
+ * <p>
+ * All client apps must hold a valid URI permission grant to access documents,
+ * typically issued when a user makes a selection through
+ * {@link Intent#ACTION_OPEN_DOCUMENT} or {@link Intent#ACTION_CREATE_DOCUMENT}.
  *
  * @see DocumentsProvider
  */
@@ -69,6 +73,8 @@
     // content://com.example/root/sdcard/search/?query=pony
     // content://com.example/document/12/
     // content://com.example/document/12/children/
+    // content://com.example/via/12/document/24/
+    // content://com.example/via/12/document/24/children/
 
     private DocumentsContract() {
     }
@@ -425,6 +431,14 @@
         public static final int FLAG_SUPPORTS_SEARCH = 1 << 3;
 
         /**
+         * Flag indicating that this root supports directory selection.
+         *
+         * @see #COLUMN_FLAGS
+         * @see DocumentsProvider#isChildDocument(String, String)
+         */
+        public static final int FLAG_SUPPORTS_DIR_SELECTION = 1 << 4;
+
+        /**
          * Flag indicating that this root is currently empty. This may be used
          * to hide the root when opening documents, but the root will still be
          * shown when creating documents and {@link #FLAG_SUPPORTS_CREATE} is
@@ -484,12 +498,15 @@
 
     /** {@hide} */
     public static final String EXTRA_THUMBNAIL_SIZE = "thumbnail_size";
+    /** {@hide} */
+    public static final String EXTRA_URI = "uri";
 
     private static final String PATH_ROOT = "root";
     private static final String PATH_RECENT = "recent";
     private static final String PATH_DOCUMENT = "document";
     private static final String PATH_CHILDREN = "children";
     private static final String PATH_SEARCH = "search";
+    private static final String PATH_VIA = "via";
 
     private static final String PARAM_QUERY = "query";
     private static final String PARAM_MANAGE = "manage";
@@ -532,6 +549,17 @@
     }
 
     /**
+     * Build URI representing access to descendant documents of the given
+     * {@link Document#COLUMN_DOCUMENT_ID}.
+     *
+     * @see #getViaDocumentId(Uri)
+     */
+    public static Uri buildViaUri(String authority, String documentId) {
+        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(authority)
+                .appendPath(PATH_VIA).appendPath(documentId).build();
+    }
+
+    /**
      * Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a
      * document provider. When queried, a provider will return a single row with
      * columns defined by {@link Document}.
@@ -545,6 +573,41 @@
     }
 
     /**
+     * Build URI representing the given {@link Document#COLUMN_DOCUMENT_ID} in a
+     * document provider. Instead of directly accessing the target document,
+     * gain access via another document. The target document must be a
+     * descendant (child, grandchild, etc) of the via document.
+     * <p>
+     * This is typically used to access documents under a user-selected
+     * directory, since it doesn't require the user to separately confirm each
+     * new document access.
+     *
+     * @param viaUri a related document (directory) that the caller is
+     *            leveraging to gain access to the target document. The target
+     *            document must be a descendant of this directory.
+     * @param documentId the target document, which the caller may not have
+     *            direct access to.
+     * @see Intent#ACTION_PICK_DIRECTORY
+     * @see DocumentsProvider#isChildDocument(String, String)
+     * @see #buildDocumentUri(String, String)
+     */
+    public static Uri buildDocumentViaUri(Uri viaUri, String documentId) {
+        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(viaUri.getAuthority()).appendPath(PATH_VIA)
+                .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT)
+                .appendPath(documentId).build();
+    }
+
+    /** {@hide} */
+    public static Uri buildDocumentMaybeViaUri(Uri baseUri, String documentId) {
+        if (isViaUri(baseUri)) {
+            return buildDocumentViaUri(baseUri, documentId);
+        } else {
+            return buildDocumentUri(baseUri.getAuthority(), documentId);
+        }
+    }
+
+    /**
      * Build URI representing the children of the given directory in a document
      * provider. When queried, a provider will return zero or more rows with
      * columns defined by {@link Document}.
@@ -562,6 +625,32 @@
     }
 
     /**
+     * Build URI representing the children of the given directory in a document
+     * provider. Instead of directly accessing the target document, gain access
+     * via another document. The target document must be a descendant (child,
+     * grandchild, etc) of the via document.
+     * <p>
+     * This is typically used to access documents under a user-selected
+     * directory, since it doesn't require the user to separately confirm each
+     * new document access.
+     *
+     * @param viaUri a related document (directory) that the caller is
+     *            leveraging to gain access to the target document. The target
+     *            document must be a descendant of this directory.
+     * @param parentDocumentId the target document, which the caller may not
+     *            have direct access to.
+     * @see Intent#ACTION_PICK_DIRECTORY
+     * @see DocumentsProvider#isChildDocument(String, String)
+     * @see #buildChildDocumentsUri(String, String)
+     */
+    public static Uri buildChildDocumentsViaUri(Uri viaUri, String parentDocumentId) {
+        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
+                .authority(viaUri.getAuthority()).appendPath(PATH_VIA)
+                .appendPath(getViaDocumentId(viaUri)).appendPath(PATH_DOCUMENT)
+                .appendPath(parentDocumentId).appendPath(PATH_CHILDREN).build();
+    }
+
+    /**
      * Build URI representing a search for matching documents under a specific
      * root in a document provider. When queried, a provider will return zero or
      * more rows with columns defined by {@link Document}.
@@ -580,21 +669,31 @@
     /**
      * Test if the given URI represents a {@link Document} backed by a
      * {@link DocumentsProvider}.
+     *
+     * @see #buildDocumentUri(String, String)
+     * @see #buildDocumentViaUri(Uri, String)
      */
     public static boolean isDocumentUri(Context context, Uri uri) {
         final List<String> paths = uri.getPathSegments();
-        if (paths.size() < 2) {
-            return false;
+        if (paths.size() >= 2
+                && (PATH_DOCUMENT.equals(paths.get(0)) || PATH_VIA.equals(paths.get(0)))) {
+            return isDocumentsProvider(context, uri.getAuthority());
         }
-        if (!PATH_DOCUMENT.equals(paths.get(0))) {
-            return false;
-        }
+        return false;
+    }
 
+    /** {@hide} */
+    public static boolean isViaUri(Uri uri) {
+        final List<String> paths = uri.getPathSegments();
+        return (paths.size() >= 2 && PATH_VIA.equals(paths.get(0)));
+    }
+
+    private static boolean isDocumentsProvider(Context context, String authority) {
         final Intent intent = new Intent(PROVIDER_INTERFACE);
         final List<ResolveInfo> infos = context.getPackageManager()
                 .queryIntentContentProviders(intent, 0);
         for (ResolveInfo info : infos) {
-            if (uri.getAuthority().equals(info.providerInfo.authority)) {
+            if (authority.equals(info.providerInfo.authority)) {
                 return true;
             }
         }
@@ -606,27 +705,40 @@
      */
     public static String getRootId(Uri rootUri) {
         final List<String> paths = rootUri.getPathSegments();
-        if (paths.size() < 2) {
-            throw new IllegalArgumentException("Not a root: " + rootUri);
+        if (paths.size() >= 2 && PATH_ROOT.equals(paths.get(0))) {
+            return paths.get(1);
         }
-        if (!PATH_ROOT.equals(paths.get(0))) {
-            throw new IllegalArgumentException("Not a root: " + rootUri);
-        }
-        return paths.get(1);
+        throw new IllegalArgumentException("Invalid URI: " + rootUri);
     }
 
     /**
      * Extract the {@link Document#COLUMN_DOCUMENT_ID} from the given URI.
+     *
+     * @see #isDocumentUri(Context, Uri)
      */
     public static String getDocumentId(Uri documentUri) {
         final List<String> paths = documentUri.getPathSegments();
-        if (paths.size() < 2) {
-            throw new IllegalArgumentException("Not a document: " + documentUri);
+        if (paths.size() >= 2 && PATH_DOCUMENT.equals(paths.get(0))) {
+            return paths.get(1);
         }
-        if (!PATH_DOCUMENT.equals(paths.get(0))) {
-            throw new IllegalArgumentException("Not a document: " + documentUri);
+        if (paths.size() >= 4 && PATH_VIA.equals(paths.get(0))
+                && PATH_DOCUMENT.equals(paths.get(2))) {
+            return paths.get(3);
         }
-        return paths.get(1);
+        throw new IllegalArgumentException("Invalid URI: " + documentUri);
+    }
+
+    /**
+     * Extract the via {@link Document#COLUMN_DOCUMENT_ID} from the given URI.
+     *
+     * @see #isViaUri(Uri)
+     */
+    public static String getViaDocumentId(Uri documentUri) {
+        final List<String> paths = documentUri.getPathSegments();
+        if (paths.size() >= 2 && PATH_VIA.equals(paths.get(0))) {
+            return paths.get(1);
+        }
+        throw new IllegalArgumentException("Invalid URI: " + documentUri);
     }
 
     /**
@@ -697,7 +809,7 @@
             // optimal decode path; otherwise fall back to buffering.
             BufferedInputStream is = null;
             try {
-                Libcore.os.lseek(fd, offset, SEEK_SET);
+                Os.lseek(fd, offset, SEEK_SET);
             } catch (ErrnoException e) {
                 is = new BufferedInputStream(new FileInputStream(fd), THUMBNAIL_BUFFER_SIZE);
                 is.mark(THUMBNAIL_BUFFER_SIZE);
@@ -723,7 +835,7 @@
                 bitmap = BitmapFactory.decodeStream(is, null, opts);
             } else {
                 try {
-                    Libcore.os.lseek(fd, offset, SEEK_SET);
+                    Os.lseek(fd, offset, SEEK_SET);
                 } catch (ErrnoException e) {
                     e.rethrowAsIOException();
                 }
@@ -758,7 +870,6 @@
      * @param mimeType MIME type of new document
      * @param displayName name of new document
      * @return newly created document, or {@code null} if failed
-     * @hide
      */
     public static Uri createDocument(ContentResolver resolver, Uri parentDocumentUri,
             String mimeType, String displayName) {
@@ -778,13 +889,12 @@
     public static Uri createDocument(ContentProviderClient client, Uri parentDocumentUri,
             String mimeType, String displayName) throws RemoteException {
         final Bundle in = new Bundle();
-        in.putString(Document.COLUMN_DOCUMENT_ID, getDocumentId(parentDocumentUri));
+        in.putParcelable(DocumentsContract.EXTRA_URI, parentDocumentUri);
         in.putString(Document.COLUMN_MIME_TYPE, mimeType);
         in.putString(Document.COLUMN_DISPLAY_NAME, displayName);
 
         final Bundle out = client.call(METHOD_CREATE_DOCUMENT, null, in);
-        return buildDocumentUri(
-                parentDocumentUri.getAuthority(), out.getString(Document.COLUMN_DOCUMENT_ID));
+        return out.getParcelable(DocumentsContract.EXTRA_URI);
     }
 
     /**
@@ -811,7 +921,7 @@
     public static void deleteDocument(ContentProviderClient client, Uri documentUri)
             throws RemoteException {
         final Bundle in = new Bundle();
-        in.putString(Document.COLUMN_DOCUMENT_ID, getDocumentId(documentUri));
+        in.putParcelable(DocumentsContract.EXTRA_URI, documentUri);
 
         client.call(METHOD_DELETE_DOCUMENT, null, in);
     }
diff --git a/core/java/android/provider/DocumentsProvider.java b/core/java/android/provider/DocumentsProvider.java
index 49816f8..1a7a00f2 100644
--- a/core/java/android/provider/DocumentsProvider.java
+++ b/core/java/android/provider/DocumentsProvider.java
@@ -46,6 +46,7 @@
 import libcore.io.IoUtils;
 
 import java.io.FileNotFoundException;
+import java.util.Objects;
 
 /**
  * Base class for a document provider. A document provider offers read and write
@@ -125,6 +126,8 @@
     private static final int MATCH_SEARCH = 4;
     private static final int MATCH_DOCUMENT = 5;
     private static final int MATCH_CHILDREN = 6;
+    private static final int MATCH_DOCUMENT_VIA = 7;
+    private static final int MATCH_CHILDREN_VIA = 8;
 
     private String mAuthority;
 
@@ -144,6 +147,8 @@
         mMatcher.addURI(mAuthority, "root/*/search", MATCH_SEARCH);
         mMatcher.addURI(mAuthority, "document/*", MATCH_DOCUMENT);
         mMatcher.addURI(mAuthority, "document/*/children", MATCH_CHILDREN);
+        mMatcher.addURI(mAuthority, "via/*/document/*", MATCH_DOCUMENT_VIA);
+        mMatcher.addURI(mAuthority, "via/*/document/*/children", MATCH_CHILDREN_VIA);
 
         // Sanity check our setup
         if (!info.exported) {
@@ -161,6 +166,35 @@
     }
 
     /**
+     * Test if a document is descendant (child, grandchild, etc) from the given
+     * parent. Providers must override this to support directory selection. You
+     * should avoid making network requests to keep this request fast.
+     *
+     * @param parentDocumentId parent to verify against.
+     * @param documentId child to verify.
+     * @return if given document is a descendant of the given parent.
+     * @see DocumentsContract.Root#FLAG_SUPPORTS_DIR_SELECTION
+     */
+    public boolean isChildDocument(String parentDocumentId, String documentId) {
+        return false;
+    }
+
+    /** {@hide} */
+    private void enforceVia(Uri documentUri) {
+        if (DocumentsContract.isViaUri(documentUri)) {
+            final String parent = DocumentsContract.getViaDocumentId(documentUri);
+            final String child = DocumentsContract.getDocumentId(documentUri);
+            if (Objects.equals(parent, child)) {
+                return;
+            }
+            if (!isChildDocument(parent, child)) {
+                throw new SecurityException(
+                        "Document " + child + " is not a descendant of " + parent);
+            }
+        }
+    }
+
+    /**
      * Create a new document and return its newly generated
      * {@link Document#COLUMN_DOCUMENT_ID}. You must allocate a new
      * {@link Document#COLUMN_DOCUMENT_ID} to represent the document, which must
@@ -182,9 +216,10 @@
 
     /**
      * Delete the requested document. Upon returning, any URI permission grants
-     * for the requested document will be revoked. If additional documents were
-     * deleted as a side effect of this call, such as documents inside a
-     * directory, the implementor is responsible for revoking those permissions.
+     * for the given document will be revoked. If additional documents were
+     * deleted as a side effect of this call (such as documents inside a
+     * directory) the implementor is responsible for revoking those permissions
+     * using {@link #revokeDocumentPermission(String)}.
      *
      * @param documentId the document to delete.
      */
@@ -420,8 +455,12 @@
                     return querySearchDocuments(
                             getRootId(uri), getSearchDocumentsQuery(uri), projection);
                 case MATCH_DOCUMENT:
+                case MATCH_DOCUMENT_VIA:
+                    enforceVia(uri);
                     return queryDocument(getDocumentId(uri), projection);
                 case MATCH_CHILDREN:
+                case MATCH_CHILDREN_VIA:
+                    enforceVia(uri);
                     if (DocumentsContract.isManageMode(uri)) {
                         return queryChildDocumentsForManage(
                                 getDocumentId(uri), projection, sortOrder);
@@ -449,6 +488,8 @@
                 case MATCH_ROOT:
                     return DocumentsContract.Root.MIME_TYPE_ITEM;
                 case MATCH_DOCUMENT:
+                case MATCH_DOCUMENT_VIA:
+                    enforceVia(uri);
                     return getDocumentType(getDocumentId(uri));
                 default:
                     return null;
@@ -460,6 +501,49 @@
     }
 
     /**
+     * Implementation is provided by the parent class. Can be overridden to
+     * provide additional functionality, but subclasses <em>must</em> always
+     * call the superclass. If the superclass returns {@code null}, the subclass
+     * may implement custom behavior.
+     * <p>
+     * This is typically used to resolve a "via" URI into a concrete document
+     * reference, issuing a narrower single-document URI permission grant along
+     * the way.
+     *
+     * @see DocumentsContract#buildDocumentViaUri(Uri, String)
+     */
+    @Override
+    public Uri canonicalize(Uri uri) {
+        final Context context = getContext();
+        switch (mMatcher.match(uri)) {
+            case MATCH_DOCUMENT_VIA:
+                enforceVia(uri);
+
+                final Uri narrowUri = DocumentsContract.buildDocumentUri(uri.getAuthority(),
+                        DocumentsContract.getDocumentId(uri));
+
+                // Caller may only have prefix grant, so extend them a grant to
+                // the narrow Uri. Caller already holds read grant to get here,
+                // so check for any other modes we should extend.
+                int modeFlags = Intent.FLAG_GRANT_READ_URI_PERMISSION;
+                if (context.checkCallingOrSelfUriPermission(uri,
+                        Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    modeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
+                }
+                if (context.checkCallingOrSelfUriPermission(uri,
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION
+                        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION)
+                        == PackageManager.PERMISSION_GRANTED) {
+                    modeFlags |= Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION;
+                }
+                context.grantUriPermission(getCallingPackage(), narrowUri, modeFlags);
+                return narrowUri;
+        }
+        return null;
+    }
+
+    /**
      * Implementation is provided by the parent class. Throws by default, and
      * cannot be overriden.
      *
@@ -496,54 +580,47 @@
      * provide additional functionality, but subclasses <em>must</em> always
      * call the superclass. If the superclass returns {@code null}, the subclass
      * may implement custom behavior.
-     *
-     * @see #openDocument(String, String, CancellationSignal)
-     * @see #deleteDocument(String)
      */
     @Override
     public Bundle call(String method, String arg, Bundle extras) {
-        final Context context = getContext();
-
         if (!method.startsWith("android:")) {
-            // Let non-platform methods pass through
+            // Ignore non-platform methods
             return super.call(method, arg, extras);
         }
 
-        final String documentId = extras.getString(Document.COLUMN_DOCUMENT_ID);
-        final Uri documentUri = DocumentsContract.buildDocumentUri(mAuthority, documentId);
+        final Uri documentUri = extras.getParcelable(DocumentsContract.EXTRA_URI);
+        final String authority = documentUri.getAuthority();
+        final String documentId = DocumentsContract.getDocumentId(documentUri);
 
-        // Require that caller can manage requested document
-        final boolean callerHasManage =
-                context.checkCallingOrSelfPermission(android.Manifest.permission.MANAGE_DOCUMENTS)
-                == PackageManager.PERMISSION_GRANTED;
-        enforceWritePermissionInner(documentUri);
+        if (!mAuthority.equals(authority)) {
+            throw new SecurityException(
+                    "Requested authority " + authority + " doesn't match provider " + mAuthority);
+        }
+        enforceVia(documentUri);
 
         final Bundle out = new Bundle();
         try {
             if (METHOD_CREATE_DOCUMENT.equals(method)) {
+                enforceWritePermissionInner(documentUri);
+
                 final String mimeType = extras.getString(Document.COLUMN_MIME_TYPE);
                 final String displayName = extras.getString(Document.COLUMN_DISPLAY_NAME);
 
                 final String newDocumentId = createDocument(documentId, mimeType, displayName);
-                out.putString(Document.COLUMN_DOCUMENT_ID, newDocumentId);
 
-                // Extend permission grant towards caller if needed
-                if (!callerHasManage) {
-                    final Uri newDocumentUri = DocumentsContract.buildDocumentUri(
-                            mAuthority, newDocumentId);
-                    context.grantUriPermission(getCallingPackage(), newDocumentUri,
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION
-                            | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                            | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
-                }
+                // No need to issue new grants here, since caller either has
+                // manage permission or a prefix grant. We might generate a
+                // "via" style URI if that's how they called us.
+                final Uri newDocumentUri = DocumentsContract.buildDocumentMaybeViaUri(documentUri,
+                        newDocumentId);
+                out.putParcelable(DocumentsContract.EXTRA_URI, newDocumentUri);
 
             } else if (METHOD_DELETE_DOCUMENT.equals(method)) {
+                enforceWritePermissionInner(documentUri);
                 deleteDocument(documentId);
 
                 // Document no longer exists, clean up any grants
-                context.revokeUriPermission(documentUri, Intent.FLAG_GRANT_READ_URI_PERMISSION
-                        | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
-                        | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
+                revokeDocumentPermission(documentId);
 
             } else {
                 throw new UnsupportedOperationException("Method not supported " + method);
@@ -555,12 +632,25 @@
     }
 
     /**
+     * Revoke any active permission grants for the given
+     * {@link Document#COLUMN_DOCUMENT_ID}, usually called when a document
+     * becomes invalid. Follows the same semantics as
+     * {@link Context#revokeUriPermission(Uri, int)}.
+     */
+    public final void revokeDocumentPermission(String documentId) {
+        final Context context = getContext();
+        context.revokeUriPermission(DocumentsContract.buildDocumentUri(mAuthority, documentId), ~0);
+        context.revokeUriPermission(DocumentsContract.buildViaUri(mAuthority, documentId), ~0);
+    }
+
+    /**
      * Implementation is provided by the parent class. Cannot be overriden.
      *
      * @see #openDocument(String, String, CancellationSignal)
      */
     @Override
     public final ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
+        enforceVia(uri);
         return openDocument(getDocumentId(uri), mode, null);
     }
 
@@ -572,17 +662,47 @@
     @Override
     public final ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
             throws FileNotFoundException {
+        enforceVia(uri);
         return openDocument(getDocumentId(uri), mode, signal);
     }
 
     /**
      * Implementation is provided by the parent class. Cannot be overriden.
      *
+     * @see #openDocument(String, String, CancellationSignal)
+     */
+    @Override
+    @SuppressWarnings("resource")
+    public final AssetFileDescriptor openAssetFile(Uri uri, String mode)
+            throws FileNotFoundException {
+        enforceVia(uri);
+        final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, null);
+        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
+    }
+
+    /**
+     * Implementation is provided by the parent class. Cannot be overriden.
+     *
+     * @see #openDocument(String, String, CancellationSignal)
+     */
+    @Override
+    @SuppressWarnings("resource")
+    public final AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
+            throws FileNotFoundException {
+        enforceVia(uri);
+        final ParcelFileDescriptor fd = openDocument(getDocumentId(uri), mode, signal);
+        return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
+    }
+
+    /**
+     * Implementation is provided by the parent class. Cannot be overriden.
+     *
      * @see #openDocumentThumbnail(String, Point, CancellationSignal)
      */
     @Override
     public final AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
             throws FileNotFoundException {
+        enforceVia(uri);
         if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
             final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
             return openDocumentThumbnail(getDocumentId(uri), sizeHint, null);
@@ -600,6 +720,7 @@
     public final AssetFileDescriptor openTypedAssetFile(
             Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
             throws FileNotFoundException {
+        enforceVia(uri);
         if (opts != null && opts.containsKey(EXTRA_THUMBNAIL_SIZE)) {
             final Point sizeHint = opts.getParcelable(EXTRA_THUMBNAIL_SIZE);
             return openDocumentThumbnail(getDocumentId(uri), sizeHint, signal);
diff --git a/core/java/android/provider/MediaStore.java b/core/java/android/provider/MediaStore.java
index ae24968..cfab1b3 100644
--- a/core/java/android/provider/MediaStore.java
+++ b/core/java/android/provider/MediaStore.java
@@ -109,14 +109,18 @@
      * An intent to perform a search for music media and automatically play content from the
      * result when possible. This can be fired, for example, by the result of a voice recognition
      * command to listen to music.
-     * <p>
-     * Contains the {@link android.app.SearchManager#QUERY} extra, which is a string
-     * that can contain any type of unstructured music search, like the name of an artist,
-     * an album, a song, a genre, or any combination of these.
-     * <p>
-     * Because this intent includes an open-ended unstructured search string, it makes the most
-     * sense for apps that can support large-scale search of music, such as services connected
-     * to an online database of music which can be streamed and played on the device.
+     * <p>This intent always includes the {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS}
+     * and {@link android.app.SearchManager#QUERY} extras. The
+     * {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} extra determines the search mode, and
+     * the value of the {@link android.app.SearchManager#QUERY} extra depends on the search mode.
+     * For more information about the search modes for this intent, see
+     * <a href="{@docRoot}guide/components/intents-common.html#PlaySearch">Play music based
+     * on a search query</a> in <a href="{@docRoot}guide/components/intents-common.html">Common
+     * Intents</a>.</p>
+     *
+     * <p>This intent makes the most sense for apps that can support large-scale search of music,
+     * such as services connected to an online database of music which can be streamed and played
+     * on the device.</p>
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH =
diff --git a/core/java/android/provider/SearchIndexableData.java b/core/java/android/provider/SearchIndexableData.java
index 05285a3..60bcc40 100644
--- a/core/java/android/provider/SearchIndexableData.java
+++ b/core/java/android/provider/SearchIndexableData.java
@@ -115,6 +115,7 @@
      * Default constructor.
      */
     public SearchIndexableData() {
+        locale = Locale.getDefault();
         enabled = true;
     }
 
@@ -124,8 +125,47 @@
      * @param ctx the Context
      */
     public SearchIndexableData(Context ctx) {
+        this();
         context = ctx;
-        locale = Locale.getDefault();
-        enabled = true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("SearchIndexableData[context: ");
+        sb.append(context);
+        sb.append(", ");
+        sb.append("locale: ");
+        sb.append(locale);
+        sb.append(", ");
+        sb.append("enabled: ");
+        sb.append(enabled);
+        sb.append(", ");
+        sb.append("rank: ");
+        sb.append(rank);
+        sb.append(", ");
+        sb.append("key: ");
+        sb.append(key);
+        sb.append(", ");
+        sb.append("className: ");
+        sb.append(className);
+        sb.append(", ");
+        sb.append("packageName: ");
+        sb.append(packageName);
+        sb.append(", ");
+        sb.append("iconResId: ");
+        sb.append(iconResId);
+        sb.append(", ");
+        sb.append("intentAction: ");
+        sb.append(intentAction);
+        sb.append(", ");
+        sb.append("intentTargetPackage: ");
+        sb.append(intentTargetPackage);
+        sb.append(", ");
+        sb.append("intentTargetClass: ");
+        sb.append(intentTargetClass);
+        sb.append("]");
+
+        return sb.toString();
     }
 }
diff --git a/core/java/android/provider/SearchIndexableResource.java b/core/java/android/provider/SearchIndexableResource.java
index ba3bd4f..c807df2 100644
--- a/core/java/android/provider/SearchIndexableResource.java
+++ b/core/java/android/provider/SearchIndexableResource.java
@@ -48,6 +48,7 @@
      * @param iconResId the resource ID associated with the data.
      */
     public SearchIndexableResource(int rank, int xmlResId, String className, int iconResId) {
+        super();
         this.rank = rank;
         this.xmlResId = xmlResId;
         this.className = className;
@@ -62,4 +63,17 @@
     public SearchIndexableResource(Context context) {
         super(context);
     }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("SearchIndexableResource[");
+        sb.append(super.toString());
+        sb.append(", ");
+        sb.append("xmlResId: ");
+        sb.append(xmlResId);
+        sb.append("]");
+
+        return sb.toString();
+    }
 }
\ No newline at end of file
diff --git a/core/java/android/provider/SearchIndexablesContract.java b/core/java/android/provider/SearchIndexablesContract.java
index 1754dce..a8b4cfb0 100644
--- a/core/java/android/provider/SearchIndexablesContract.java
+++ b/core/java/android/provider/SearchIndexablesContract.java
@@ -35,7 +35,7 @@
     private static final String SETTINGS = "settings";
 
     /**
-     * Indexable references name.
+     * Indexable reference names.
      */
     public static final String INDEXABLES_XML_RES = "indexables_xml_res";
 
@@ -45,7 +45,7 @@
     public static final String INDEXABLES_XML_RES_PATH = SETTINGS + "/" + INDEXABLES_XML_RES;
 
     /**
-     * Indexable raw data name.
+     * Indexable raw data names.
      */
     public static final String INDEXABLES_RAW = "indexables_raw";
 
@@ -55,6 +55,16 @@
     public static final String INDEXABLES_RAW_PATH = SETTINGS + "/" + INDEXABLES_RAW;
 
     /**
+     * Non indexable data keys.
+     */
+    public static final String NON_INDEXABLES_KEYS = "non_indexables_key";
+
+    /**
+     * ContentProvider path for non indexable data keys.
+     */
+    public static final String NON_INDEXABLES_KEYS_PATH = SETTINGS + "/" + NON_INDEXABLES_KEYS;
+
+    /**
      * Indexable xml resources colums.
      */
     public static final String[] INDEXABLES_XML_RES_COLUMNS = new String[] {
@@ -114,6 +124,17 @@
     public static final int COLUMN_INDEX_RAW_INTENT_TARGET_CLASS = 11;
     public static final int COLUMN_INDEX_RAW_KEY = 12;
 
+    /**
+     * Indexable raw data colums.
+     */
+    public static final String[] NON_INDEXABLES_KEYS_COLUMNS = new String[] {
+            NonIndexableKey.COLUMN_KEY_VALUE      // 0
+    };
+
+    /**
+     * Non indexable data keys colums indices.
+     */
+    public static final int COLUMN_INDEX_NON_INDEXABLE_KEYS_KEY_VALUE = 0;
 
     /**
      * Constants related to a {@link SearchIndexableResource}.
@@ -165,7 +186,7 @@
         public static final String COLUMN_SUMMARY_OFF = "summaryOff";
 
         /**
-         * Entries associated with the raw data (when the data can can several values).
+         * Entries associated with the raw data (when the data can have several values).
          */
         public static final String COLUMN_ENTRIES = "entries";
 
@@ -175,7 +196,7 @@
         public static final String COLUMN_KEYWORDS = "keywords";
 
         /**
-         * Fragment's title associated with the raw data.
+         * Fragment or Activity title associated with the raw data.
          */
         public static final String COLUMN_SCREEN_TITLE = "screenTitle";
 
@@ -186,6 +207,24 @@
     }
 
     /**
+     * Constants related to a {@link SearchIndexableResource} and {@link SearchIndexableData}.
+     *
+     * This is a description of a data (thru its unique key) that cannot be indexed.
+     */
+    public static final class NonIndexableKey extends BaseColumns {
+        private NonIndexableKey() {
+        }
+
+        public static final String MIME_TYPE = ContentResolver.CURSOR_DIR_BASE_TYPE +
+                "/" + NON_INDEXABLES_KEYS;
+
+        /**
+         * Key for the non indexable data.
+         */
+        public static final String COLUMN_KEY_VALUE = "key";
+    }
+
+    /**
      * The base columns.
      */
     private static class BaseColumns {
diff --git a/core/java/android/provider/SearchIndexablesProvider.java b/core/java/android/provider/SearchIndexablesProvider.java
index 2e358e4..9c8f6d0 100644
--- a/core/java/android/provider/SearchIndexablesProvider.java
+++ b/core/java/android/provider/SearchIndexablesProvider.java
@@ -69,6 +69,7 @@
 
     private static final int MATCH_RES_CODE = 1;
     private static final int MATCH_RAW_CODE = 2;
+    private static final int MATCH_NON_INDEXABLE_KEYS_CODE = 3;
 
     /**
      * Implementation is provided by the parent class.
@@ -82,6 +83,8 @@
                 MATCH_RES_CODE);
         mMatcher.addURI(mAuthority, SearchIndexablesContract.INDEXABLES_RAW_PATH,
                 MATCH_RAW_CODE);
+        mMatcher.addURI(mAuthority, SearchIndexablesContract.NON_INDEXABLES_KEYS_PATH,
+                MATCH_NON_INDEXABLE_KEYS_CODE);
 
         // Sanity check our setup
         if (!info.exported) {
@@ -105,6 +108,8 @@
                 return queryXmlResources(null);
             case MATCH_RAW_CODE:
                 return queryRawData(null);
+            case MATCH_NON_INDEXABLE_KEYS_CODE:
+                return queryNonIndexableKeys(null);
             default:
                 throw new UnsupportedOperationException("Unknown Uri " + uri);
         }
@@ -113,7 +118,7 @@
     /**
      * Returns all {@link android.provider.SearchIndexablesContract.XmlResource}.
      *
-     * Those are usually xml resource ID to some {@link android.preference.PreferenceScreen}.
+     * Those are Xml resource IDs to some {@link android.preference.PreferenceScreen}.
      *
      * @param projection list of {@link android.provider.SearchIndexablesContract.XmlResource}
      *                   columns to put into the cursor. If {@code null} all supported columns
@@ -124,7 +129,7 @@
     /**
      * Returns all {@link android.provider.SearchIndexablesContract.RawData}.
      *
-     * Those are raw indexable data.
+     * Those are the raw indexable data.
      *
      * @param projection list of {@link android.provider.SearchIndexablesContract.RawData} columns
      *                   to put into the cursor. If {@code null} all supported columns should be
@@ -132,6 +137,17 @@
      */
     public abstract Cursor queryRawData(String[] projection);
 
+    /**
+     * Returns all {@link android.provider.SearchIndexablesContract.NonIndexableKey}.
+     *
+     * Those are the non indexable data keys.
+     *
+     * @param projection list of {@link android.provider.SearchIndexablesContract.NonIndexableKey}
+     *                   columns to put into the cursor. If {@code null} all supported columns
+     *                   should be included.
+     */
+    public abstract Cursor queryNonIndexableKeys(String[] projection);
+
     @Override
     public String getType(Uri uri) {
         switch (mMatcher.match(uri)) {
@@ -139,14 +155,15 @@
                 return SearchIndexablesContract.XmlResource.MIME_TYPE;
             case MATCH_RAW_CODE:
                 return SearchIndexablesContract.RawData.MIME_TYPE;
+            case MATCH_NON_INDEXABLE_KEYS_CODE:
+                return SearchIndexablesContract.NonIndexableKey.MIME_TYPE;
             default:
                 throw new IllegalArgumentException("Unknown URI " + uri);
         }
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final Uri insert(Uri uri, ContentValues values) {
@@ -154,8 +171,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final int delete(Uri uri, String selection, String[] selectionArgs) {
@@ -163,8 +179,7 @@
     }
 
     /**
-     * Implementation is provided by the parent class. Throws by default, and
-     * cannot be overriden.
+     * Implementation is provided by the parent class. Throws by default, and cannot be overriden.
      */
     @Override
     public final int update(
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7062933..ab06230 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -723,6 +723,13 @@
             = "android.settings.NOTIFICATION_LISTENER_SETTINGS";
 
     /**
+     * @hide
+     */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String ACTION_CONDITION_PROVIDER_SETTINGS
+            = "android.settings.ACTION_CONDITION_PROVIDER_SETTINGS";
+
+    /**
      * Activity Action: Show settings for video captioning.
      * <p>
      * In some cases, a matching Activity may not exist, so ensure you safeguard
@@ -757,6 +764,11 @@
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_ZEN_MODE_SETTINGS = "android.settings.ZEN_MODE_SETTINGS";
 
+    /** {@hide} */
+    @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
+    public static final String
+            ACTION_SHOW_REGULATORY_INFO = "android.settings.SHOW_REGULATORY_INFO";
+
     // End of Intent actions for Settings
 
     /**
@@ -3311,6 +3323,12 @@
                 "input_method_selector_visibility";
 
         /**
+         * The currently selected voice interaction service flattened ComponentName.
+         * @hide
+         */
+        public static final String VOICE_INTERACTION_SERVICE = "voice_interaction_service";
+
+        /**
          * bluetooth HCI snoop log configuration
          * @hide
          */
@@ -4510,6 +4528,11 @@
          */
         public static final String ENABLED_NOTIFICATION_LISTENERS = "enabled_notification_listeners";
 
+        /**
+         * @hide
+         */
+        public static final String ENABLED_CONDITION_PROVIDERS = "enabled_condition_providers";
+
         /** @hide */
         public static final String BAR_SERVICE_COMPONENT = "bar_service_component";
 
@@ -5097,6 +5120,13 @@
        public static final String NETWORK_PREFERENCE = "network_preference";
 
        /**
+        * Which package name to use for network scoring. If null, or if the package is not a valid
+        * scorer app, external network scores will neither be requested nor accepted.
+        * @hide
+        */
+       public static final String NETWORK_SCORER_APP = "network_scorer_app";
+
+       /**
         * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
         * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
         * exceeded.
@@ -5963,6 +5993,12 @@
         public static final String SHOW_PROCESSES = "show_processes";
 
         /**
+         * If 1 low power mode is enabled.
+         * @hide
+         */
+        public static final String LOW_POWER_MODE = "low_power";
+
+         /**
          * If 1, the activity manager will aggressively finish activities and
          * processes as soon as they are no longer needed.  If 0, the normal
          * extended lifetime is used.
@@ -6113,6 +6149,13 @@
         }
 
         /**
+         * Opaque value, changes when persisted zen mode configuration changes.
+         *
+         * @hide
+         */
+        public static final String ZEN_MODE_CONFIG_ETAG = "zen_mode_config_etag";
+
+        /**
          * Defines global heads up toggle.  One of HEADS_UP_OFF, HEADS_UP_ON.
          *
          * @hide
diff --git a/core/java/android/provider/TvContract.java b/core/java/android/provider/TvContract.java
new file mode 100644
index 0000000..62252be
--- /dev/null
+++ b/core/java/android/provider/TvContract.java
@@ -0,0 +1,596 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.provider;
+
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.net.Uri;
+
+import java.util.List;
+
+/**
+ * <p>
+ * The contract between the TV provider and applications. Contains definitions for the supported
+ * URIs and columns.
+ * </p>
+ * <h3>Overview</h3>
+ * <p>
+ * TvContract defines a basic database of TV content metadata such as channel and program
+ * information. The information is stored in {@link Channels} and {@link Programs} tables.
+ * </p>
+ * <ul>
+ *     <li>A row in the {@link Channels} table represents information about a TV channel. The data
+ *         format can vary greatly from standard to standard or according to service provider, thus
+ *         the columns here are mostly comprised of basic entities that are usually seen to users
+ *         regardless of standard such as channel number and name.</li>
+ *     <li>A row in the {@link Programs} table represents a set of data describing a TV program such
+ *         as program title and start time.</li>
+ * </ul>
+ */
+public final class TvContract {
+    /** The authority for the TV provider. */
+    public static final String AUTHORITY = "com.android.tv";
+
+    private static final String PATH_CHANNEL = "channel";
+    private static final String PATH_PROGRAM = "program";
+    private static final String PATH_INPUT = "input";
+
+    /**
+     * An optional query, update or delete URI parameter that allows the caller to specify start
+     * time (in milliseconds since the epoch) to filter programs.
+     *
+     * @hide
+     */
+    public static final String PARAM_START_TIME = "start_time";
+
+    /**
+     * An optional query, update or delete URI parameter that allows the caller to specify end time
+     * (in milliseconds since the epoch) to filter programs.
+     *
+     * @hide
+     */
+    public static final String PARAM_END_TIME = "end_time";
+
+    /**
+     * A query, update or delete URI parameter that allows the caller to operate on all or
+     * browsable-only channels. If set to "true", the rows that contain non-browsable channels are
+     * not affected.
+     *
+     * @hide
+     */
+    public static final String PARAM_BROWSABLE_ONLY = "browable_only";
+
+    /**
+     * Builds a URI that points to a specific channel.
+     *
+     * @param channelId The ID of the channel to point to.
+     */
+    public static final Uri buildChannelUri(long channelId) {
+        return ContentUris.withAppendedId(Channels.CONTENT_URI, channelId);
+    }
+
+    /**
+     * Builds a URI that points to all browsable channels from a given TV input.
+     *
+     * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
+     *            the given TV input.
+     */
+    public static final Uri buildChannelsUriForInput(ComponentName name) {
+        return buildChannelsUriForInput(name, true);
+    }
+
+    /**
+     * Builds a URI that points to all or browsable-only channels from a given TV input.
+     *
+     * @param name {@link ComponentName} of the {@link android.tv.TvInputService} that implements
+     *            the given TV input.
+     * @param browsableOnly If set to {@code true} the URI points to only browsable channels. If set
+     *            to {@code false} the URI points to all channels regardless of whether they are
+     *            browsable or not.
+     */
+    public static final Uri buildChannelsUriForInput(ComponentName name, boolean browsableOnly) {
+        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
+                .appendPath(PATH_INPUT).appendPath(name.getPackageName())
+                .appendPath(name.getClassName()).appendPath(PATH_CHANNEL)
+                .appendQueryParameter(PARAM_BROWSABLE_ONLY, String.valueOf(browsableOnly)).build();
+    }
+
+    /**
+     * Builds a URI that points to a specific program.
+     *
+     * @param programId The ID of the program to point to.
+     */
+    public static final Uri buildProgramUri(long programId) {
+        return ContentUris.withAppendedId(Programs.CONTENT_URI, programId);
+    }
+
+    /**
+     * Builds a URI that points to all programs on a given channel.
+     *
+     * @param channelUri The URI of the channel to return programs for.
+     */
+    public static final Uri buildProgramsUriForChannel(Uri channelUri) {
+        if (!PATH_CHANNEL.equals(channelUri.getPathSegments().get(0))) {
+            throw new IllegalArgumentException("Not a channel: " + channelUri);
+        }
+        String channelId = String.valueOf(ContentUris.parseId(channelUri));
+        return new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT).authority(AUTHORITY)
+                .appendPath(PATH_CHANNEL).appendPath(channelId).appendPath(PATH_PROGRAM).build();
+    }
+
+    /**
+     * Builds a URI that points to programs on a specific channel whose schedules overlap with the
+     * given time frame.
+     *
+     * @param channelUri The URI of the channel to return programs for.
+     * @param startTime The start time used to filter programs. The returned programs should have
+     *            {@link Programs#END_TIME_UTC_MILLIS} that is greater than this time.
+     * @param endTime The end time used to filter programs. The returned programs should have
+     *            {@link Programs#START_TIME_UTC_MILLIS} that is less than this time.
+     */
+    public static final Uri buildProgramsUriForChannel(Uri channelUri, long startTime,
+            long endTime) {
+        Uri uri = buildProgramsUriForChannel(channelUri);
+        return uri.buildUpon().appendQueryParameter(PARAM_START_TIME, String.valueOf(startTime))
+                .appendQueryParameter(PARAM_END_TIME, String.valueOf(endTime)).build();
+    }
+
+    /**
+     * Builds a URI that points to a specific program the user watched.
+     *
+     * @param watchedProgramId The ID of the watched program to point to.
+     * @hide
+     */
+    public static final Uri buildWatchedProgramUri(long watchedProgramId) {
+        return ContentUris.withAppendedId(WatchedPrograms.CONTENT_URI, watchedProgramId);
+    }
+
+    /**
+     * Extracts the {@link Channels#PACKAGE_NAME} from a given URI.
+     *
+     * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
+     *            {@link #buildChannelsUriForInput(ComponentName, boolean)}.
+     * @hide
+     */
+    public static final String getPackageName(Uri channelsUri) {
+        final List<String> paths = channelsUri.getPathSegments();
+        if (paths.size() < 4) {
+            throw new IllegalArgumentException("Not channels: " + channelsUri);
+        }
+        if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
+            throw new IllegalArgumentException("Not channels: " + channelsUri);
+        }
+        return paths.get(1);
+    }
+
+    /**
+     * Extracts the {@link Channels#SERVICE_NAME} from a given URI.
+     *
+     * @param channelsUri A URI constructed by {@link #buildChannelsUriForInput(ComponentName)} or
+     *            {@link #buildChannelsUriForInput(ComponentName, boolean)}.
+     * @hide
+     */
+    public static final String getServiceName(Uri channelsUri) {
+        final List<String> paths = channelsUri.getPathSegments();
+        if (paths.size() < 4) {
+            throw new IllegalArgumentException("Not channels: " + channelsUri);
+        }
+        if (!PATH_INPUT.equals(paths.get(0)) || !PATH_CHANNEL.equals(paths.get(3))) {
+            throw new IllegalArgumentException("Not channels: " + channelsUri);
+        }
+        return paths.get(2);
+    }
+
+    /**
+     * Extracts the {@link Channels#_ID} from a given URI.
+     *
+     * @param programsUri A URI constructed by {@link #buildProgramsUriForChannel(Uri)} or
+     *            {@link #buildProgramsUriForChannel(Uri, long, long)}.
+     * @hide
+     */
+    public static final String getChannelId(Uri programsUri) {
+        final List<String> paths = programsUri.getPathSegments();
+        if (paths.size() < 3) {
+            throw new IllegalArgumentException("Not programs: " + programsUri);
+        }
+        if (!PATH_CHANNEL.equals(paths.get(0)) || !PATH_PROGRAM.equals(paths.get(2))) {
+            throw new IllegalArgumentException("Not programs: " + programsUri);
+        }
+        return paths.get(1);
+    }
+
+
+    private TvContract() {}
+
+    /**
+     * Common base for the tables of TV channels/programs.
+     */
+    public interface BaseTvColumns extends BaseColumns {
+        /**
+         * The name of the package that owns a row in each table.
+         * <p>
+         * The TV provider fills it in with the name of the package that provides the initial data
+         * of that row. If the package is later uninstalled, the rows it owns are automatically
+         * removed from the tables.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String PACKAGE_NAME = "package_name";
+    }
+
+    /** Column definitions for the TV channels table. */
+    public static final class Channels implements BaseTvColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
+                + PATH_CHANNEL);
+
+        /** The MIME type of a directory of TV channels. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.channels";
+
+        /** The MIME type of a single TV channel. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.channels";
+
+        /** A generic channel type. */
+        public static final int TYPE_OTHER = 0x0;
+
+        /** The special channel type used for pass-through inputs such as HDMI. */
+        public static final int TYPE_PASSTHROUGH = 0x00010000;
+
+        /** The channel type for DVB-T (terrestrial). */
+        public static final int TYPE_DVB_T = 0x00020000;
+
+        /** The channel type for DVB-T2 (terrestrial). */
+        public static final int TYPE_DVB_T2 = 0x00020001;
+
+        /** The channel type for DVB-S (satellite). */
+        public static final int TYPE_DVB_S = 0x00020100;
+
+        /** The channel type for DVB-S2 (satellite). */
+        public static final int TYPE_DVB_S2 = 0x00020101;
+
+        /** The channel type for DVB-C (cable). */
+        public static final int TYPE_DVB_C = 0x00020200;
+
+        /** The channel type for DVB-C2 (cable). */
+        public static final int TYPE_DVB_C2 = 0x00020201;
+
+        /** The channel type for DVB-H (handheld). */
+        public static final int TYPE_DVB_H = 0x00020300;
+
+        /** The channel type for DVB-SH (satellite). */
+        public static final int TYPE_DVB_SH = 0x00020400;
+
+        /** The channel type for ATSC (terrestrial/cable). */
+        public static final int TYPE_ATSC = 0x00030000;
+
+        /** The channel type for ATSC 2.0. */
+        public static final int TYPE_ATSC_2_0 = 0x00030001;
+
+        /** The channel type for ATSC-M/H (mobile/handheld). */
+        public static final int TYPE_ATSC_M_H = 0x00030100;
+
+        /** The channel type for ISDB-T (terrestrial). */
+        public static final int TYPE_ISDB_T = 0x00040000;
+
+        /** The channel type for ISDB-Tb (Brazil). */
+        public static final int TYPE_ISDB_TB = 0x00040100;
+
+        /** The channel type for ISDB-S (satellite). */
+        public static final int TYPE_ISDB_S = 0x00040200;
+
+        /** The channel type for ISDB-C (cable). */
+        public static final int TYPE_ISDB_C = 0x00040300;
+
+        /** The channel type for 1seg (handheld). */
+        public static final int TYPE_1SEG = 0x00040400;
+
+        /** The channel type for DTMB (terrestrial). */
+        public static final int TYPE_DTMB = 0x00050000;
+
+        /** The channel type for CMMB (handheld). */
+        public static final int TYPE_CMMB = 0x00050100;
+
+        /** The channel type for T-DMB (terrestrial). */
+        public static final int TYPE_T_DMB = 0x00060000;
+
+        /** The channel type for S-DMB (satellite). */
+        public static final int TYPE_S_DMB = 0x00060100;
+
+        /**
+         * The name of the TV input service that provides this TV channel.
+         * <p>
+         * This is a required field.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String SERVICE_NAME = "service_name";
+
+        /**
+         * The predefined type of this TV channel.
+         * <p>
+         * This is used to indicate which broadcast standard (e.g. ATSC, DVB or ISDB) the current
+         * channel conforms to.
+         * </p><p>
+         * This is a required field.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String TYPE = "type";
+
+        /**
+         * The transport stream ID as appeared in various broadcast standards.
+         * <p>
+         * This is not a required field but if provided, can significantly increase the accuracy of
+         * channel identification.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String TRANSPORT_STREAM_ID = "transport_stream_id";
+
+        /**
+         * The channel number that is displayed to the user.
+         * <p>
+         * The format can vary depending on broadcast standard and product specification.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String DISPLAY_NUMBER = "display_number";
+
+        /**
+         * The channel name that is displayed to the user.
+         * <p>
+         * A call sign is a good candidate to use for this purpose but any name that helps the user
+         * recognize the current channel will be enough. Can also be empty depending on broadcast
+         * standard.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DISPLAY_NAME = "display_name";
+
+        /**
+         * The description of this TV channel.
+         * <p>
+         * Can be empty initially.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        /**
+         * The flag indicating whether this TV channel is browsable or not.
+         * <p>
+         * A value of 1 indicates the channel is included in the channel list that applications use
+         * to browse channels, a value of 0 indicates the channel is not included in the list. If
+         * not specified, this value is set to 1 by default.
+         * </p><p>
+         * Type: INTEGER (boolean)
+         * </p>
+         */
+        public static final String BROWSABLE = "browsable";
+
+        /**
+         * Generic data used by individual TV input services.
+         * <p>
+         * Type: BLOB
+         * </p>
+         */
+        public static final String DATA = "data";
+
+
+        /**
+         * The version number of this row entry used by TV input services.
+         * <p>
+         * This is best used by sync adapters to identify the rows to update. The number can be
+         * defined by individual TV input services. One may assign the same value as
+         * {@code version_number} that appears in ETSI EN 300 468 or ATSC A/65, if the data are
+         * coming from a TV broadcast.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String VERSION_NUMBER = "version_number";
+
+        private Channels() {}
+    }
+
+    /** Column definitions for the TV programs table. */
+    public static final class Programs implements BaseTvColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI = Uri.parse("content://" + AUTHORITY + "/"
+                + PATH_PROGRAM);
+
+        /** The MIME type of a directory of TV programs. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.programs";
+
+        /** The MIME type of a single TV program. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.programs";
+
+        /**
+         * The ID of the TV channel that contains this TV program.
+         * <p>
+         * This is a part of the channel URI and matches to {@link BaseColumns#_ID}.
+         * </p><p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String CHANNEL_ID = "channel_id";
+
+        /**
+         * The title of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         **/
+        public static final String TITLE = "title";
+
+        /**
+         * The start time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+        /**
+         * The end time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+        /**
+         * The description of this TV program that is displayed to the user by default.
+         * <p>
+         * The maximum length of this field is 256 characters.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        /**
+         * The detailed, lengthy description of this TV program that is displayed only when the user
+         * wants to see more information.
+         * <p>
+         * TV input services should leave this field empty if they have no additional
+         * details beyond {@link #DESCRIPTION}.
+         * </p><p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String LONG_DESCRIPTION = "long_description";
+
+        /**
+         * Generic data used by TV input services.
+         * <p>
+         * Type: BLOB
+         * </p>
+         */
+        public static final String DATA = "data";
+
+        /**
+         * The version number of this row entry used by TV input services.
+         * <p>
+         * This is best used by sync adapters to identify the rows to update. The number can be
+         * defined by individual TV input services. One may assign the same value as
+         * {@code version_number} in ETSI EN 300 468 or ATSC A/65, if the data are coming from a TV
+         * broadcast.
+         * </p><p>
+         * Type: INTEGER
+         * </p>
+         */
+        public static final String VERSION_NUMBER = "version_number";
+
+        private Programs() {}
+    }
+
+    /**
+     * Column definitions for the TV programs that the user watched. Applications do not have access
+     * to this table.
+     *
+     * @hide
+     */
+    public static final class WatchedPrograms implements BaseColumns {
+
+        /** The content:// style URI for this table. */
+        public static final Uri CONTENT_URI =
+                Uri.parse("content://" + AUTHORITY + "/watched_program");
+
+        /** The MIME type of a directory of watched programs. */
+        public static final String CONTENT_TYPE =
+                "vnd.android.cursor.dir/vnd.com.android.tv.watched_programs";
+
+        /** The MIME type of a single item in this table. */
+        public static final String CONTENT_ITEM_TYPE =
+                "vnd.android.cursor.item/vnd.com.android.tv.watched_programs";
+
+        /**
+         * The UTC time that the user started watching this TV program, in milliseconds since the
+         * epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String WATCH_START_TIME_UTC_MILLIS = "watch_start_time_utc_millis";
+
+        /**
+         * The UTC time that the user stopped watching this TV program, in milliseconds since the
+         * epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String WATCH_END_TIME_UTC_MILLIS = "watch_end_time_utc_millis";
+
+        /**
+         * The channel ID that contains this TV program.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String CHANNEL_ID = "channel_id";
+
+        /**
+         * The title of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String TITLE = "title";
+
+        /**
+         * The start time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String START_TIME_UTC_MILLIS = "start_time_utc_millis";
+
+        /**
+         * The end time of this TV program, in milliseconds since the epoch.
+         * <p>
+         * Type: INTEGER (long)
+         * </p>
+         */
+        public static final String END_TIME_UTC_MILLIS = "end_time_utc_millis";
+
+        /**
+         * The description of this TV program.
+         * <p>
+         * Type: TEXT
+         * </p>
+         */
+        public static final String DESCRIPTION = "description";
+
+        private WatchedPrograms() {}
+    }
+}
diff --git a/core/java/android/service/dreams/DreamService.java b/core/java/android/service/dreams/DreamService.java
index de9eeff..2303d65 100644
--- a/core/java/android/service/dreams/DreamService.java
+++ b/core/java/android/service/dreams/DreamService.java
@@ -789,10 +789,20 @@
             return;
         }
 
-        // start it up
-        if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
-        mStarted = true;
-        onDreamingStarted();
+        // We need to defer calling onDreamingStarted until after onWindowAttached,
+        // which is posted to the handler by addView, so we post onDreamingStarted
+        // to the handler also.  Need to watch out here in case detach occurs before
+        // this callback is invoked.
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (mWindow != null) {
+                    if (mDebug) Slog.v(TAG, "Calling onDreamingStarted()");
+                    mStarted = true;
+                    onDreamingStarted();
+                }
+            }
+        });
     }
 
     private void safelyFinish() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/notification/Condition.aidl
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/notification/Condition.aidl
index 0377123..432852c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/notification/Condition.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.notification;
 
-import android.view.View;
+parcelable Condition;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
diff --git a/core/java/android/service/notification/Condition.java b/core/java/android/service/notification/Condition.java
new file mode 100644
index 0000000..71e3166
--- /dev/null
+++ b/core/java/android/service/notification/Condition.java
@@ -0,0 +1,147 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.util.Objects;
+
+/**
+ * Condition information from condition providers.
+ *
+ * @hide
+ */
+public class Condition implements Parcelable {
+
+    public static final String SCHEME = "condition";
+
+    public static final int STATE_FALSE = 0;
+    public static final int STATE_TRUE = 1;
+    public static final int STATE_UNKNOWN = 2;
+    public static final int STATE_ERROR = 3;
+
+    public static final int FLAG_RELEVANT_NOW = 1 << 0;
+    public static final int FLAG_RELEVANT_ALWAYS = 1 << 1;
+
+    public final Uri id;
+    public String caption;
+    public int state;
+    public int flags;
+
+    public Condition(Uri id, String caption, int state, int flags) {
+        if (id == null) throw new IllegalArgumentException("id is required");
+        if (caption == null) throw new IllegalArgumentException("caption is required");
+        if (!isValidState(state)) throw new IllegalArgumentException("state is invalid: " + state);
+        this.id = id;
+        this.caption = caption;
+        this.state = state;
+        this.flags = flags;
+    }
+
+    private Condition(Parcel source) {
+        this((Uri)source.readParcelable(Condition.class.getClassLoader()),
+                source.readString(),
+                source.readInt(),
+                source.readInt());
+    }
+
+    private static boolean isValidState(int state) {
+        return state >= STATE_FALSE && state <= STATE_ERROR;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(id, 0);
+        dest.writeString(caption);
+        dest.writeInt(state);
+        dest.writeInt(flags);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(Condition.class.getSimpleName()).append('[')
+            .append("id=").append(id)
+            .append(",caption=").append(caption)
+            .append(",state=").append(stateToString(state))
+            .append(",flags=").append(flags)
+            .append(']').toString();
+    }
+
+    public static String stateToString(int state) {
+        if (state == STATE_FALSE) return "STATE_FALSE";
+        if (state == STATE_TRUE) return "STATE_TRUE";
+        if (state == STATE_UNKNOWN) return "STATE_UNKNOWN";
+        if (state == STATE_ERROR) return "STATE_ERROR";
+        throw new IllegalArgumentException("state is invalid: " + state);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Condition)) return false;
+        if (o == this) return true;
+        final Condition other = (Condition) o;
+        return Objects.equals(other.id, id)
+                && Objects.equals(other.caption, caption)
+                && other.state == state
+                && other.flags == flags;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, caption, state, flags);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public Condition copy() {
+        final Parcel parcel = Parcel.obtain();
+        try {
+            writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            return new Condition(parcel);
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    public static Uri.Builder newId(Context context) {
+        return new Uri.Builder().scheme(SCHEME).authority(context.getPackageName());
+    }
+
+    public static boolean isValidId(Uri id, String pkg) {
+        return id != null && id.getScheme().equals(SCHEME) && id.getAuthority().equals(pkg);
+    }
+
+    public static final Parcelable.Creator<Condition> CREATOR
+            = new Parcelable.Creator<Condition>() {
+        @Override
+        public Condition createFromParcel(Parcel source) {
+            return new Condition(source);
+        }
+
+        @Override
+        public Condition[] newArray(int size) {
+            return new Condition[size];
+        }
+    };
+}
diff --git a/core/java/android/service/notification/ConditionProviderService.java b/core/java/android/service/notification/ConditionProviderService.java
new file mode 100644
index 0000000..326412f
--- /dev/null
+++ b/core/java/android/service/notification/ConditionProviderService.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.annotation.SdkConstant;
+import android.app.INotificationManager;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.util.Log;
+
+/**
+ * A service that provides conditions about boolean state.
+ * <p>To extend this class, you must declare the service in your manifest file with
+ * the {@link android.Manifest.permission#BIND_CONDITION_PROVIDER_SERVICE} permission
+ * and include an intent filter with the {@link #SERVICE_INTERFACE} action. For example:</p>
+ * <pre>
+ * &lt;service android:name=".MyConditionProvider"
+ *          android:label="&#64;string/service_name"
+ *          android:permission="android.permission.BIND_CONDITION_PROVIDER_SERVICE">
+ *     &lt;intent-filter>
+ *         &lt;action android:name="android.service.notification.ConditionProviderService" />
+ *     &lt;/intent-filter>
+ * &lt;/service></pre>
+ *
+ * @hide
+ */
+public abstract class ConditionProviderService extends Service {
+    private final String TAG = ConditionProviderService.class.getSimpleName()
+            + "[" + getClass().getSimpleName() + "]";
+
+    private final H mHandler = new H();
+
+    private Provider mProvider;
+    private INotificationManager mNoMan;
+
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE
+            = "android.service.notification.ConditionProviderService";
+
+    abstract public void onConnected();
+    abstract public void onRequestConditions(int relevance);
+    abstract public void onSubscribe(Uri conditionId);
+    abstract public void onUnsubscribe(Uri conditionId);
+
+    private final INotificationManager getNotificationInterface() {
+        if (mNoMan == null) {
+            mNoMan = INotificationManager.Stub.asInterface(
+                    ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        }
+        return mNoMan;
+    }
+
+    public final void notifyCondition(Condition condition) {
+        if (condition == null) return;
+        notifyConditions(new Condition[]{ condition });
+    }
+
+    public final void notifyConditions(Condition... conditions) {
+        if (!isBound() || conditions == null) return;
+        try {
+            getNotificationInterface().notifyConditions(getPackageName(), mProvider, conditions);
+        } catch (android.os.RemoteException ex) {
+            Log.v(TAG, "Unable to contact notification manager", ex);
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (mProvider == null) {
+            mProvider = new Provider();
+        }
+        return mProvider;
+    }
+
+    private boolean isBound() {
+        if (mProvider == null) {
+            Log.w(TAG, "Condition provider service not yet bound.");
+            return false;
+        }
+        return true;
+    }
+
+    private final class Provider extends IConditionProvider.Stub {
+        @Override
+        public void onConnected() {
+            mHandler.obtainMessage(H.ON_CONNECTED).sendToTarget();
+        }
+
+        @Override
+        public void onRequestConditions(int relevance) {
+            mHandler.obtainMessage(H.ON_REQUEST_CONDITIONS, relevance, 0).sendToTarget();
+        }
+
+        @Override
+        public void onSubscribe(Uri conditionId) {
+            mHandler.obtainMessage(H.ON_SUBSCRIBE, conditionId).sendToTarget();
+        }
+
+        @Override
+        public void onUnsubscribe(Uri conditionId) {
+            mHandler.obtainMessage(H.ON_UNSUBSCRIBE, conditionId).sendToTarget();
+        }
+    }
+
+    private final class H extends Handler {
+        private static final int ON_CONNECTED = 1;
+        private static final int ON_REQUEST_CONDITIONS = 2;
+        private static final int ON_SUBSCRIBE = 3;
+        private static final int ON_UNSUBSCRIBE = 4;
+
+        @Override
+        public void handleMessage(Message msg) {
+            String name = null;
+            try {
+                switch(msg.what) {
+                    case ON_CONNECTED:
+                        name = "onConnected";
+                        onConnected();
+                        break;
+                    case ON_REQUEST_CONDITIONS:
+                        name = "onRequestConditions";
+                        onRequestConditions(msg.arg1);
+                        break;
+                    case ON_SUBSCRIBE:
+                        name = "onSubscribe";
+                        onSubscribe((Uri)msg.obj);
+                        break;
+                    case ON_UNSUBSCRIBE:
+                        name = "onUnsubscribe";
+                        onUnsubscribe((Uri)msg.obj);
+                        break;
+                }
+            } catch (Throwable t) {
+                Log.w(TAG, "Error running " + name, t);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/notification/IConditionListener.aidl
similarity index 60%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/notification/IConditionListener.aidl
index 0377123..01f874f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/notification/IConditionListener.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,12 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.notification;
 
-import android.view.View;
+import android.net.Uri;
+import android.service.notification.Condition;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+/** @hide */
+oneway interface IConditionListener {
+    void onConditionsReceived(in Condition[] conditions);
+}
\ No newline at end of file
diff --git a/core/java/android/service/notification/IConditionProvider.aidl b/core/java/android/service/notification/IConditionProvider.aidl
new file mode 100644
index 0000000..ada8939
--- /dev/null
+++ b/core/java/android/service/notification/IConditionProvider.aidl
@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.net.Uri;
+import android.service.notification.Condition;
+
+/** @hide */
+oneway interface IConditionProvider {
+    void onConnected();
+    void onRequestConditions(int relevance);
+    void onSubscribe(in Uri conditionId);
+    void onUnsubscribe(in Uri conditionId);
+}
\ No newline at end of file
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index 0f74169..72720d1 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -32,7 +32,7 @@
     private final String key;
 
     private final int uid;
-    private final String basePkg;
+    private final String opPkg;
     private final int initialPid;
     private final Notification notification;
     private final UserHandle user;
@@ -41,26 +41,20 @@
     private final int score;
 
     /** @hide */
-    public StatusBarNotification(String pkg, int id, String tag, int uid, int initialPid, int score,
-            Notification notification, UserHandle user) {
-        this(pkg, null, id, tag, uid, initialPid, score, notification, user);
-    }
-
-    /** @hide */
-    public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user) {
-        this(pkg, basePkg, id, tag, uid, initialPid, score, notification, user,
+        this(pkg, opPkg, id, tag, uid, initialPid, score, notification, user,
                 System.currentTimeMillis());
     }
 
-    public StatusBarNotification(String pkg, String basePkg, int id, String tag, int uid,
+    public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid,
             int initialPid, int score, Notification notification, UserHandle user,
             long postTime) {
         if (pkg == null) throw new NullPointerException();
         if (notification == null) throw new NullPointerException();
 
         this.pkg = pkg;
-        this.basePkg = pkg;
+        this.opPkg = opPkg;
         this.id = id;
         this.tag = tag;
         this.uid = uid;
@@ -75,7 +69,7 @@
 
     public StatusBarNotification(Parcel in) {
         this.pkg = in.readString();
-        this.basePkg = in.readString();
+        this.opPkg = in.readString();
         this.id = in.readInt();
         if (in.readInt() != 0) {
             this.tag = in.readString();
@@ -93,12 +87,12 @@
     }
 
     private String key() {
-        return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
+        return pkg + '|' + id + '|' + tag + '|' + uid;
     }
 
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(this.pkg);
-        out.writeString(this.basePkg);
+        out.writeString(this.opPkg);
         out.writeInt(this.id);
         if (this.tag != null) {
             out.writeInt(1);
@@ -139,14 +133,14 @@
     public StatusBarNotification cloneLight() {
         final Notification no = new Notification();
         this.notification.cloneInto(no, false); // light copy
-        return new StatusBarNotification(this.pkg, this.basePkg,
+        return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
                 this.score, no, this.user, this.postTime);
     }
 
     @Override
     public StatusBarNotification clone() {
-        return new StatusBarNotification(this.pkg, this.basePkg,
+        return new StatusBarNotification(this.pkg, this.opPkg,
                 this.id, this.tag, this.uid, this.initialPid,
                 this.score, this.notification.clone(), this.user, this.postTime);
     }
@@ -205,9 +199,9 @@
         return uid;
     }
 
-    /** The notifying app's base package. @hide */
-    public String getBasePkg() {
-        return basePkg;
+    /** The package used for AppOps tracking. @hide */
+    public String getOpPkg() {
+        return opPkg;
     }
 
     /** @hide */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/notification/ZenModeConfig.aidl
similarity index 63%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/notification/ZenModeConfig.aidl
index 0377123..c73b75e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/notification/ZenModeConfig.aidl
@@ -1,11 +1,11 @@
 /*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.notification;
 
-import android.view.View;
+parcelable ZenModeConfig;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
diff --git a/core/java/android/service/notification/ZenModeConfig.java b/core/java/android/service/notification/ZenModeConfig.java
new file mode 100644
index 0000000..925ddcf
--- /dev/null
+++ b/core/java/android/service/notification/ZenModeConfig.java
@@ -0,0 +1,234 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.notification;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.Objects;
+
+/**
+ * Persisted configuration for zen mode.
+ *
+ * @hide
+ */
+public class ZenModeConfig implements Parcelable {
+
+    public static final String SLEEP_MODE_NIGHTS = "nights";
+    public static final String SLEEP_MODE_WEEKNIGHTS = "weeknights";
+
+    private static final int XML_VERSION = 1;
+    private static final String ZEN_TAG = "zen";
+    private static final String ZEN_ATT_VERSION = "version";
+    private static final String ALLOW_TAG = "allow";
+    private static final String ALLOW_ATT_CALLS = "calls";
+    private static final String ALLOW_ATT_MESSAGES = "messages";
+    private static final String SLEEP_TAG = "sleep";
+    private static final String SLEEP_ATT_MODE = "mode";
+
+    private static final String SLEEP_ATT_START_HR = "startHour";
+    private static final String SLEEP_ATT_START_MIN = "startMin";
+    private static final String SLEEP_ATT_END_HR = "endHour";
+    private static final String SLEEP_ATT_END_MIN = "endMin";
+
+    public boolean allowCalls;
+    public boolean allowMessages;
+
+    public String sleepMode;
+    public int sleepStartHour;
+    public int sleepStartMinute;
+    public int sleepEndHour;
+    public int sleepEndMinute;
+
+    public ZenModeConfig() { }
+
+    public ZenModeConfig(Parcel source) {
+        allowCalls = source.readInt() == 1;
+        allowMessages = source.readInt() == 1;
+        if (source.readInt() == 1) {
+            sleepMode = source.readString();
+        }
+        sleepStartHour = source.readInt();
+        sleepStartMinute = source.readInt();
+        sleepEndHour = source.readInt();
+        sleepEndMinute = source.readInt();
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(allowCalls ? 1 : 0);
+        dest.writeInt(allowMessages ? 1 : 0);
+        if (sleepMode != null) {
+            dest.writeInt(1);
+            dest.writeString(sleepMode);
+        } else {
+            dest.writeInt(0);
+        }
+        dest.writeInt(sleepStartHour);
+        dest.writeInt(sleepStartMinute);
+        dest.writeInt(sleepEndHour);
+        dest.writeInt(sleepEndMinute);
+    }
+
+    @Override
+    public String toString() {
+        return new StringBuilder(ZenModeConfig.class.getSimpleName()).append('[')
+            .append("allowCalls=").append(allowCalls)
+            .append(",allowMessages=").append(allowMessages)
+            .append(",sleepMode=").append(sleepMode)
+            .append(",sleepStart=").append(sleepStartHour).append('.').append(sleepStartMinute)
+            .append(",sleepEnd=").append(sleepEndHour).append('.').append(sleepEndMinute)
+            .append(']').toString();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof ZenModeConfig)) return false;
+        if (o == this) return true;
+        final ZenModeConfig other = (ZenModeConfig) o;
+        return other.allowCalls == allowCalls
+                && other.allowMessages == allowMessages
+                && Objects.equals(other.sleepMode, sleepMode)
+                && other.sleepStartHour == sleepStartHour
+                && other.sleepStartMinute == sleepStartMinute
+                && other.sleepEndHour == sleepEndHour
+                && other.sleepEndMinute == sleepEndMinute;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(allowCalls, allowMessages, sleepMode, sleepStartHour,
+                sleepStartMinute, sleepEndHour, sleepEndMinute);
+    }
+
+    public boolean isValid() {
+        return isValidHour(sleepStartHour) && isValidMinute(sleepStartMinute)
+                && isValidHour(sleepEndHour) && isValidMinute(sleepEndMinute)
+                && (sleepMode == null || sleepMode.equals(SLEEP_MODE_NIGHTS)
+                    || sleepMode.equals(SLEEP_MODE_WEEKNIGHTS));
+    }
+
+    public static ZenModeConfig readXml(XmlPullParser parser)
+            throws XmlPullParserException, IOException {
+        int type = parser.getEventType();
+        if (type != XmlPullParser.START_TAG) return null;
+        String tag = parser.getName();
+        if (!ZEN_TAG.equals(tag)) return null;
+        final ZenModeConfig rt = new ZenModeConfig();
+        final int version = Integer.parseInt(parser.getAttributeValue(null, ZEN_ATT_VERSION));
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            tag = parser.getName();
+            if (type == XmlPullParser.END_TAG && ZEN_TAG.equals(tag)) return rt;
+            if (type == XmlPullParser.START_TAG) {
+                if (ALLOW_TAG.equals(tag)) {
+                    rt.allowCalls = safeBoolean(parser, ALLOW_ATT_CALLS, false);
+                    rt.allowMessages = safeBoolean(parser, ALLOW_ATT_MESSAGES, false);
+                } else if (SLEEP_TAG.equals(tag)) {
+                    final String mode = parser.getAttributeValue(null, SLEEP_ATT_MODE);
+                    rt.sleepMode = (SLEEP_MODE_NIGHTS.equals(mode)
+                            || SLEEP_MODE_WEEKNIGHTS.equals(mode)) ? mode : null;
+                    final int startHour = safeInt(parser, SLEEP_ATT_START_HR, 0);
+                    final int startMinute = safeInt(parser, SLEEP_ATT_START_MIN, 0);
+                    final int endHour = safeInt(parser, SLEEP_ATT_END_HR, 0);
+                    final int endMinute = safeInt(parser, SLEEP_ATT_END_MIN, 0);
+                    rt.sleepStartHour = isValidHour(startHour) ? startHour : 0;
+                    rt.sleepStartMinute = isValidMinute(startMinute) ? startMinute : 0;
+                    rt.sleepEndHour = isValidHour(endHour) ? endHour : 0;
+                    rt.sleepEndMinute = isValidMinute(endMinute) ? endMinute : 0;
+                }
+            }
+        }
+        return rt;
+    }
+
+    public void writeXml(XmlSerializer out) throws IOException {
+        out.startTag(null, ZEN_TAG);
+        out.attribute(null, ZEN_ATT_VERSION, Integer.toString(XML_VERSION));
+
+        out.startTag(null, ALLOW_TAG);
+        out.attribute(null, ALLOW_ATT_CALLS, Boolean.toString(allowCalls));
+        out.attribute(null, ALLOW_ATT_MESSAGES, Boolean.toString(allowMessages));
+        out.endTag(null, ALLOW_TAG);
+
+        out.startTag(null, SLEEP_TAG);
+        if (sleepMode != null) {
+            out.attribute(null, SLEEP_ATT_MODE, sleepMode);
+        }
+        out.attribute(null, SLEEP_ATT_START_HR, Integer.toString(sleepStartHour));
+        out.attribute(null, SLEEP_ATT_START_MIN, Integer.toString(sleepStartMinute));
+        out.attribute(null, SLEEP_ATT_END_HR, Integer.toString(sleepEndHour));
+        out.attribute(null, SLEEP_ATT_END_MIN, Integer.toString(sleepEndMinute));
+        out.endTag(null, SLEEP_TAG);
+
+        out.endTag(null, ZEN_TAG);
+    }
+
+    public static boolean isValidHour(int val) {
+        return val >= 0 && val < 24;
+    }
+
+    public static boolean isValidMinute(int val) {
+        return val >= 0 && val < 60;
+    }
+
+    private static boolean safeBoolean(XmlPullParser parser, String att, boolean defValue) {
+        final String val = parser.getAttributeValue(null, att);
+        if (TextUtils.isEmpty(val)) return defValue;
+        return Boolean.valueOf(val);
+    }
+
+    private static int safeInt(XmlPullParser parser, String att, int defValue) {
+        final String val = parser.getAttributeValue(null, att);
+        if (TextUtils.isEmpty(val)) return defValue;
+        return Integer.valueOf(val);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public ZenModeConfig copy() {
+        final Parcel parcel = Parcel.obtain();
+        try {
+            writeToParcel(parcel, 0);
+            parcel.setDataPosition(0);
+            return new ZenModeConfig(parcel);
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    public static final Parcelable.Creator<ZenModeConfig> CREATOR
+            = new Parcelable.Creator<ZenModeConfig>() {
+        @Override
+        public ZenModeConfig createFromParcel(Parcel source) {
+            return new ZenModeConfig(source);
+        }
+
+        @Override
+        public ZenModeConfig[] newArray(int size) {
+            return new ZenModeConfig[size];
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/voice/IVoiceInteractionService.aidl
similarity index 69%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/voice/IVoiceInteractionService.aidl
index 0377123..e9e2f4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/voice/IVoiceInteractionService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,10 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.voice;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
+/**
+ * @hide
+ */
+oneway interface IVoiceInteractionService {
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/voice/IVoiceInteractionSession.aidl
similarity index 66%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/voice/IVoiceInteractionSession.aidl
index 0377123..7dbf66b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/voice/IVoiceInteractionSession.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.voice;
 
-import android.view.View;
+import android.os.Bundle;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
+import com.android.internal.app.IVoiceInteractorCallback;
+import com.android.internal.app.IVoiceInteractorRequest;
+
+/**
+ * @hide
+ */
+interface IVoiceInteractionSession {
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
similarity index 65%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/service/voice/IVoiceInteractionSessionService.aidl
index 0377123..2519442 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/service/voice/IVoiceInteractionSessionService.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,15 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.service.voice;
 
-import android.view.View;
+import android.os.Bundle;
 
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
+import android.service.voice.IVoiceInteractionSession;
+
+/**
+ * @hide
+ */
+oneway interface IVoiceInteractionSessionService {
+    void newSession(IBinder token, in Bundle args);
 }
diff --git a/core/java/android/service/voice/VoiceInteractionService.java b/core/java/android/service/voice/VoiceInteractionService.java
new file mode 100644
index 0000000..d005890
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionService.java
@@ -0,0 +1,77 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.annotation.SdkConstant;
+import android.app.Instrumentation;
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IVoiceInteractionManagerService;
+
+public class VoiceInteractionService extends Service {
+    /**
+     * The {@link Intent} that must be declared as handled by the service.
+     * To be supported, the service must also require the
+     * {@link android.Manifest.permission#BIND_VOICE_INTERACTION} permission so
+     * that other applications can not abuse it.
+     */
+    @SdkConstant(SdkConstant.SdkConstantType.SERVICE_ACTION)
+    public static final String SERVICE_INTERFACE =
+            "android.service.voice.VoiceInteractionService";
+
+    /**
+     * Name under which a VoiceInteractionService component publishes information about itself.
+     * This meta-data should reference an XML resource containing a
+     * <code>&lt;{@link
+     * android.R.styleable#VoiceInteractionService voice-interaction-service}&gt;</code> tag.
+     */
+    public static final String SERVICE_META_DATA = "android.voice_interaction";
+
+    IVoiceInteractionService mInterface = new IVoiceInteractionService.Stub() {
+    };
+
+    IVoiceInteractionManagerService mSystemService;
+
+    public void startVoiceActivity(Intent intent, Bundle sessionArgs) {
+        try {
+            mSystemService.startVoiceActivity(intent,
+                    intent.resolveType(getContentResolver()),
+                    mInterface, sessionArgs);
+        } catch (RemoteException e) {
+        }
+    }
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
+                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mInterface.asBinder();
+        }
+        return null;
+    }
+}
diff --git a/core/java/android/service/voice/VoiceInteractionServiceInfo.java b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
new file mode 100644
index 0000000..a909ead
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionServiceInfo.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.Manifest;
+import android.content.ComponentName;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.content.res.XmlResourceParser;
+import android.speech.RecognitionService;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Xml;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.IOException;
+
+/** @hide */
+public class VoiceInteractionServiceInfo {
+    static final String TAG = "VoiceInteractionServiceInfo";
+
+    private String mParseError;
+
+    private ServiceInfo mServiceInfo;
+    private String mSessionService;
+    private String mSettingsActivity;
+
+    public VoiceInteractionServiceInfo(PackageManager pm, ComponentName comp)
+            throws PackageManager.NameNotFoundException {
+        this(pm, pm.getServiceInfo(comp, PackageManager.GET_META_DATA));
+    }
+
+    public VoiceInteractionServiceInfo(PackageManager pm, ServiceInfo si) {
+        if (!Manifest.permission.BIND_VOICE_INTERACTION.equals(si.permission)) {
+            mParseError = "Service does not require permission "
+                    + Manifest.permission.BIND_VOICE_INTERACTION;
+            return;
+        }
+
+        XmlResourceParser parser = null;
+        try {
+            parser = si.loadXmlMetaData(pm, VoiceInteractionService.SERVICE_META_DATA);
+            if (parser == null) {
+                mParseError = "No " + VoiceInteractionService.SERVICE_META_DATA
+                        + " meta-data for " + si.packageName;
+                return;
+            }
+
+            Resources res = pm.getResourcesForApplication(si.applicationInfo);
+
+            AttributeSet attrs = Xml.asAttributeSet(parser);
+
+            int type;
+            while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                    && type != XmlPullParser.START_TAG) {
+            }
+
+            String nodeName = parser.getName();
+            if (!"voice-interaction-service".equals(nodeName)) {
+                mParseError = "Meta-data does not start with voice-interaction-service tag";
+                return;
+            }
+
+            TypedArray array = res.obtainAttributes(attrs,
+                    com.android.internal.R.styleable.VoiceInteractionService);
+            mSessionService = array.getString(
+                    com.android.internal.R.styleable.VoiceInteractionService_sessionService);
+            mSettingsActivity = array.getString(
+                    com.android.internal.R.styleable.VoiceInteractionService_settingsActivity);
+            array.recycle();
+            if (mSessionService == null) {
+                mParseError = "No sessionService specified";
+                return;
+            }
+        } catch (XmlPullParserException e) {
+            mParseError = "Error parsing voice interation service meta-data: " + e;
+            Log.w(TAG, "error parsing voice interaction service meta-data", e);
+            return;
+        } catch (IOException e) {
+            mParseError = "Error parsing voice interation service meta-data: " + e;
+            Log.w(TAG, "error parsing voice interaction service meta-data", e);
+            return;
+        } catch (PackageManager.NameNotFoundException e) {
+            mParseError = "Error parsing voice interation service meta-data: " + e;
+            Log.w(TAG, "error parsing voice interaction service meta-data", e);
+            return;
+        } finally {
+            if (parser != null) parser.close();
+        }
+        mServiceInfo = si;
+    }
+
+    public String getParseError() {
+        return mParseError;
+    }
+
+    public ServiceInfo getServiceInfo() {
+        return mServiceInfo;
+    }
+
+    public String getSessionService() {
+        return mSessionService;
+    }
+
+    public String getSettingsActivity() {
+        return mSettingsActivity;
+    }
+}
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
new file mode 100644
index 0000000..963b6b4
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -0,0 +1,195 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.content.Context;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Message;
+import android.os.RemoteException;
+import android.util.ArrayMap;
+import android.util.Log;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.app.IVoiceInteractorCallback;
+import com.android.internal.app.IVoiceInteractorRequest;
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+public abstract class VoiceInteractionSession {
+    static final String TAG = "VoiceInteractionSession";
+    static final boolean DEBUG = true;
+
+    final IVoiceInteractor mInteractor = new IVoiceInteractor.Stub() {
+        @Override
+        public IVoiceInteractorRequest startConfirmation(String callingPackage,
+                IVoiceInteractorCallback callback, String prompt, Bundle extras) {
+            Request request = findRequest(callback, true);
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_CONFIRMATION,
+                    new Caller(callingPackage, Binder.getCallingUid()), request,
+                    prompt, extras));
+            return request.mInterface;
+        }
+
+        @Override
+        public IVoiceInteractorRequest startCommand(String callingPackage,
+                IVoiceInteractorCallback callback, String command, Bundle extras) {
+            Request request = findRequest(callback, true);
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOOOO(MSG_START_COMMAND,
+                    new Caller(callingPackage, Binder.getCallingUid()), request,
+                    command, extras));
+            return request.mInterface;
+        }
+
+        @Override
+        public boolean[] supportsCommands(String callingPackage, String[] commands) {
+            Message msg = mHandlerCaller.obtainMessageIOO(MSG_SUPPORTS_COMMANDS,
+                    0, new Caller(callingPackage, Binder.getCallingUid()), commands);
+            SomeArgs args = mHandlerCaller.sendMessageAndWait(msg);
+            if (args != null) {
+                boolean[] res = (boolean[])args.arg1;
+                args.recycle();
+                return res;
+            }
+            return new boolean[commands.length];
+        }
+    };
+
+    final IVoiceInteractionSession mSession = new IVoiceInteractionSession.Stub() {
+    };
+
+    public static class Request {
+        final IVoiceInteractorRequest mInterface = new IVoiceInteractorRequest.Stub() {
+            @Override
+            public void cancel() throws RemoteException {
+                mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageO(MSG_CANCEL, Request.this));
+            }
+        };
+        final IVoiceInteractorCallback mCallback;
+        final HandlerCaller mHandlerCaller;
+        Request(IVoiceInteractorCallback callback, HandlerCaller handlerCaller) {
+            mCallback = callback;
+            mHandlerCaller = handlerCaller;
+        }
+
+        public void sendConfirmResult(boolean confirmed, Bundle result) {
+            try {
+                if (DEBUG) Log.d(TAG, "sendConfirmResult: req=" + mInterface
+                        + " confirmed=" + confirmed + " result=" + result);
+                mCallback.deliverConfirmationResult(mInterface, confirmed, result);
+            } catch (RemoteException e) {
+            }
+        }
+
+        public void sendCommandResult(boolean complete, Bundle result) {
+            try {
+                if (DEBUG) Log.d(TAG, "sendCommandResult: req=" + mInterface
+                        + " result=" + result);
+                mCallback.deliverCommandResult(mInterface, complete, result);
+            } catch (RemoteException e) {
+            }
+        }
+
+        public void sendCancelResult() {
+            try {
+                if (DEBUG) Log.d(TAG, "sendCancelResult: req=" + mInterface);
+                mCallback.deliverCancel(mInterface);
+            } catch (RemoteException e) {
+            }
+        }
+    }
+
+    public static class Caller {
+        final String packageName;
+        final int uid;
+
+        Caller(String _packageName, int _uid) {
+            packageName = _packageName;
+            uid = _uid;
+        }
+    }
+
+    static final int MSG_START_CONFIRMATION = 1;
+    static final int MSG_START_COMMAND = 2;
+    static final int MSG_SUPPORTS_COMMANDS = 3;
+    static final int MSG_CANCEL = 4;
+
+    final Context mContext;
+    final HandlerCaller mHandlerCaller;
+    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+        @Override
+        public void executeMessage(Message msg) {
+            SomeArgs args = (SomeArgs)msg.obj;
+            switch (msg.what) {
+                case MSG_START_CONFIRMATION:
+                    if (DEBUG) Log.d(TAG, "onConfirm: req=" + ((Request) args.arg2).mInterface
+                            + " prompt=" + args.arg3 + " extras=" + args.arg4);
+                    onConfirm((Caller)args.arg1, (Request)args.arg2, (String)args.arg3,
+                            (Bundle)args.arg4);
+                    break;
+                case MSG_START_COMMAND:
+                    if (DEBUG) Log.d(TAG, "onCommand: req=" + ((Request) args.arg2).mInterface
+                            + " command=" + args.arg3 + " extras=" + args.arg4);
+                    onCommand((Caller) args.arg1, (Request) args.arg2, (String) args.arg3,
+                            (Bundle) args.arg4);
+                    break;
+                case MSG_SUPPORTS_COMMANDS:
+                    if (DEBUG) Log.d(TAG, "onGetSupportedCommands: cmds=" + args.arg2);
+                    args.arg1 = onGetSupportedCommands((Caller) args.arg1, (String[]) args.arg2);
+                    break;
+                case MSG_CANCEL:
+                    if (DEBUG) Log.d(TAG, "onCancel: req=" + ((Request) args.arg1).mInterface);
+                    onCancel((Request)args.arg1);
+                    break;
+            }
+        }
+    };
+
+    final ArrayMap<IBinder, Request> mActiveRequests = new ArrayMap<IBinder, Request>();
+
+    public VoiceInteractionSession(Context context) {
+        this(context, new Handler());
+    }
+
+    public VoiceInteractionSession(Context context, Handler handler) {
+        mContext = context;
+        mHandlerCaller = new HandlerCaller(context, handler.getLooper(),
+                mHandlerCallerCallback, true);
+    }
+
+    Request findRequest(IVoiceInteractorCallback callback, boolean newRequest) {
+        synchronized (this) {
+            Request req = mActiveRequests.get(callback.asBinder());
+            if (req != null) {
+                if (newRequest) {
+                    throw new IllegalArgumentException("Given request callback " + callback
+                            + " is already active");
+                }
+                return req;
+            }
+            req = new Request(callback, mHandlerCaller);
+            mActiveRequests.put(callback.asBinder(), req);
+            return req;
+        }
+    }
+
+    public abstract boolean[] onGetSupportedCommands(Caller caller, String[] commands);
+    public abstract void onConfirm(Caller caller, Request request, String prompt, Bundle extras);
+    public abstract void onCommand(Caller caller, Request request, String command, Bundle extras);
+    public abstract void onCancel(Request request);
+}
diff --git a/core/java/android/service/voice/VoiceInteractionSessionService.java b/core/java/android/service/voice/VoiceInteractionSessionService.java
new file mode 100644
index 0000000..40e5bba
--- /dev/null
+++ b/core/java/android/service/voice/VoiceInteractionSessionService.java
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.service.voice;
+
+import android.app.Service;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
+
+public abstract class VoiceInteractionSessionService extends Service {
+
+    static final int MSG_NEW_SESSION = 1;
+
+    IVoiceInteractionManagerService mSystemService;
+
+    IVoiceInteractionSessionService mInterface = new IVoiceInteractionSessionService.Stub() {
+        public void newSession(IBinder token, Bundle args) {
+            mHandlerCaller.sendMessage(mHandlerCaller.obtainMessageOO(MSG_NEW_SESSION,
+                    token, args));
+
+        }
+    };
+
+    HandlerCaller mHandlerCaller;
+    final HandlerCaller.Callback mHandlerCallerCallback = new HandlerCaller.Callback() {
+        @Override
+        public void executeMessage(Message msg) {
+            SomeArgs args = (SomeArgs)msg.obj;
+            switch (msg.what) {
+                case MSG_NEW_SESSION:
+                    doNewSession((IBinder)args.arg1, (Bundle)args.arg2);
+                    break;
+            }
+        }
+    };
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        mSystemService = IVoiceInteractionManagerService.Stub.asInterface(
+                ServiceManager.getService(Context.VOICE_INTERACTION_MANAGER_SERVICE));
+        mHandlerCaller = new HandlerCaller(this, Looper.myLooper(),
+                mHandlerCallerCallback, true);
+    }
+
+    public abstract VoiceInteractionSession onNewSession(Bundle args);
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mInterface.asBinder();
+    }
+
+    void doNewSession(IBinder token, Bundle args) {
+        VoiceInteractionSession session = onNewSession(args);
+        try {
+            mSystemService.deliverNewSession(token, session.mSession, session.mInteractor);
+        } catch (RemoteException e) {
+        }
+    }
+}
diff --git a/core/java/android/speech/tts/TextToSpeechClient.java b/core/java/android/speech/tts/TextToSpeechClient.java
index c6a14f2..10e2073 100644
--- a/core/java/android/speech/tts/TextToSpeechClient.java
+++ b/core/java/android/speech/tts/TextToSpeechClient.java
@@ -57,7 +57,7 @@
  * successful callback is the client usable.
  * <p>
  * After successful connection, the list of all available voices can be obtained
- * by calling the {@link TextToSpeechClient#getEngineStatus() method. The client can
+ * by calling the {@link TextToSpeechClient#getEngineStatus()} method. The client can
  * choose a voice using some custom heuristic and build a {@link RequestConfig} object
  * using {@link RequestConfig.Builder}, or can use one of the common heuristics found
  * in ({@link RequestConfigHelper}.
@@ -69,7 +69,7 @@
  * {@link ConnectionCallbacks#onEngineStatusChange} with new set of available voices as argument.
  * In response, the client HAVE to recreate all {@link RequestConfig} instances in use.
  */
-public final class TextToSpeechClient {
+public class TextToSpeechClient {
     private static final String TAG = TextToSpeechClient.class.getSimpleName();
 
     private final Object mLock = new Object();
diff --git a/core/java/android/text/BoringLayout.java b/core/java/android/text/BoringLayout.java
index 77cd71e..6f00707 100644
--- a/core/java/android/text/BoringLayout.java
+++ b/core/java/android/text/BoringLayout.java
@@ -188,10 +188,6 @@
             spacing = metrics.descent - metrics.ascent;
         }
 
-        if (spacingmult != 1 || spacingadd != 0) {
-            spacing = (int)(spacing * spacingmult + spacingadd + 0.5f);
-        }
-
         mBottom = spacing;
 
         if (includepad) {
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 638ef22..0db00f0 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -632,7 +632,11 @@
             bottom = fm.bottom;
         }
 
-        if (j == 0) {
+        boolean firstLine = (j == 0);
+        boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
+        boolean lastLine = currentLineIsTheLastVisibleOne || (end == bufEnd);
+
+        if (firstLine) {
             if (trackPad) {
                 mTopPadding = top - above;
             }
@@ -641,7 +645,10 @@
                 above = top;
             }
         }
-        if (end == bufEnd) {
+
+        int extra;
+
+        if (lastLine) {
             if (trackPad) {
                 mBottomPadding = bottom - below;
             }
@@ -651,9 +658,8 @@
             }
         }
 
-        int extra;
 
-        if (needMultiply) {
+        if (needMultiply && !lastLine) {
             double ex = (below - above) * (spacingmult - 1) + spacingadd;
             if (ex >= 0) {
                 extra = (int)(ex + EXTRA_ROUNDING);
@@ -690,8 +696,6 @@
         if (ellipsize != null) {
             // If there is only one line, then do any type of ellipsis except when it is MARQUEE
             // if there are multiple lines, just allow END ellipsis on the last line
-            boolean firstLine = (j == 0);
-            boolean currentLineIsTheLastVisibleOne = (j + 1 == mMaximumVisibleLineCount);
             boolean forceEllipsis = moreChars && (mLineCount + 1 == mMaximumVisibleLineCount);
 
             boolean doEllipsis =
diff --git a/core/java/android/text/format/Formatter.java b/core/java/android/text/format/Formatter.java
index 9c98b98..b0cbcd2 100644
--- a/core/java/android/text/format/Formatter.java
+++ b/core/java/android/text/format/Formatter.java
@@ -106,4 +106,69 @@
     public static String formatIpAddress(int ipv4Address) {
         return NetworkUtils.intToInetAddress(ipv4Address).getHostAddress();
     }
+
+    private static final int SECONDS_PER_MINUTE = 60;
+    private static final int SECONDS_PER_HOUR = 60 * 60;
+    private static final int SECONDS_PER_DAY = 24 * 60 * 60;
+
+    /**
+     * Returns elapsed time for the given millis, in the following format:
+     * 1 day 5 hrs; will include at most two units, can go down to seconds precision.
+     * @param context the application context
+     * @param millis the elapsed time in milli seconds
+     * @return the formatted elapsed time
+     * @hide
+     */
+    public static String formatShortElapsedTime(Context context, long millis) {
+        long secondsLong = millis / 1000;
+
+        int days = 0, hours = 0, minutes = 0;
+        if (secondsLong >= SECONDS_PER_DAY) {
+            days = (int)(secondsLong / SECONDS_PER_DAY);
+            secondsLong -= days * SECONDS_PER_DAY;
+        }
+        if (secondsLong >= SECONDS_PER_HOUR) {
+            hours = (int)(secondsLong / SECONDS_PER_HOUR);
+            secondsLong -= hours * SECONDS_PER_HOUR;
+        }
+        if (secondsLong >= SECONDS_PER_MINUTE) {
+            minutes = (int)(secondsLong / SECONDS_PER_MINUTE);
+            secondsLong -= minutes * SECONDS_PER_MINUTE;
+        }
+        int seconds = (int)secondsLong;
+
+        if (days >= 2) {
+            days += (hours+12)/24;
+            return context.getString(com.android.internal.R.string.durationDays, days);
+        } else if (days > 0) {
+            if (hours == 1) {
+                return context.getString(com.android.internal.R.string.durationDayHour, days, hours);
+            }
+            return context.getString(com.android.internal.R.string.durationDayHours, days, hours);
+        } else if (hours >= 2) {
+            hours += (minutes+30)/60;
+            return context.getString(com.android.internal.R.string.durationHours, hours);
+        } else if (hours > 0) {
+            if (minutes == 1) {
+                return context.getString(com.android.internal.R.string.durationHourMinute, hours,
+                        minutes);
+            }
+            return context.getString(com.android.internal.R.string.durationHourMinutes, hours,
+                    minutes);
+        } else if (minutes >= 2) {
+            minutes += (seconds+30)/60;
+            return context.getString(com.android.internal.R.string.durationMinutes, minutes);
+        } else if (minutes > 0) {
+            if (seconds == 1) {
+                return context.getString(com.android.internal.R.string.durationMinuteSecond, minutes,
+                        seconds);
+            }
+            return context.getString(com.android.internal.R.string.durationMinuteSeconds, minutes,
+                    seconds);
+        } else if (seconds == 1) {
+            return context.getString(com.android.internal.R.string.durationSecond, seconds);
+        } else {
+            return context.getString(com.android.internal.R.string.durationSeconds, seconds);
+        }
+    }
 }
diff --git a/core/java/android/transition/ChangeClipBounds.java b/core/java/android/transition/ChangeClipBounds.java
new file mode 100644
index 0000000..a61b29d
--- /dev/null
+++ b/core/java/android/transition/ChangeClipBounds.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition;
+
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.animation.RectEvaluator;
+import android.graphics.Rect;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * ChangeClipBounds captures the {@link android.view.View#getClipBounds()} before and after the
+ * scene change and animates those changes during the transition.
+ */
+public class ChangeClipBounds extends Transition {
+
+    private static final String TAG = "ChangeTransform";
+
+    private static final String PROPNAME_CLIP = "android:clipBounds:clip";
+    private static final String PROPNAME_BOUNDS = "android:clipBounds:bounds";
+
+    private static final String[] sTransitionProperties = {
+            PROPNAME_CLIP,
+    };
+
+    @Override
+    public String[] getTransitionProperties() {
+        return sTransitionProperties;
+    }
+
+    private void captureValues(TransitionValues values) {
+        View view = values.view;
+        if (view.getVisibility() == View.GONE) {
+            return;
+        }
+
+        Rect clip = view.getClipBounds();
+        values.values.put(PROPNAME_CLIP, clip);
+        if (clip == null) {
+            Rect bounds = new Rect(0, 0, view.getWidth(), view.getHeight());
+            values.values.put(PROPNAME_BOUNDS, bounds);
+        }
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        if (startValues == null || endValues == null
+                || !startValues.values.containsKey(PROPNAME_CLIP)
+                || !endValues.values.containsKey(PROPNAME_CLIP)) {
+            return null;
+        }
+        Rect start = (Rect) startValues.values.get(PROPNAME_CLIP);
+        Rect end = (Rect) endValues.values.get(PROPNAME_CLIP);
+        if (start == null && end == null) {
+            return null; // No animation required since there is no clip.
+        }
+
+        if (start == null) {
+            start = (Rect) startValues.values.get(PROPNAME_BOUNDS);
+        } else if (end == null) {
+            end = (Rect) endValues.values.get(PROPNAME_BOUNDS);
+        }
+        if (start.equals(end)) {
+            return null;
+        }
+
+        endValues.view.setClipBounds(start);
+        RectEvaluator evaluator = new RectEvaluator(new Rect());
+        return ObjectAnimator.ofObject(endValues.view, "clipBounds", evaluator, start, end);
+    }
+}
diff --git a/core/java/android/transition/ChangeTransform.java b/core/java/android/transition/ChangeTransform.java
new file mode 100644
index 0000000..85cb2c7
--- /dev/null
+++ b/core/java/android/transition/ChangeTransform.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.transition;
+
+import android.animation.Animator;
+import android.animation.FloatArrayEvaluator;
+import android.animation.ObjectAnimator;
+import android.util.FloatProperty;
+import android.util.Property;
+import android.view.View;
+import android.view.ViewGroup;
+
+/**
+ * This Transition captures scale and rotation for Views before and after the
+ * scene change and animates those changes during the transition.
+ *
+ * <p>ChangeTransform does not work when the pivot changes between scenes, so either the
+ * pivot must be set to prevent automatic pivot adjustment or the View's size must be unchanged.</p>
+ */
+public class ChangeTransform extends Transition {
+
+    private static final String TAG = "ChangeTransform";
+
+    private static final String PROPNAME_SCALE_X = "android:changeTransform:scaleX";
+    private static final String PROPNAME_SCALE_Y = "android:changeTransform:scaleY";
+    private static final String PROPNAME_ROTATION_X = "android:changeTransform:rotationX";
+    private static final String PROPNAME_ROTATION_Y = "android:changeTransform:rotationY";
+    private static final String PROPNAME_ROTATION_Z = "android:changeTransform:rotationZ";
+    private static final String PROPNAME_PIVOT_X = "android:changeTransform:pivotX";
+    private static final String PROPNAME_PIVOT_Y = "android:changeTransform:pivotY";
+
+    private static final String[] sTransitionProperties = {
+            PROPNAME_SCALE_X,
+            PROPNAME_SCALE_Y,
+            PROPNAME_ROTATION_X,
+            PROPNAME_ROTATION_Y,
+            PROPNAME_ROTATION_Z,
+    };
+
+    private static final FloatProperty<View>[] sChangedProperties = new FloatProperty[] {
+            (FloatProperty) View.SCALE_X,
+            (FloatProperty) View.SCALE_Y,
+            (FloatProperty) View.ROTATION_X,
+            (FloatProperty) View.ROTATION_Y,
+            (FloatProperty) View.ROTATION,
+    };
+
+    private static Property<View, float[]> TRANSFORMS = new Property<View, float[]>(float[].class,
+            "transforms") {
+        @Override
+        public float[] get(View object) {
+            return null;
+        }
+
+        @Override
+        public void set(View view, float[] values) {
+            for (int i = 0; i < values.length; i++) {
+                float value = values[i];
+                if (value != Float.NaN) {
+                    sChangedProperties[i].setValue(view, value);
+                }
+            }
+        }
+    };
+
+    @Override
+    public String[] getTransitionProperties() {
+        return sTransitionProperties;
+    }
+
+    private void captureValues(TransitionValues values) {
+        View view = values.view;
+        if (view.getVisibility() == View.GONE) {
+            return;
+        }
+
+        values.values.put(PROPNAME_SCALE_X, view.getScaleX());
+        values.values.put(PROPNAME_SCALE_Y, view.getScaleY());
+        values.values.put(PROPNAME_PIVOT_X, view.getPivotX());
+        values.values.put(PROPNAME_PIVOT_Y, view.getPivotY());
+        values.values.put(PROPNAME_ROTATION_X, view.getRotationX());
+        values.values.put(PROPNAME_ROTATION_Y, view.getRotationY());
+        values.values.put(PROPNAME_ROTATION_Z, view.getRotation());
+    }
+
+    @Override
+    public void captureStartValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public void captureEndValues(TransitionValues transitionValues) {
+        captureValues(transitionValues);
+    }
+
+    @Override
+    public Animator createAnimator(final ViewGroup sceneRoot, TransitionValues startValues,
+            TransitionValues endValues) {
+        if (startValues == null || endValues == null
+                || !startValues.values.containsKey(PROPNAME_SCALE_X)
+                || !endValues.values.containsKey(PROPNAME_SCALE_X)
+                || !isPivotSame(startValues, endValues)
+                || !isChanged(startValues, endValues)) {
+            return null;
+        }
+
+        float[] start = createValues(startValues);
+        float[] end = createValues(endValues);
+        for (int i = 0; i < start.length; i++) {
+            if (start[i] == end[i]) {
+                start[i] = Float.NaN;
+                end[i] = Float.NaN;
+            } else {
+                sChangedProperties[i].setValue(endValues.view, start[i]);
+            }
+        }
+        FloatArrayEvaluator evaluator = new FloatArrayEvaluator(new float[start.length]);
+        return ObjectAnimator.ofObject(endValues.view, TRANSFORMS, evaluator, start, end);
+    }
+
+    private static float[] createValues(TransitionValues transitionValues) {
+        float[] values = new float[sChangedProperties.length];
+        for (int i = 0; i < values.length; i++) {
+            values[i] = (Float) transitionValues.values.get(sTransitionProperties[i]);
+        }
+        return values;
+    }
+
+    private static boolean isPivotSame(TransitionValues startValues, TransitionValues endValues) {
+        float startPivotX = (Float) startValues.values.get(PROPNAME_PIVOT_X);
+        float startPivotY = (Float) startValues.values.get(PROPNAME_PIVOT_Y);
+        float endPivotX = (Float) endValues.values.get(PROPNAME_PIVOT_X);
+        float endPivotY = (Float) endValues.values.get(PROPNAME_PIVOT_Y);
+
+        // We don't support pivot changes, because they could be automatically set
+        // and we can't end the state in an automatic state.
+        return startPivotX == endPivotX && startPivotY == endPivotY;
+    }
+
+    private static boolean isChanged(TransitionValues startValues, TransitionValues endValues) {
+        for (int i = 0; i < sChangedProperties.length; i++) {
+            Object start = startValues.values.get(sTransitionProperties[i]);
+            Object end = endValues.values.get(sTransitionProperties[i]);
+            if (!start.equals(end)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}
diff --git a/core/java/android/transition/CircularPropagation.java b/core/java/android/transition/CircularPropagation.java
index 18a3d22..51beb51 100644
--- a/core/java/android/transition/CircularPropagation.java
+++ b/core/java/android/transition/CircularPropagation.java
@@ -34,7 +34,7 @@
 public class CircularPropagation extends VisibilityPropagation {
     private static final String TAG = "CircularPropagation";
 
-    private float mPropagationSpeed = 4.0f;
+    private float mPropagationSpeed = 3.0f;
 
     /**
      * Sets the speed at which transition propagation happens, relative to the duration of the
@@ -91,8 +91,12 @@
         float maxDistance = distance(0, 0, sceneRoot.getWidth(), sceneRoot.getHeight());
         float distanceFraction = distance/maxDistance;
 
-        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
-                * distanceFraction);
+        long duration = transition.getDuration();
+        if (duration < 0) {
+            duration = 300;
+        }
+
+        return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction);
     }
 
     private static float distance(float x1, float y1, float x2, float y2) {
diff --git a/core/java/android/transition/Fade.java b/core/java/android/transition/Fade.java
index 08e27d3..e70dc0c 100644
--- a/core/java/android/transition/Fade.java
+++ b/core/java/android/transition/Fade.java
@@ -105,7 +105,7 @@
         if (DBG) {
             Log.d(LOG_TAG, "Created animator " + anim);
         }
-        FadeAnimatorListener listener = new FadeAnimatorListener(view, endAlpha);
+        FadeAnimatorListener listener = new FadeAnimatorListener(view);
         anim.addListener(listener);
         anim.addPauseListener(listener);
         return anim;
@@ -138,13 +138,11 @@
 
     private static class FadeAnimatorListener extends AnimatorListenerAdapter {
         private final View mView;
-        private final float mEndAlpha;
         private boolean mCanceled = false;
-        private float mPausedAlpha;
+        private float mPausedAlpha = -1;
 
-        public FadeAnimatorListener(View view, float endAlpha) {
+        public FadeAnimatorListener(View view) {
             mView = view;
-            mEndAlpha = endAlpha;
         }
 
         @Override
@@ -158,14 +156,14 @@
         @Override
         public void onAnimationEnd(Animator animator) {
             if (!mCanceled) {
-                mView.setTransitionAlpha(mEndAlpha);
+                mView.setTransitionAlpha(1);
             }
         }
 
         @Override
         public void onAnimationPause(Animator animator) {
             mPausedAlpha = mView.getTransitionAlpha();
-            mView.setTransitionAlpha(mEndAlpha);
+            mView.setTransitionAlpha(1);
         }
 
         @Override
diff --git a/core/java/android/transition/MoveImage.java b/core/java/android/transition/MoveImage.java
index d68e971..e4c3939 100644
--- a/core/java/android/transition/MoveImage.java
+++ b/core/java/android/transition/MoveImage.java
@@ -170,13 +170,20 @@
 
         drawable = drawable.getConstantState().newDrawable();
         final MatrixClippedDrawable matrixClippedDrawable = new MatrixClippedDrawable(drawable);
+        final ImageView overlayImage = new ImageView(imageView.getContext());
+        final ViewGroupOverlay overlay = sceneRoot.getOverlay();
+        overlay.add(overlayImage);
+        overlayImage.setLeft(0);
+        overlayImage.setTop(0);
+        overlayImage.setRight(sceneRoot.getWidth());
+        overlayImage.setBottom(sceneRoot.getBottom());
+        overlayImage.setScaleType(ImageView.ScaleType.MATRIX);
+        overlayImage.setImageDrawable(matrixClippedDrawable);
         matrixClippedDrawable.setMatrix(startMatrix);
         matrixClippedDrawable.setBounds(startBounds);
         matrixClippedDrawable.setClipRect(startClip);
 
         imageView.setVisibility(View.INVISIBLE);
-        final ViewGroupOverlay overlay = sceneRoot.getOverlay();
-        overlay.add(matrixClippedDrawable);
         ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(matrixClippedDrawable,
                 changes.toArray(new PropertyValuesHolder[changes.size()]));
 
@@ -184,19 +191,24 @@
             @Override
             public void onAnimationEnd(Animator animation) {
                 imageView.setVisibility(View.VISIBLE);
-                overlay.remove(matrixClippedDrawable);
+                overlay.remove(overlayImage);
             }
 
             @Override
             public void onAnimationPause(Animator animation) {
                 imageView.setVisibility(View.VISIBLE);
-                overlay.remove(matrixClippedDrawable);
+                overlayImage.setVisibility(View.INVISIBLE);
             }
 
             @Override
             public void onAnimationResume(Animator animation) {
                 imageView.setVisibility(View.INVISIBLE);
-                overlay.add(matrixClippedDrawable);
+                overlayImage.setVisibility(View.VISIBLE);
+            }
+
+            @Override
+            public void onAnimationCancel(Animator animation) {
+                onAnimationEnd(animation);
             }
         };
 
diff --git a/core/java/android/transition/SidePropagation.java b/core/java/android/transition/SidePropagation.java
index c331945..5d38ac8 100644
--- a/core/java/android/transition/SidePropagation.java
+++ b/core/java/android/transition/SidePropagation.java
@@ -52,7 +52,7 @@
      */
     public static final int BOTTOM = Slide.BOTTOM;
 
-    private float mPropagationSpeed = 4.0f;
+    private float mPropagationSpeed = 3.0f;
     private int mSide = BOTTOM;
 
     /**
@@ -129,8 +129,12 @@
         float maxDistance = getMaxDistance(sceneRoot);
         float distanceFraction = distance/maxDistance;
 
-        return Math.round(transition.getDuration() * directionMultiplier / mPropagationSpeed
-                * distanceFraction);
+        long duration = transition.getDuration();
+        if (duration < 0) {
+            duration = 300;
+        }
+
+        return Math.round(duration * directionMultiplier / mPropagationSpeed * distanceFraction);
     }
 
     private int distance(int viewX, int viewY, int epicenterX, int epicenterY,
diff --git a/core/java/android/transition/Transition.java b/core/java/android/transition/Transition.java
index b7ae31e..2549fde 100644
--- a/core/java/android/transition/Transition.java
+++ b/core/java/android/transition/Transition.java
@@ -66,13 +66,12 @@
  *
  * {@sample development/samples/ApiDemos/res/transition/changebounds.xml ChangeBounds}
  *
- * <p>{@link android.transition.Explode} transition:</p>
+ * <p>This TransitionSet contains {@link android.transition.Explode} for visibility,
+ * {@link android.transition.ChangeBounds}, {@link android.transition.ChangeTransform},
+ * and {@link android.transition.ChangeClipBounds} for non-<code>ImageView</code>s and
+ * {@link android.transition.MoveImage} for <code>ImageView</code>s:</p>
  *
- * {@sample development/samples/ApiDemos/res/transition/explode.xml Explode}
- *
- * <p>{@link android.transition.MoveImage} transition:</p>
- *
- * {@sample development/samples/ApiDemos/res/transition/move_image.xml MoveImage}
+ * {@sample development/samples/ApiDemos/res/transition/explode_move_together.xml MultipleTransform}
  *
  * <p>Note that attributes for the transition are not required, just as they are
  * optional when declared in code; Transitions created from XML resources will use
@@ -89,7 +88,8 @@
  * transition uses a fadingMode of {@link Fade#OUT} instead of the default
  * out-in behavior. Finally, note the use of the <code>targets</code> sub-tag, which
  * takes a set of {@link android.R.styleable#TransitionTarget target} tags, each
- * of which lists a specific <code>targetId</code> which this transition acts upon.
+ * of which lists a specific <code>targetId</code>, <code>targetClass</code>,
+ * <code>excludeId</code>, or <code>excludeClass</code>, which this transition acts upon.
  * Use of targets is optional, but can be used to either limit the time spent checking
  * attributes on unchanging views, or limiting the types of animations run on specific views.
  * In this case, we know that only the <code>grayscaleContainer</code> will be
@@ -116,6 +116,7 @@
     ArrayList<Integer> mTargetIdExcludes = null;
     ArrayList<View> mTargetExcludes = null;
     ArrayList<Class> mTargetTypeExcludes = null;
+    ArrayList<Class> mTargetTypes = null;
     ArrayList<Integer> mTargetIdChildExcludes = null;
     ArrayList<View> mTargetChildExcludes = null;
     ArrayList<Class> mTargetTypeChildExcludes = null;
@@ -569,19 +570,15 @@
                 }
             }
         }
-        if (mTargetIds.size() == 0 && mTargets.size() == 0) {
+        if (mTargetIds.size() == 0 && mTargets.size() == 0 && mTargetTypes == null) {
             return true;
         }
-        if (mTargetIds.size() > 0) {
-            for (int i = 0; i < mTargetIds.size(); ++i) {
-                if (mTargetIds.get(i) == targetId) {
-                    return true;
-                }
-            }
+        if (mTargetIds.contains((int) targetId) || mTargets.contains(target)) {
+            return true;
         }
-        if (target != null && mTargets.size() > 0) {
-            for (int i = 0; i < mTargets.size(); ++i) {
-                if (mTargets.get(i) == target) {
+        if (mTargetTypes != null) {
+            for (int i = 0; i < mTargetTypes.size(); ++i) {
+                if (mTargetTypes.get(i).isInstance(target)) {
                     return true;
                 }
             }
@@ -727,6 +724,36 @@
     }
 
     /**
+     * Adds the Class of a target view that this Transition is interested in
+     * animating. By default, there are no targetTypes, and a Transition will
+     * listen for changes on every view in the hierarchy below the sceneRoot
+     * of the Scene being transitioned into. Setting targetTypes constrains
+     * the Transition to only listen for, and act on, views with these classes.
+     * Views with different classes will be ignored.
+     *
+     * <p>Note that any View that can be cast to targetType will be included, so
+     * if targetType is <code>View.class</code>, all Views will be included.</p>
+     *
+     * @see #addTarget(int)
+     * @see #addTarget(android.view.View)
+     * @see #excludeTarget(Class, boolean)
+     * @see #excludeChildren(Class, boolean)
+     *
+     * @param targetType The type to include when running this transition.
+     * @return The Transition to which the target class was added.
+     * Returning the same object makes it easier to chain calls during
+     * construction, such as
+     * <code>transitionSet.addTransitions(new Fade()).addTarget(ImageView.class);</code>
+     */
+    public Transition addTarget(Class targetType) {
+        if (mTargetTypes == null) {
+            mTargetTypes = new ArrayList<Class>();
+        }
+        mTargetTypes.add(targetType);
+        return this;
+    }
+
+    /**
      * Removes the given targetId from the list of ids that this Transition
      * is interested in animating.
      *
@@ -1116,9 +1143,6 @@
         if (view == null) {
             return;
         }
-        if (!isValidTarget(view, view.getId())) {
-            return;
-        }
         boolean isListViewItem = false;
         if (view.getParent() instanceof ListView) {
             isListViewItem = true;
@@ -1585,7 +1609,7 @@
      * hierarchy underneath it.
      */
     void capturePropagationValues(TransitionValues transitionValues) {
-        if (mPropagation != null) {
+        if (mPropagation != null && !transitionValues.values.isEmpty()) {
             String[] propertyNames = mPropagation.getPropagationProperties();
             if (propertyNames == null) {
                 return;
diff --git a/core/java/android/transition/TransitionInflater.java b/core/java/android/transition/TransitionInflater.java
index f675c6a..a5e960a 100644
--- a/core/java/android/transition/TransitionInflater.java
+++ b/core/java/android/transition/TransitionInflater.java
@@ -153,6 +153,12 @@
             } else if ("moveImage".equals(name)) {
                 transition = new MoveImage();
                 newTransition = true;
+            } else if ("changeTransform".equals(name)) {
+                transition = new ChangeTransform();
+                newTransition = true;
+            } else if ("changeClipBounds".equals(name)) {
+                transition = new ChangeClipBounds();
+                newTransition = true;
             } else if ("autoTransition".equals(name)) {
                 transition = new AutoTransition();
                 newTransition = true;
@@ -210,7 +216,6 @@
         int type;
         int depth = parser.getDepth();
 
-        ArrayList<Integer> targetIds = new ArrayList<Integer>();
         while (((type=parser.next()) != XmlPullParser.END_TAG || parser.getDepth() > depth)
                 && type != XmlPullParser.END_DOCUMENT) {
 
@@ -225,18 +230,31 @@
                 int id = a.getResourceId(
                         com.android.internal.R.styleable.TransitionTarget_targetId, -1);
                 if (id >= 0) {
-                    targetIds.add(id);
+                    transition.addTarget(id);
+                } else if ((id = a.getResourceId(
+                        com.android.internal.R.styleable.TransitionTarget_excludeId, -1)) >= 0) {
+                    transition.excludeTarget(id, true);
+                } else {
+                    String className = a.getString(
+                            com.android.internal.R.styleable.TransitionTarget_excludeClass);
+                    try {
+                        if (className != null) {
+                            Class clazz = Class.forName(className);
+                            transition.excludeTarget(clazz, true);
+                        } else if ((className = a.getString(
+                                com.android.internal.R.styleable.TransitionTarget_targetClass))
+                                != null) {
+                            Class clazz = Class.forName(className);
+                            transition.addTarget(clazz);
+                        }
+                    } catch (ClassNotFoundException e) {
+                        throw new RuntimeException("Could not create " + className, e);
+                    }
                 }
             } else {
                 throw new RuntimeException("Unknown scene name: " + parser.getName());
             }
         }
-        int numTargets = targetIds.size();
-        if (numTargets > 0) {
-            for (int i = 0; i < numTargets; ++i) {
-                transition.addTarget(targetIds.get(i));
-            }
-        }
     }
 
     private Transition loadTransition(Transition transition, AttributeSet attrs)
@@ -309,15 +327,11 @@
         if (transitionId >= 0) {
             Transition transition = inflateTransition(transitionId);
             if (transition != null) {
+                if (toScene == null) {
+                    throw new RuntimeException("No toScene for transition ID " + transitionId);
+                }
                 if (fromScene == null) {
-                    if (toScene == null) {
-                        throw new RuntimeException("No matching fromScene or toScene " +
-                                "for transition ID " + transitionId);
-                    } else {
-                        transitionManager.setTransition(toScene, transition);
-                    }
-                } else if (toScene == null) {
-                    transitionManager.setExitTransition(fromScene, transition);
+                    transitionManager.setTransition(toScene, transition);
                 } else {
                     transitionManager.setTransition(fromScene, toScene, transition);
                 }
diff --git a/core/java/android/transition/TransitionManager.java b/core/java/android/transition/TransitionManager.java
index 1614d34..ce3cc2f 100644
--- a/core/java/android/transition/TransitionManager.java
+++ b/core/java/android/transition/TransitionManager.java
@@ -70,7 +70,6 @@
     private static final String[] EMPTY_STRINGS = new String[0];
 
     ArrayMap<Scene, Transition> mSceneTransitions = new ArrayMap<Scene, Transition>();
-    ArrayMap<Scene, Transition> mExitSceneTransitions = new ArrayMap<Scene, Transition>();
     ArrayMap<Scene, ArrayMap<Scene, Transition>> mScenePairTransitions =
             new ArrayMap<Scene, ArrayMap<Scene, Transition>>();
     private static ThreadLocal<WeakReference<ArrayMap<ViewGroup, ArrayList<Transition>>>>
@@ -119,21 +118,6 @@
     }
 
     /**
-     * Sets a specific transition to occur when the given scene is exited. This
-     * has the lowest priority -- if a Scene-to-Scene transition or
-     * Scene enter transition can be applied, it will.
-     *
-     * @param scene The scene which, when exited, will cause the given
-     * transition to run.
-     * @param transition The transition that will play when the given scene is
-     * exited. A value of null will result in the default behavior of
-     * using the default transition instead.
-     */
-    public void setExitTransition(Scene scene, Transition transition) {
-        mExitSceneTransitions.put(scene, transition);
-    }
-
-    /**
      * Sets a specific transition to occur when the given pair of scenes is
      * exited/entered.
      *
@@ -181,9 +165,6 @@
             }
         }
         transition = mSceneTransitions.get(scene);
-        if (transition == null && sceneRoot != null) {
-            transition = mExitSceneTransitions.get(Scene.getCurrentScene(sceneRoot));
-        }
         return (transition != null) ? transition : sDefaultTransition;
     }
 
@@ -239,34 +220,6 @@
     }
 
     /**
-     * Retrieve the transition to a target defined scene if one has been
-     * associated with this TransitionManager.
-     *
-     * @param toScene Target scene that this transition will move to
-     * @return Transition corresponding to the given toScene or null
-     *         if no association exists in this TransitionManager
-     *
-     * @see #setTransition(Scene, Transition)
-     * @hide
-     */
-    public Transition getEnterTransition(Scene toScene) {
-        return mSceneTransitions.get(toScene);
-    }
-
-    /**
-     * Retrieve the transition from a defined scene to a target named scene if one has been
-     * associated with this TransitionManager.
-     *
-     * @param fromScene Scene that this transition starts from
-     * @return Transition corresponding to the given fromScene or null
-     *         if no association exists in this TransitionManager
-     * @hide
-     */
-    public Transition getExitTransition(Scene fromScene) {
-        return mExitSceneTransitions.get(fromScene);
-    }
-
-    /**
      * This private utility class is used to listen for both OnPreDraw and
      * OnAttachStateChange events. OnPreDraw events are the main ones we care
      * about since that's what triggers the transition to take place.
diff --git a/core/java/android/transition/TransitionSet.java b/core/java/android/transition/TransitionSet.java
index 966b24d..9081234 100644
--- a/core/java/android/transition/TransitionSet.java
+++ b/core/java/android/transition/TransitionSet.java
@@ -256,11 +256,45 @@
     @Override
     protected void createAnimators(ViewGroup sceneRoot, TransitionValuesMaps startValues,
             TransitionValuesMaps endValues) {
+        startValues = removeExcludes(startValues);
+        endValues = removeExcludes(endValues);
         for (Transition childTransition : mTransitions) {
             childTransition.createAnimators(sceneRoot, startValues, endValues);
         }
     }
 
+    private TransitionValuesMaps removeExcludes(TransitionValuesMaps values) {
+        if (mTargetIds.isEmpty() && mTargetIdExcludes == null && mTargetTypeExcludes == null
+                && mTargets.isEmpty()) {
+            return values;
+        }
+        TransitionValuesMaps included = new TransitionValuesMaps();
+        int numValues = values.viewValues.size();
+        for (int i = 0; i < numValues; i++) {
+            View view = values.viewValues.keyAt(i);
+            if (isValidTarget(view, view.getId())) {
+                included.viewValues.put(view, values.viewValues.valueAt(i));
+            }
+        }
+        numValues = values.idValues.size();
+        for (int i = 0; i < numValues; i++) {
+            int id = values.idValues.keyAt(i);
+            TransitionValues transitionValues = values.idValues.valueAt(i);
+            if (isValidTarget(transitionValues.view, id)) {
+                included.idValues.put(id, transitionValues);
+            }
+        }
+        numValues = values.itemIdValues.size();
+        for (int i = 0; i < numValues; i++) {
+            long id = values.itemIdValues.keyAt(i);
+            TransitionValues transitionValues = values.itemIdValues.valueAt(i);
+            if (isValidTarget(transitionValues.view, id)) {
+                included.itemIdValues.put(id, transitionValues);
+            }
+        }
+        return included;
+    }
+
     /**
      * @hide
      */
diff --git a/core/java/android/transition/Visibility.java b/core/java/android/transition/Visibility.java
index 7783b6f..6e6496c 100644
--- a/core/java/android/transition/Visibility.java
+++ b/core/java/android/transition/Visibility.java
@@ -109,14 +109,14 @@
         final VisibilityInfo visInfo = new VisibilityInfo();
         visInfo.visibilityChange = false;
         visInfo.fadeIn = false;
-        if (startValues != null) {
+        if (startValues != null && startValues.values.containsKey(PROPNAME_VISIBILITY)) {
             visInfo.startVisibility = (Integer) startValues.values.get(PROPNAME_VISIBILITY);
             visInfo.startParent = (ViewGroup) startValues.values.get(PROPNAME_PARENT);
         } else {
             visInfo.startVisibility = -1;
             visInfo.startParent = null;
         }
-        if (endValues != null) {
+        if (endValues != null && endValues.values.containsKey(PROPNAME_VISIBILITY)) {
             visInfo.endVisibility = (Integer) endValues.values.get(PROPNAME_VISIBILITY);
             visInfo.endParent = (ViewGroup) endValues.values.get(PROPNAME_PARENT);
         } else {
@@ -347,10 +347,11 @@
         }
 
         if (viewToKeep != null) {
+            int originalVisibility = viewToKeep.getVisibility();
             viewToKeep.setVisibility(View.VISIBLE);
             Animator animator = onDisappear(sceneRoot, viewToKeep, startValues, endValues);
             if (animator == null) {
-                viewToKeep.setVisibility(finalVisibility);
+                viewToKeep.setVisibility(originalVisibility);
             } else {
                 final View finalViewToKeep = viewToKeep;
                 animator.addListener(new AnimatorListenerAdapter() {
diff --git a/core/java/android/tv/ITvInputClient.aidl b/core/java/android/tv/ITvInputClient.aidl
index 43be6f0..538f8a1 100644
--- a/core/java/android/tv/ITvInputClient.aidl
+++ b/core/java/android/tv/ITvInputClient.aidl
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.tv.ITvInputSession;
+import android.view.InputChannel;
 
 /**
  * Interface a client of the ITvInputManager implements, to identify itself and receive information
@@ -25,6 +26,6 @@
  * @hide
  */
 oneway interface ITvInputClient {
-    void onSessionCreated(in ComponentName name, IBinder token, int seq);
+    void onSessionCreated(in ComponentName name, IBinder token, in InputChannel channel, int seq);
     void onAvailabilityChanged(in ComponentName name, boolean isAvailable);
 }
diff --git a/core/java/android/tv/ITvInputManager.aidl b/core/java/android/tv/ITvInputManager.aidl
index a927dc9..a4c99e4 100644
--- a/core/java/android/tv/ITvInputManager.aidl
+++ b/core/java/android/tv/ITvInputManager.aidl
@@ -17,6 +17,7 @@
 package android.tv;
 
 import android.content.ComponentName;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.tv.ITvInputClient;
 import android.tv.TvInputInfo;
@@ -40,4 +41,9 @@
     void setSurface(in IBinder sessionToken, in Surface surface, int userId);
     void setVolume(in IBinder sessionToken, float volume, int userId);
     void tune(in IBinder sessionToken, in Uri channelUri, int userId);
+
+    void createOverlayView(in IBinder sessionToken, in IBinder windowToken, in Rect frame,
+            int userId);
+    void relayoutOverlayView(in IBinder sessionToken, in Rect frame, int userId);
+    void removeOverlayView(in IBinder sessionToken, int userId);
 }
diff --git a/core/java/android/tv/ITvInputService.aidl b/core/java/android/tv/ITvInputService.aidl
index d80f286..4f1bc2b 100644
--- a/core/java/android/tv/ITvInputService.aidl
+++ b/core/java/android/tv/ITvInputService.aidl
@@ -17,8 +17,8 @@
 package android.tv;
 
 import android.tv.ITvInputServiceCallback;
-import android.tv.ITvInputSession;
 import android.tv.ITvInputSessionCallback;
+import android.view.InputChannel;
 
 /**
  * Top-level interface to a TV input component (implemented in a Service).
@@ -27,5 +27,5 @@
 oneway interface ITvInputService {
     void registerCallback(ITvInputServiceCallback callback);
     void unregisterCallback(in ITvInputServiceCallback callback);
-    void createSession(ITvInputSessionCallback callback);
+    void createSession(in InputChannel channel, ITvInputSessionCallback callback);
 }
diff --git a/core/java/android/tv/ITvInputSession.aidl b/core/java/android/tv/ITvInputSession.aidl
index d379d2d..32fee4b 100644
--- a/core/java/android/tv/ITvInputSession.aidl
+++ b/core/java/android/tv/ITvInputSession.aidl
@@ -16,6 +16,7 @@
 
 package android.tv;
 
+import android.graphics.Rect;
 import android.net.Uri;
 import android.view.Surface;
 
@@ -31,4 +32,8 @@
     // is to introduce some new concepts that will solve a number of problems in audio policy today.
     void setVolume(float volume);
     void tune(in Uri channelUri);
+
+    void createOverlayView(in IBinder windowToken, in Rect frame);
+    void relayoutOverlayView(in Rect frame);
+    void removeOverlayView();
 }
diff --git a/core/java/android/tv/ITvInputSessionWrapper.java b/core/java/android/tv/ITvInputSessionWrapper.java
index fd4e1e3..3ccccf3 100644
--- a/core/java/android/tv/ITvInputSessionWrapper.java
+++ b/core/java/android/tv/ITvInputSessionWrapper.java
@@ -17,12 +17,23 @@
 package android.tv;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.net.Uri;
+import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
+import android.tv.TvInputManager.Session;
+import android.tv.TvInputService.TvInputSessionImpl;
 import android.util.Log;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.Surface;
 
 import com.android.internal.os.HandlerCaller;
+import com.android.internal.os.SomeArgs;
 
 /**
  * Implements the internal ITvInputSession interface to convert incoming calls on to it back to
@@ -37,37 +48,70 @@
     private static final int DO_SET_SURFACE = 2;
     private static final int DO_SET_VOLUME = 3;
     private static final int DO_TUNE = 4;
+    private static final int DO_CREATE_OVERLAY_VIEW = 5;
+    private static final int DO_RELAYOUT_OVERLAY_VIEW = 6;
+    private static final int DO_REMOVE_OVERLAY_VIEW = 7;
 
-    private TvInputSession mTvInputSession;
     private final HandlerCaller mCaller;
 
-    public ITvInputSessionWrapper(Context context, TvInputSession session) {
+    private TvInputSessionImpl mTvInputSessionImpl;
+    private InputChannel mChannel;
+    private TvInputEventReceiver mReceiver;
+
+    public ITvInputSessionWrapper(Context context, TvInputSessionImpl sessionImpl,
+            InputChannel channel) {
         mCaller = new HandlerCaller(context, null, this, true /* asyncHandler */);
-        mTvInputSession = session;
+        mTvInputSessionImpl = sessionImpl;
+        mChannel = channel;
+        if (channel != null) {
+            mReceiver = new TvInputEventReceiver(channel, context.getMainLooper());
+        }
     }
 
     @Override
     public void executeMessage(Message msg) {
-        if (mTvInputSession == null) {
+        if (mTvInputSessionImpl == null) {
             return;
         }
 
         switch (msg.what) {
             case DO_RELEASE: {
-                mTvInputSession.release();
-                mTvInputSession = null;
+                mTvInputSessionImpl.release();
+                mTvInputSessionImpl = null;
+                if (mReceiver != null) {
+                    mReceiver.dispose();
+                    mReceiver = null;
+                }
+                if (mChannel != null) {
+                    mChannel.dispose();
+                    mChannel = null;
+                }
                 return;
             }
             case DO_SET_SURFACE: {
-                mTvInputSession.setSurface((Surface) msg.obj);
+                mTvInputSessionImpl.setSurface((Surface) msg.obj);
                 return;
             }
             case DO_SET_VOLUME: {
-                mTvInputSession.setVolume((Float) msg.obj);
+                mTvInputSessionImpl.setVolume((Float) msg.obj);
                 return;
             }
             case DO_TUNE: {
-                mTvInputSession.tune((Uri) msg.obj);
+                mTvInputSessionImpl.tune((Uri) msg.obj);
+                return;
+            }
+            case DO_CREATE_OVERLAY_VIEW: {
+                SomeArgs args = (SomeArgs) msg.obj;
+                mTvInputSessionImpl.createOverlayView((IBinder) args.arg1, (Rect) args.arg2);
+                args.recycle();
+                return;
+            }
+            case DO_RELAYOUT_OVERLAY_VIEW: {
+                mTvInputSessionImpl.relayoutOverlayView((Rect) msg.obj);
+                return;
+            }
+            case DO_REMOVE_OVERLAY_VIEW: {
+                mTvInputSessionImpl.removeOverlayView(true);
                 return;
             }
             default: {
@@ -96,4 +140,40 @@
     public void tune(Uri channelUri) {
         mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_TUNE, channelUri));
     }
+
+    @Override
+    public void createOverlayView(IBinder windowToken, Rect frame) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageOO(DO_CREATE_OVERLAY_VIEW, windowToken,
+                frame));
+    }
+
+    @Override
+    public void relayoutOverlayView(Rect frame) {
+        mCaller.executeOrSendMessage(mCaller.obtainMessageO(DO_RELAYOUT_OVERLAY_VIEW, frame));
+    }
+
+    @Override
+    public void removeOverlayView() {
+        mCaller.executeOrSendMessage(mCaller.obtainMessage(DO_REMOVE_OVERLAY_VIEW));
+    }
+
+    private final class TvInputEventReceiver extends InputEventReceiver {
+        public TvInputEventReceiver(InputChannel inputChannel, Looper looper) {
+            super(inputChannel, looper);
+        }
+
+        @Override
+        public void onInputEvent(InputEvent event) {
+            if (mTvInputSessionImpl == null) {
+                // The session has been finished.
+                finishInputEvent(event, false);
+                return;
+            }
+
+            int handled = mTvInputSessionImpl.dispatchInputEvent(event, this);
+            if (handled != Session.DISPATCH_IN_PROGRESS) {
+                finishInputEvent(event, handled == Session.DISPATCH_HANDLED);
+            }
+        }
+    }
 }
diff --git a/core/java/android/tv/TvInputInfo.java b/core/java/android/tv/TvInputInfo.java
index 90625d8..90e4177 100644
--- a/core/java/android/tv/TvInputInfo.java
+++ b/core/java/android/tv/TvInputInfo.java
@@ -87,6 +87,34 @@
         return 0;
     }
 
+    @Override
+    public int hashCode() {
+        return mId.hashCode();
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o == this) {
+            return true;
+        }
+
+        if (!(o instanceof TvInputInfo)) {
+            return false;
+        }
+
+        TvInputInfo obj = (TvInputInfo) o;
+        return mId.equals(obj.mId)
+                && mService.serviceInfo.packageName.equals(obj.mService.serviceInfo.packageName)
+                && mService.serviceInfo.name.equals(obj.mService.serviceInfo.name);
+    }
+
+    @Override
+    public String toString() {
+        return "TvInputInfo{id=" + mId
+                + ", pkg=" + mService.serviceInfo.packageName
+                + ", service=" + mService.serviceInfo.name + "}";
+    }
+
     /**
      * Used to package this object into a {@link Parcel}.
      *
diff --git a/core/java/android/tv/TvInputManager.java b/core/java/android/tv/TvInputManager.java
index 0b6ab64..7b9b1fb 100644
--- a/core/java/android/tv/TvInputManager.java
+++ b/core/java/android/tv/TvInputManager.java
@@ -17,13 +17,22 @@
 package android.tv;
 
 import android.content.ComponentName;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.Pools.Pool;
+import android.util.Pools.SimplePool;
 import android.util.SparseArray;
+import android.view.InputChannel;
+import android.view.InputEvent;
+import android.view.InputEventSender;
 import android.view.Surface;
+import android.view.View;
 
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -136,7 +145,8 @@
         mUserId = userId;
         mClient = new ITvInputClient.Stub() {
             @Override
-            public void onSessionCreated(ComponentName name, IBinder token, int seq) {
+            public void onSessionCreated(ComponentName name, IBinder token, InputChannel channel,
+                    int seq) {
                 synchronized (mSessionCreateCallbackRecordMap) {
                     SessionCreateCallbackRecord record = mSessionCreateCallbackRecordMap.get(seq);
                     mSessionCreateCallbackRecordMap.delete(seq);
@@ -146,7 +156,7 @@
                     }
                     Session session = null;
                     if (token != null) {
-                        session = new Session(name, token, mService, mUserId);
+                        session = new Session(token, channel, mService, mUserId);
                     }
                     record.postSessionCreated(session);
                 }
@@ -282,7 +292,7 @@
     }
 
     /**
-     * Creates a {@link TvInputSession} interface for a given TV input.
+     * Creates a {@link Session} for a given TV input.
      * <p>
      * The number of sessions that can be created at the same time is limited by the capability of
      * the given TV input.
@@ -319,34 +329,73 @@
 
     /** The Session provides the per-session functionality of TV inputs. */
     public static final class Session {
+        static final int DISPATCH_IN_PROGRESS = -1;
+        static final int DISPATCH_NOT_HANDLED = 0;
+        static final int DISPATCH_HANDLED = 1;
+
+        private static final long INPUT_SESSION_NOT_RESPONDING_TIMEOUT = 2500;
+
         private final ITvInputManager mService;
-        private final IBinder mToken;
         private final int mUserId;
 
+        // For scheduling input event handling on the main thread. This also serves as a lock to
+        // protect pending input events and the input channel.
+        private final InputEventHandler mHandler = new InputEventHandler(Looper.getMainLooper());
+
+        private final Pool<PendingEvent> mPendingEventPool = new SimplePool<PendingEvent>(20);
+        private final SparseArray<PendingEvent> mPendingEvents = new SparseArray<PendingEvent>(20);
+
+        private IBinder mToken;
+        private TvInputEventSender mSender;
+        private InputChannel mChannel;
+
         /** @hide */
-        private Session(ComponentName name, IBinder token, ITvInputManager service, int userId) {
+        private Session(IBinder token, InputChannel channel, ITvInputManager service, int userId) {
             mToken = token;
+            mChannel = channel;
             mService = service;
             mUserId = userId;
         }
 
         /**
          * Releases this session.
+         *
+         * @throws IllegalStateException if the session has been already released.
          */
         public void release() {
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
             try {
                 mService.releaseSession(mToken, mUserId);
+                mToken = null;
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
+
+            synchronized (mHandler) {
+                if (mChannel != null) {
+                    if (mSender != null) {
+                        flushPendingEventsLocked();
+                        mSender.dispose();
+                        mSender = null;
+                    }
+                    mChannel.dispose();
+                    mChannel = null;
+                }
+            }
         }
 
         /**
          * Sets the {@link android.view.Surface} for this session.
          *
          * @param surface A {@link android.view.Surface} used to render video.
+         * @throws IllegalStateException if the session has been already released.
          */
-        public void setSurface(Surface surface) {
+        void setSurface(Surface surface) {
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
             // surface can be null.
             try {
                 mService.setSurface(mToken, surface, mUserId);
@@ -360,8 +409,12 @@
          *
          * @param volume A volume value between 0.0f to 1.0f.
          * @throws IllegalArgumentException if the volume value is out of range.
+         * @throws IllegalStateException if the session has been already released.
          */
         public void setVolume(float volume) {
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
             try {
                 if (volume < 0.0f || volume > 1.0f) {
                     throw new IllegalArgumentException("volume should be between 0.0f and 1.0f");
@@ -377,16 +430,313 @@
          *
          * @param channelUri The URI of a channel.
          * @throws IllegalArgumentException if the argument is {@code null}.
+         * @throws IllegalStateException if the session has been already released.
          */
         public void tune(Uri channelUri) {
             if (channelUri == null) {
                 throw new IllegalArgumentException("channelUri cannot be null");
             }
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
             try {
                 mService.tune(mToken, channelUri, mUserId);
             } catch (RemoteException e) {
                 throw new RuntimeException(e);
             }
         }
+
+        /**
+         * Creates an overlay view. Once the overlay view is created, {@link #relayoutOverlayView}
+         * should be called whenever the layout of its containing view is changed.
+         * {@link #removeOverlayView()} should be called to remove the overlay view.
+         * Since a session can have only one overlay view, this method should be called only once
+         * or it can be called again after calling {@link #removeOverlayView()}.
+         *
+         * @param view A view playing TV.
+         * @param frame A position of the overlay view.
+         * @throws IllegalArgumentException if any of the arguments is {@code null}.
+         * @throws IllegalStateException if {@code view} is not attached to a window or
+         *         if the session has been already released.
+         */
+        void createOverlayView(View view, Rect frame) {
+            if (view == null) {
+                throw new IllegalArgumentException("view cannot be null");
+            }
+            if (frame == null) {
+                throw new IllegalArgumentException("frame cannot be null");
+            }
+            if (view.getWindowToken() == null) {
+                throw new IllegalStateException("view must be attached to a window");
+            }
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
+            try {
+                mService.createOverlayView(mToken, view.getWindowToken(), frame, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Relayouts the current overlay view.
+         *
+         * @param frame A new position of the overlay view.
+         * @throws IllegalArgumentException if the arguments is {@code null}.
+         * @throws IllegalStateException if the session has been already released.
+         */
+        void relayoutOverlayView(Rect frame) {
+            if (frame == null) {
+                throw new IllegalArgumentException("frame cannot be null");
+            }
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
+            try {
+                mService.relayoutOverlayView(mToken, frame, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Removes the current overlay view.
+         *
+         * @throws IllegalStateException if the session has been already released.
+         */
+        void removeOverlayView() {
+            if (mToken == null) {
+                throw new IllegalStateException("the session has been already released");
+            }
+            try {
+                mService.removeOverlayView(mToken, mUserId);
+            } catch (RemoteException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+        /**
+         * Dispatches an input event to this session.
+         *
+         * @param event {@link InputEvent} to dispatch.
+         * @param token A token used to identify the input event later in the callback.
+         * @param callback A callback used to receive the dispatch result.
+         * @param handler {@link Handler} that the dispatch result will be delivered to.
+         * @return Returns {@link #DISPATCH_HANDLED} if the event was handled. Returns
+         *         {@link #DISPATCH_NOT_HANDLED} if the event was not handled. Returns
+         *         {@link #DISPATCH_IN_PROGRESS} if the event is in progress and the callback will
+         *         be invoked later.
+         * @throws IllegalArgumentException if any of the necessary arguments is {@code null}.
+         * @hide
+         */
+        public int dispatchInputEvent(InputEvent event, Object token,
+                FinishedInputEventCallback callback, Handler handler) {
+            if (event == null) {
+                throw new IllegalArgumentException("event cannot be null");
+            }
+            if (callback != null && handler == null) {
+                throw new IllegalArgumentException("handler cannot be null");
+            }
+            synchronized (mHandler) {
+                if (mChannel == null) {
+                    return DISPATCH_NOT_HANDLED;
+                }
+                PendingEvent p = obtainPendingEventLocked(event, token, callback, handler);
+                if (Looper.myLooper() == Looper.getMainLooper()) {
+                    // Already running on the main thread so we can send the event immediately.
+                    return sendInputEventOnMainLooperLocked(p);
+                }
+
+                // Post the event to the main thread.
+                Message msg = mHandler.obtainMessage(InputEventHandler.MSG_SEND_INPUT_EVENT, p);
+                msg.setAsynchronous(true);
+                mHandler.sendMessage(msg);
+                return DISPATCH_IN_PROGRESS;
+            }
+        }
+
+        /**
+         * Callback that is invoked when an input event that was dispatched to this session has been
+         * finished.
+         *
+         * @hide
+         */
+        public interface FinishedInputEventCallback {
+            /**
+             * Called when the dispatched input event is finished.
+             *
+             * @param token a token passed to {@link #dispatchInputEvent}.
+             * @param handled {@code true} if the dispatched input event was handled properly.
+             *            {@code false} otherwise.
+             */
+            public void onFinishedInputEvent(Object token, boolean handled);
+        }
+
+        // Must be called on the main looper
+        private void sendInputEventAndReportResultOnMainLooper(PendingEvent p) {
+            synchronized (mHandler) {
+                int result = sendInputEventOnMainLooperLocked(p);
+                if (result == DISPATCH_IN_PROGRESS) {
+                    return;
+                }
+            }
+
+            invokeFinishedInputEventCallback(p, false);
+        }
+
+        private int sendInputEventOnMainLooperLocked(PendingEvent p) {
+            if (mChannel != null) {
+                if (mSender == null) {
+                    mSender = new TvInputEventSender(mChannel, mHandler.getLooper());
+                }
+
+                final InputEvent event = p.mEvent;
+                final int seq = event.getSequenceNumber();
+                if (mSender.sendInputEvent(seq, event)) {
+                    mPendingEvents.put(seq, p);
+                    Message msg = mHandler.obtainMessage(InputEventHandler.MSG_TIMEOUT_INPUT_EVENT, p);
+                    msg.setAsynchronous(true);
+                    mHandler.sendMessageDelayed(msg, INPUT_SESSION_NOT_RESPONDING_TIMEOUT);
+                    return DISPATCH_IN_PROGRESS;
+                }
+
+                Log.w(TAG, "Unable to send input event to session: " + mToken + " dropping:"
+                        + event);
+            }
+            return DISPATCH_NOT_HANDLED;
+        }
+
+        void finishedInputEvent(int seq, boolean handled, boolean timeout) {
+            final PendingEvent p;
+            synchronized (mHandler) {
+                int index = mPendingEvents.indexOfKey(seq);
+                if (index < 0) {
+                    return; // spurious, event already finished or timed out
+                }
+
+                p = mPendingEvents.valueAt(index);
+                mPendingEvents.removeAt(index);
+
+                if (timeout) {
+                    Log.w(TAG, "Timeout waiting for seesion to handle input event after "
+                            + INPUT_SESSION_NOT_RESPONDING_TIMEOUT + " ms: " + mToken);
+                } else {
+                    mHandler.removeMessages(InputEventHandler.MSG_TIMEOUT_INPUT_EVENT, p);
+                }
+            }
+
+            invokeFinishedInputEventCallback(p, handled);
+        }
+
+        // Assumes the event has already been removed from the queue.
+        void invokeFinishedInputEventCallback(PendingEvent p, boolean handled) {
+            p.mHandled = handled;
+            if (p.mHandler.getLooper().isCurrentThread()) {
+                // Already running on the callback handler thread so we can send the callback
+                // immediately.
+                p.run();
+            } else {
+                // Post the event to the callback handler thread.
+                // In this case, the callback will be responsible for recycling the event.
+                Message msg = Message.obtain(p.mHandler, p);
+                msg.setAsynchronous(true);
+                msg.sendToTarget();
+            }
+        }
+
+        private void flushPendingEventsLocked() {
+            mHandler.removeMessages(InputEventHandler.MSG_FLUSH_INPUT_EVENT);
+
+            final int count = mPendingEvents.size();
+            for (int i = 0; i < count; i++) {
+                int seq = mPendingEvents.keyAt(i);
+                Message msg = mHandler.obtainMessage(InputEventHandler.MSG_FLUSH_INPUT_EVENT, seq, 0);
+                msg.setAsynchronous(true);
+                msg.sendToTarget();
+            }
+        }
+
+        private PendingEvent obtainPendingEventLocked(InputEvent event, Object token,
+                FinishedInputEventCallback callback, Handler handler) {
+            PendingEvent p = mPendingEventPool.acquire();
+            if (p == null) {
+                p = new PendingEvent();
+            }
+            p.mEvent = event;
+            p.mToken = token;
+            p.mCallback = callback;
+            p.mHandler = handler;
+            return p;
+        }
+
+        private void recyclePendingEventLocked(PendingEvent p) {
+            p.recycle();
+            mPendingEventPool.release(p);
+        }
+
+        private final class InputEventHandler extends Handler {
+            public static final int MSG_SEND_INPUT_EVENT = 1;
+            public static final int MSG_TIMEOUT_INPUT_EVENT = 2;
+            public static final int MSG_FLUSH_INPUT_EVENT = 3;
+
+            InputEventHandler(Looper looper) {
+                super(looper, null, true);
+            }
+
+            @Override
+            public void handleMessage(Message msg) {
+                switch (msg.what) {
+                    case MSG_SEND_INPUT_EVENT: {
+                        sendInputEventAndReportResultOnMainLooper((PendingEvent) msg.obj);
+                        return;
+                    }
+                    case MSG_TIMEOUT_INPUT_EVENT: {
+                        finishedInputEvent(msg.arg1, false, true);
+                        return;
+                    }
+                    case MSG_FLUSH_INPUT_EVENT: {
+                        finishedInputEvent(msg.arg1, false, false);
+                        return;
+                    }
+                }
+            }
+        }
+
+        private final class TvInputEventSender extends InputEventSender {
+            public TvInputEventSender(InputChannel inputChannel, Looper looper) {
+                super(inputChannel, looper);
+            }
+
+            @Override
+            public void onInputEventFinished(int seq, boolean handled) {
+                finishedInputEvent(seq, handled, false);
+            }
+        }
+
+        private final class PendingEvent implements Runnable {
+            public InputEvent mEvent;
+            public Object mToken;
+            public FinishedInputEventCallback mCallback;
+            public Handler mHandler;
+            public boolean mHandled;
+
+            public void recycle() {
+                mEvent = null;
+                mToken = null;
+                mCallback = null;
+                mHandler = null;
+                mHandled = false;
+            }
+
+            @Override
+            public void run() {
+                mCallback.onFinishedInputEvent(mToken, mHandled);
+
+                synchronized (mHandler) {
+                    recyclePendingEventLocked(this);
+                }
+            }
+        }
     }
 }
diff --git a/core/java/android/tv/TvInputService.java b/core/java/android/tv/TvInputService.java
index e43cc95..70e7f95 100644
--- a/core/java/android/tv/TvInputService.java
+++ b/core/java/android/tv/TvInputService.java
@@ -18,17 +18,31 @@
 
 import android.app.Service;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.tv.TvInputManager.Session;
 import android.util.Log;
+import android.view.Gravity;
+import android.view.InputChannel;
+import android.view.InputDevice;
+import android.view.InputEvent;
+import android.view.InputEventReceiver;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.View;
+import android.view.WindowManager;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.os.SomeArgs;
 
 /**
  * A base class for implementing television input service.
@@ -83,10 +97,17 @@
             }
 
             @Override
-            public void createSession(ITvInputSessionCallback cb) {
-                if (cb != null) {
-                    mHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, cb).sendToTarget();
+            public void createSession(InputChannel channel, ITvInputSessionCallback cb) {
+                if (channel == null) {
+                    Log.w(TAG, "Creating session without input channel");
                 }
+                if (cb == null) {
+                    return;
+                }
+                SomeArgs args = SomeArgs.obtain();
+                args.arg1 = channel;
+                args.arg2 = cb;
+                mHandler.obtainMessage(ServiceHandler.DO_CREATE_SESSION, args).sendToTarget();
             }
         };
     }
@@ -123,9 +144,48 @@
     public abstract TvInputSessionImpl onCreateSession();
 
     /**
-     * Base class for derived classes to implement to provide {@link TvInputSession}.
+     * Base class for derived classes to implement to provide {@link TvInputManager.Session}.
      */
-    public abstract static class TvInputSessionImpl {
+    public abstract class TvInputSessionImpl implements KeyEvent.Callback {
+        private final KeyEvent.DispatcherState mDispatcherState = new KeyEvent.DispatcherState();
+        private final WindowManager mWindowManager;
+        private WindowManager.LayoutParams mWindowParams;
+        private Surface mSurface;
+        private View mOverlayView;
+        private boolean mOverlayViewEnabled;
+        private IBinder mWindowToken;
+        private Rect mOverlayFrame;
+
+        public TvInputSessionImpl() {
+            mWindowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
+        }
+
+        /**
+         * Enables or disables the overlay view. By default, the overlay view is disabled. Must be
+         * called explicitly after the session is created to enable the overlay view.
+         *
+         * @param enable {@code true} if you want to enable the overlay view. {@code false}
+         *            otherwise.
+         */
+        public void setOverlayViewEnabled(final boolean enable) {
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    if (enable == mOverlayViewEnabled) {
+                        return;
+                    }
+                    mOverlayViewEnabled = enable;
+                    if (enable) {
+                        if (mWindowToken != null) {
+                            createOverlayView(mWindowToken, mOverlayFrame);
+                        }
+                    } else {
+                        removeOverlayView(false);
+                    }
+                }
+            });
+        }
+
         /**
          * Called when the session is released.
          */
@@ -155,54 +215,288 @@
          * @return {@code true} the tuning was successful, {@code false} otherwise.
          */
         public abstract boolean onTune(Uri channelUri);
-    }
 
-    /**
-     * Internal implementation of {@link TvInputSession}. This takes care of basic maintenance of
-     * the TV input session but most behavior must be implemented in {@link TvInputSessionImpl}
-     * returned by {@link TvInputService#onCreateSession}.
-     */
-    private static class TvInputSessionImplInternal extends TvInputSession {
-        private final TvInputSessionImpl mSessionImpl;
+        /**
+         * Called when an application requests to create an overlay view. Each session
+         * implementation can override this method and return its own view.
+         *
+         * @return a view attached to the overlay window
+         */
+        public View onCreateOverlayView() {
+            return null;
+        }
 
-        public TvInputSessionImplInternal(TvInputSessionImpl sessionImpl) {
-            mSessionImpl = sessionImpl;
+        /**
+         * Default implementation of {@link android.view.KeyEvent.Callback#onKeyDown(int, KeyEvent)
+         * KeyEvent.Callback.onKeyDown()}: always returns false (doesn't handle the event).
+         * <p>
+         * Override this to intercept key down events before they are processed by the application.
+         * If you return true, the application will not process the event itself. If you return
+         * false, the normal application processing will occur as if the TV input had not seen the
+         * event at all.
+         *
+         * @param keyCode The value in event.getKeyCode().
+         * @param event Description of the key event.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         */
+        @Override
+        public boolean onKeyDown(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * Default implementation of
+         * {@link android.view.KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
+         * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle the event).
+         * <p>
+         * Override this to intercept key long press events before they are processed by the
+         * application. If you return true, the application will not process the event itself. If
+         * you return false, the normal application processing will occur as if the TV input had not
+         * seen the event at all.
+         *
+         * @param keyCode The value in event.getKeyCode().
+         * @param event Description of the key event.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         */
+        @Override
+        public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * Default implementation of
+         * {@link android.view.KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
+         * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle the event).
+         * <p>
+         * Override this to intercept special key multiple events before they are processed by the
+         * application. If you return true, the application will not itself process the event. If
+         * you return false, the normal application processing will occur as if the TV input had not
+         * seen the event at all.
+         *
+         * @param keyCode The value in event.getKeyCode().
+         * @param count The number of times the action was made.
+         * @param event Description of the key event.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         */
+        @Override
+        public boolean onKeyMultiple(int keyCode, int count, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * Default implementation of {@link android.view.KeyEvent.Callback#onKeyUp(int, KeyEvent)
+         * KeyEvent.Callback.onKeyUp()}: always returns false (doesn't handle the event).
+         * <p>
+         * Override this to intercept key up events before they are processed by the application. If
+         * you return true, the application will not itself process the event. If you return false,
+         * the normal application processing will occur as if the TV input had not seen the event at
+         * all.
+         *
+         * @param keyCode The value in event.getKeyCode().
+         * @param event Description of the key event.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         */
+        @Override
+        public boolean onKeyUp(int keyCode, KeyEvent event) {
+            return false;
+        }
+
+        /**
+         * Implement this method to handle touch screen motion events on the current input session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onTouchEvent
+         */
+        public boolean onTouchEvent(MotionEvent event) {
+            return false;
+        }
+
+        /**
+         * Implement this method to handle trackball events on the current input session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onTrackballEvent
+         */
+        public boolean onTrackballEvent(MotionEvent event) {
+            return false;
+        }
+
+        /**
+         * Implement this method to handle generic motion events on the current input session.
+         *
+         * @param event The motion event being received.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         * @see View#onGenericMotionEvent
+         */
+        public boolean onGenericMotionEvent(MotionEvent event) {
+            return false;
         }
 
         /**
          * This method is called when the application would like to stop using the current input
          * session.
          */
-        @Override
-        public final void release() {
-            mSessionImpl.onRelease();
+        void release() {
+            onRelease();
+            if (mSurface != null) {
+                mSurface.release();
+                mSurface = null;
+            }
+            removeOverlayView(true);
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onSetSurface}.
+         * Calls {@link #onSetSurface}.
          */
-        @Override
-        public final void setSurface(Surface surface) {
-            mSessionImpl.onSetSurface(surface);
+        void setSurface(Surface surface) {
+            onSetSurface(surface);
+            if (mSurface != null) {
+                mSurface.release();
+            }
+            mSurface = surface;
             // TODO: Handle failure.
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onSetVolume}.
+         * Calls {@link #onSetVolume}.
          */
-        @Override
-        public final void setVolume(float volume) {
-            mSessionImpl.onSetVolume(volume);
+        void setVolume(float volume) {
+            onSetVolume(volume);
         }
 
         /**
-         * Calls {@link TvInputSessionImpl#onTune}.
+         * Calls {@link #onTune}.
          */
-        @Override
-        public final void tune(Uri channelUri) {
-            mSessionImpl.onTune(channelUri);
+        void tune(Uri channelUri) {
+            onTune(channelUri);
             // TODO: Handle failure.
         }
+
+        /**
+         * Creates an overlay view. This calls {@link #onCreateOverlayView} to get a view to attach
+         * to the overlay window.
+         *
+         * @param windowToken A window token of an application.
+         * @param frame A position of the overlay view.
+         */
+        void createOverlayView(IBinder windowToken, Rect frame) {
+            if (mOverlayView != null) {
+                mWindowManager.removeView(mOverlayView);
+                mOverlayView = null;
+            }
+            if (DEBUG) {
+                Log.d(TAG, "create overlay view(" + frame + ")");
+            }
+            mWindowToken = windowToken;
+            mOverlayFrame = frame;
+            if (!mOverlayViewEnabled) {
+                return;
+            }
+            mOverlayView = onCreateOverlayView();
+            if (mOverlayView == null) {
+                return;
+            }
+            // TvView's window type is TYPE_APPLICATION_MEDIA and we want to create
+            // an overlay window above the media window but below the application window.
+            int type = WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA_OVERLAY;
+            // We make the overlay view non-focusable and non-touchable so that
+            // the application that owns the window token can decide whether to consume or
+            // dispatch the input events.
+            int flag = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+            mWindowParams = new WindowManager.LayoutParams(
+                    frame.right - frame.left, frame.bottom - frame.top,
+                    frame.left, frame.top, type, flag, PixelFormat.TRANSPARENT);
+            mWindowParams.privateFlags |=
+                    WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+            mWindowParams.gravity = Gravity.START | Gravity.TOP;
+            mWindowParams.token = windowToken;
+            mWindowManager.addView(mOverlayView, mWindowParams);
+        }
+
+        /**
+         * Relayouts the current overlay view.
+         *
+         * @param frame A new position of the overlay view.
+         */
+        void relayoutOverlayView(Rect frame) {
+            if (DEBUG) {
+                Log.d(TAG, "relayout overlay view(" + frame + ")");
+            }
+            mOverlayFrame = frame;
+            if (!mOverlayViewEnabled || mOverlayView == null) {
+                return;
+            }
+            mWindowParams.x = frame.left;
+            mWindowParams.y = frame.top;
+            mWindowParams.width = frame.right - frame.left;
+            mWindowParams.height = frame.bottom - frame.top;
+            mWindowManager.updateViewLayout(mOverlayView, mWindowParams);
+        }
+
+        /**
+         * Removes the current overlay view.
+         */
+        void removeOverlayView(boolean clearWindowToken) {
+            if (DEBUG) {
+                Log.d(TAG, "remove overlay view(" + mOverlayView + ")");
+            }
+            if (clearWindowToken) {
+                mWindowToken = null;
+                mOverlayFrame = null;
+            }
+            if (mOverlayView != null) {
+                mWindowManager.removeView(mOverlayView);
+                mOverlayView = null;
+                mWindowParams = null;
+            }
+        }
+
+        /**
+         * Takes care of dispatching incoming input events and tells whether the event was handled.
+         */
+        int dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
+            if (DEBUG) Log.d(TAG, "dispatchInputEvent(" + event + ")");
+            if (event instanceof KeyEvent) {
+                if (((KeyEvent) event).dispatch(this, mDispatcherState, this)) {
+                    return Session.DISPATCH_HANDLED;
+                }
+            } else if (event instanceof MotionEvent) {
+                MotionEvent motionEvent = (MotionEvent) event;
+                final int source = motionEvent.getSource();
+                if (motionEvent.isTouchEvent()) {
+                    if (onTouchEvent(motionEvent)) {
+                        return Session.DISPATCH_HANDLED;
+                    }
+                } else if ((source & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) {
+                    if (onTrackballEvent(motionEvent)) {
+                        return Session.DISPATCH_HANDLED;
+                    }
+                } else {
+                    if (onGenericMotionEvent(motionEvent)) {
+                        return Session.DISPATCH_HANDLED;
+                    }
+                }
+            }
+            if (mOverlayView == null) {
+                return Session.DISPATCH_NOT_HANDLED;
+            }
+            if (!mOverlayView.hasWindowFocus()) {
+                mOverlayView.getViewRootImpl().windowFocusChanged(true, true);
+            }
+            mOverlayView.getViewRootImpl().dispatchInputEvent(event, receiver);
+            return Session.DISPATCH_IN_PROGRESS;
+        }
     }
 
     private final class ServiceHandler extends Handler {
@@ -213,20 +507,23 @@
         public final void handleMessage(Message msg) {
             switch (msg.what) {
                 case DO_CREATE_SESSION: {
-                    ITvInputSessionCallback cb = (ITvInputSessionCallback) msg.obj;
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    InputChannel channel = (InputChannel) args.arg1;
+                    ITvInputSessionCallback cb = (ITvInputSessionCallback) args.arg2;
                     try {
                         TvInputSessionImpl sessionImpl = onCreateSession();
                         if (sessionImpl == null) {
                             // Failed to create a session.
                             cb.onSessionCreated(null);
-                            return;
+                        } else {
+                            ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
+                                    sessionImpl, channel);
+                            cb.onSessionCreated(stub);
                         }
-                        ITvInputSession stub = new ITvInputSessionWrapper(TvInputService.this,
-                                new TvInputSessionImplInternal(sessionImpl));
-                        cb.onSessionCreated(stub);
                     } catch (RemoteException e) {
                         Log.e(TAG, "error in onSessionCreated");
                     }
+                    args.recycle();
                     return;
                 }
                 case DO_BROADCAST_AVAILABILITY_CHANGE: {
diff --git a/core/java/android/tv/TvInputSession.java b/core/java/android/tv/TvInputSession.java
deleted file mode 100644
index cdd363b..0000000
--- a/core/java/android/tv/TvInputSession.java
+++ /dev/null
@@ -1,55 +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.
- */
-
-package android.tv;
-
-import android.net.Uri;
-import android.view.Surface;
-
-/**
- * The TvInputSession provides the per-session functionality of TvInputService.
- */
-public abstract class TvInputSession {
-    /**
-     * This method is called when the application would like to stop using the current input
-     * session.
-     */
-    public void release() { }
-
-    /**
-     * Sets the {@link Surface} for the current input session on which the TV input renders video.
-     *
-     * @param surface {@link Surface} to be used for the video playback of this session.
-     */
-    public void setSurface(Surface surface) { }
-
-    /**
-     * This method is called when the application needs to handle the change of audio focus by
-     * setting the relative volume of the current TV input service session.
-     *
-     * @param volume Volume scale from 0.0 to 1.0.
-     */
-    // TODO: Remove this once it becomes irrelevant for applications to handle audio focus. The plan
-    // is to introduce some new concepts that will solve a number of problems in audio policy today.
-    public void setVolume(float volume) { }
-
-    /**
-     * Tunes to a given channel.
-     *
-     * @param channelUri The URI of the channel.
-     */
-    public void tune(Uri channelUri) { }
-}
diff --git a/core/java/android/tv/TvView.java b/core/java/android/tv/TvView.java
new file mode 100644
index 0000000..289823b
--- /dev/null
+++ b/core/java/android/tv/TvView.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.tv;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.graphics.Rect;
+import android.os.Handler;
+import android.tv.TvInputManager.Session;
+import android.tv.TvInputManager.Session.FinishedInputEventCallback;
+import android.tv.TvInputManager.SessionCreateCallback;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.InputEvent;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+
+/**
+ * View playing TV
+ */
+public class TvView extends SurfaceView {
+    // STOPSHIP: Turn debugging off.
+    private static final boolean DEBUG = true;
+    private static final String TAG = "TvView";
+
+    private final Handler mHandler = new Handler();
+    private TvInputManager.Session mSession;
+    private Surface mSurface;
+    private boolean mOverlayViewCreated;
+    private Rect mOverlayViewFrame;
+    private final TvInputManager mTvInputManager;
+    private SessionCreateCallback mSessionCreateCallback;
+    private OnUnhandledInputEventListener mOnUnhandledInputEventListener;
+
+    private final SurfaceHolder.Callback mSurfaceHolderCallback = new SurfaceHolder.Callback() {
+        @Override
+        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+            Log.d(TAG, "surfaceChanged(holder=" + holder + ", format=" + format + ", width=" + width
+                    + ", height=" + height + ")");
+            if (holder.getSurface() == mSurface) {
+                return;
+            }
+            mSurface = holder.getSurface();
+            setSessionSurface(mSurface);
+        }
+
+        @Override
+        public void surfaceCreated(SurfaceHolder holder) {
+            mSurface = holder.getSurface();
+            setSessionSurface(mSurface);
+        }
+
+        @Override
+        public void surfaceDestroyed(SurfaceHolder holder) {
+            mSurface = null;
+            setSessionSurface(null);
+        }
+    };
+
+    private final FinishedInputEventCallback mFinishedInputEventCallback =
+            new FinishedInputEventCallback() {
+        @Override
+        public void onFinishedInputEvent(Object token, boolean handled) {
+            if (DEBUG) {
+                Log.d(TAG, "onFinishedInputEvent(token=" + token + ", handled=" + handled + ")");
+            }
+            if (handled) {
+                return;
+            }
+            // TODO: Re-order unhandled events.
+            InputEvent event = (InputEvent) token;
+            if (dispatchUnhandledInputEvent(event)) {
+                return;
+            }
+            getViewRootImpl().dispatchUnhandledInputEvent(event);
+        }
+    };
+
+    public TvView(Context context) {
+        this(context, null, 0);
+    }
+
+    public TvView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TvView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+        getHolder().addCallback(mSurfaceHolderCallback);
+        mTvInputManager = (TvInputManager) getContext().getSystemService(Context.TV_INPUT_SERVICE);
+    }
+
+    /**
+     * Binds a TV input to this view. {@link SessionCreateCallback#onSessionCreated} will be
+     * called to send the result of this binding with {@link TvInputManager.Session}.
+     * If a TV input is already bound, the input will be unbound from this view and its session
+     * will be released.
+     *
+     * @param name TV input name will be bound to this view.
+     * @param callback called when TV input is bound. The callback sends
+     *        {@link TvInputManager.Session}
+     * @throws IllegalArgumentException if any of the arguments is {@code null}.
+     */
+    public void bindTvInput(ComponentName name, SessionCreateCallback callback) {
+        if (name == null) {
+            throw new IllegalArgumentException("name cannot be null");
+        }
+        if (callback == null) {
+            throw new IllegalArgumentException("callback cannot be null");
+        }
+        if (mSession != null) {
+            release();
+        }
+        // When bindTvInput is called multiple times before the callback is called,
+        // only the callback of the last bindTvInput call will be actually called back.
+        // The previous callbacks will be ignored. For the logic, mSessionCreateCallback
+        // is newly assigned for every bindTvInput call and compared with
+        // MySessionCreateCallback.this.
+        mSessionCreateCallback = new MySessionCreateCallback(callback);
+        mTvInputManager.createSession(name, mSessionCreateCallback, mHandler);
+    }
+
+    /**
+     * Unbinds a TV input currently bound. Its corresponding {@link TvInputManager.Session}
+     * is released.
+     */
+    public void unbindTvInput() {
+        if (mSession != null) {
+            release();
+        }
+    }
+
+    /**
+     * Dispatches an unhandled input event to the next receiver.
+     * <p>
+     * Except system keys, TvView always consumes input events in the normal flow. This is called
+     * asynchronously from where the event is dispatched. It gives the host application a chance to
+     * dispatch the unhandled input events.
+     *
+     * @param event The input event.
+     * @return {@code true} if the event was handled by the view, {@code false} otherwise.
+     */
+    public boolean dispatchUnhandledInputEvent(InputEvent event) {
+        if (mOnUnhandledInputEventListener != null) {
+            if (mOnUnhandledInputEventListener.onUnhandledInputEvent(event)) {
+                return true;
+            }
+        }
+        return onUnhandledInputEvent(event);
+    }
+
+    /**
+     * Called when an unhandled input event was also not handled by the user provided callback. This
+     * is the last chance to handle the unhandled input event in the TvView.
+     *
+     * @param event The input event.
+     * @return If you handled the event, return {@code true}. If you want to allow the event to be
+     *         handled by the next receiver, return {@code false}.
+     */
+    public boolean onUnhandledInputEvent(InputEvent event) {
+        return false;
+    }
+
+    /**
+     * Registers a callback to be invoked when an input event was not handled by the bound TV input.
+     *
+     * @param listener The callback to invoke when the unhandled input event was received.
+     */
+    public void setOnUnhandledInputEventListener(OnUnhandledInputEventListener listener) {
+        mOnUnhandledInputEventListener = listener;
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        if (super.dispatchKeyEvent(event)) {
+            return true;
+        }
+        if (DEBUG) Log.d(TAG, "dispatchKeyEvent(" + event + ")");
+        if (mSession == null) {
+            return false;
+        }
+        int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+        return ret != Session.DISPATCH_NOT_HANDLED;
+    }
+
+    @Override
+    public boolean dispatchTouchEvent(MotionEvent event) {
+        if (super.dispatchTouchEvent(event)) {
+            return true;
+        }
+        if (DEBUG) Log.d(TAG, "dispatchTouchEvent(" + event + ")");
+        if (mSession == null) {
+            return false;
+        }
+        int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+        return ret != Session.DISPATCH_NOT_HANDLED;
+    }
+
+    @Override
+    public boolean dispatchTrackballEvent(MotionEvent event) {
+        if (super.dispatchTrackballEvent(event)) {
+            return true;
+        }
+        if (DEBUG) Log.d(TAG, "dispatchTrackballEvent(" + event + ")");
+        if (mSession == null) {
+            return false;
+        }
+        int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+        return ret != Session.DISPATCH_NOT_HANDLED;
+    }
+
+    @Override
+    public boolean dispatchGenericMotionEvent(MotionEvent event) {
+        if (super.dispatchGenericMotionEvent(event)) {
+            return true;
+        }
+        if (DEBUG) Log.d(TAG, "dispatchGenericMotionEvent(" + event + ")");
+        if (mSession == null) {
+            return false;
+        }
+        int ret = mSession.dispatchInputEvent(event, event, mFinishedInputEventCallback, mHandler);
+        return ret != Session.DISPATCH_NOT_HANDLED;
+    }
+
+    @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        createSessionOverlayView();
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        removeSessionOverlayView();
+        super.onDetachedFromWindow();
+    }
+
+    /** @hide */
+    @Override
+    protected void updateWindow(boolean force, boolean redrawNeeded) {
+        super.updateWindow(force, redrawNeeded);
+        relayoutSessionOverlayView();
+    }
+
+    private void release() {
+        setSessionSurface(null);
+        removeSessionOverlayView();
+        mSession.release();
+        mSession = null;
+    }
+
+    private void setSessionSurface(Surface surface) {
+        if (mSession == null) {
+            return;
+        }
+        mSession.setSurface(surface);
+    }
+
+    private void createSessionOverlayView() {
+        if (mSession == null || !isAttachedToWindow()
+                || mOverlayViewCreated) {
+            return;
+        }
+        mOverlayViewFrame = getViewFrameOnScreen();
+        mSession.createOverlayView(this, mOverlayViewFrame);
+        mOverlayViewCreated = true;
+    }
+
+    private void removeSessionOverlayView() {
+        if (mSession == null || !mOverlayViewCreated) {
+            return;
+        }
+        mSession.removeOverlayView();
+        mOverlayViewCreated = false;
+        mOverlayViewFrame = null;
+    }
+
+    private void relayoutSessionOverlayView() {
+        if (mSession == null || !isAttachedToWindow()
+                || !mOverlayViewCreated) {
+            return;
+        }
+        Rect viewFrame = getViewFrameOnScreen();
+        if (viewFrame.equals(mOverlayViewFrame)) {
+            return;
+        }
+        mSession.relayoutOverlayView(viewFrame);
+        mOverlayViewFrame = viewFrame;
+    }
+
+    private Rect getViewFrameOnScreen() {
+        int[] location = new int[2];
+        getLocationOnScreen(location);
+        return new Rect(location[0], location[1],
+                location[0] + getWidth(), location[1] + getHeight());
+    }
+
+    /**
+     * Interface definition for a callback to be invoked when the unhandled input event is received.
+     */
+    public interface OnUnhandledInputEventListener {
+        /**
+         * Called when an input event was not handled by the bound TV input.
+         * <p>
+         * This is called asynchronously from where the event is dispatched. It gives the host
+         * application a chance to handle the unhandled input events.
+         *
+         * @param event The input event.
+         * @return If you handled the event, return {@code true}. If you want to allow the event to
+         *         be handled by the next receiver, return {@code false}.
+         */
+        boolean onUnhandledInputEvent(InputEvent event);
+    }
+
+    private class MySessionCreateCallback implements SessionCreateCallback {
+        final SessionCreateCallback mExternalCallback;
+
+        MySessionCreateCallback(SessionCreateCallback externalCallback) {
+            mExternalCallback = externalCallback;
+        }
+
+        @Override
+        public void onSessionCreated(Session session) {
+            if (this != mSessionCreateCallback) {
+                // This callback is obsolete.
+                session.release();
+                return;
+            }
+            mSession = session;
+            if (session != null) {
+                // mSurface may not be ready yet as soon as starting an application.
+                // In the case, we don't send Session.setSurface(null) unnecessarily.
+                // setSessionSurface will be called in surfaceCreated.
+                if (mSurface != null) {
+                    setSessionSurface(mSurface);
+                }
+                createSessionOverlayView();
+            }
+            if (mExternalCallback != null) {
+                mExternalCallback.onSessionCreated(session);
+            }
+        }
+    }
+}
diff --git a/core/java/android/util/EventLog.java b/core/java/android/util/EventLog.java
index 29c0ba2..aefced8 100644
--- a/core/java/android/util/EventLog.java
+++ b/core/java/android/util/EventLog.java
@@ -56,16 +56,18 @@
     public static final class Event {
         private final ByteBuffer mBuffer;
 
-        // Layout of event log entry received from kernel.
+        // Layout of event log entry received from Android logger.
+        //  see system/core/include/log/logger.h
         private static final int LENGTH_OFFSET = 0;
+        private static final int HEADER_SIZE_OFFSET = 2;
         private static final int PROCESS_OFFSET = 4;
         private static final int THREAD_OFFSET = 8;
         private static final int SECONDS_OFFSET = 12;
         private static final int NANOSECONDS_OFFSET = 16;
 
-        private static final int PAYLOAD_START = 20;
-        private static final int TAG_OFFSET = 20;
-        private static final int DATA_START = 24;
+        // Layout for event log v1 format, v2 and v3 use HEADER_SIZE_OFFSET
+        private static final int V1_PAYLOAD_START = 20;
+        private static final int DATA_OFFSET = 4;
 
         // Value types
         private static final byte INT_TYPE    = 0;
@@ -97,14 +99,22 @@
 
         /** @return the type tag code of the entry */
         public int getTag() {
-            return mBuffer.getInt(TAG_OFFSET);
+            int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
+            if (offset == 0) {
+                offset = V1_PAYLOAD_START;
+            }
+            return mBuffer.getInt(offset);
         }
 
         /** @return one of Integer, Long, String, null, or Object[] of same. */
         public synchronized Object getData() {
             try {
-                mBuffer.limit(PAYLOAD_START + mBuffer.getShort(LENGTH_OFFSET));
-                mBuffer.position(DATA_START);  // Just after the tag.
+                int offset = mBuffer.getShort(HEADER_SIZE_OFFSET);
+                if (offset == 0) {
+                    offset = V1_PAYLOAD_START;
+                }
+                mBuffer.limit(offset + mBuffer.getShort(LENGTH_OFFSET));
+                mBuffer.position(offset + DATA_OFFSET); // Just after the tag.
                 return decodeObject();
             } catch (IllegalArgumentException e) {
                 Log.wtf(TAG, "Illegal entry payload: tag=" + getTag(), e);
diff --git a/core/java/android/util/Log.java b/core/java/android/util/Log.java
index abd173a..2b81072 100644
--- a/core/java/android/util/Log.java
+++ b/core/java/android/util/Log.java
@@ -352,6 +352,7 @@
     /** @hide */ public static final int LOG_ID_RADIO = 1;
     /** @hide */ public static final int LOG_ID_EVENTS = 2;
     /** @hide */ public static final int LOG_ID_SYSTEM = 3;
+    /** @hide */ public static final int LOG_ID_CRASH = 4;
 
     /** @hide */ public static native int println_native(int bufID,
             int priority, String tag, String msg);
diff --git a/core/java/android/util/Patterns.java b/core/java/android/util/Patterns.java
index 13cc88b..2cc91b9 100644
--- a/core/java/android/util/Patterns.java
+++ b/core/java/android/util/Patterns.java
@@ -130,7 +130,10 @@
     private static final String IRI
         = "[" + GOOD_IRI_CHAR + "]([" + GOOD_IRI_CHAR + "\\-]{0,61}[" + GOOD_IRI_CHAR + "]){0,1}";
 
-    private static final String HOST_NAME = IRI + "(?:\\." + IRI + ")+";
+    private static final String GOOD_GTLD_CHAR =
+        "a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF";
+    private static final String GTLD = "[" + GOOD_GTLD_CHAR + "]{2,63}";
+    private static final String HOST_NAME = "(" + IRI + "\\.)+" + GTLD;
 
     public static final Pattern DOMAIN_NAME
         = Pattern.compile("(" + HOST_NAME + "|" + IP_ADDRESS + ")");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/view/AnimationRenderStats.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/view/AnimationRenderStats.aidl
index 0377123..4599708 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/view/AnimationRenderStats.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.view;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable AnimationRenderStats;
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index d3f63b4..d7a913d 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -204,6 +204,36 @@
     public static final int TYPE_VIRTUAL = 5;
 
     /**
+     * Display state: The display state is unknown.
+     *
+     * @see #getState
+     */
+    public static final int STATE_UNKNOWN = 0;
+
+    /**
+     * Display state: The display is off.
+     *
+     * @see #getState
+     */
+    public static final int STATE_OFF = 1;
+
+    /**
+     * Display state: The display is on.
+     *
+     * @see #getState
+     */
+    public static final int STATE_ON = 2;
+
+    /**
+     * Display state: The display is dozing in a low-power state; it may be showing
+     * system-provided content while the device is in a non-interactive state.
+     *
+     * @see #getState
+     * @see android.os.PowerManager#isInteractive
+     */
+    public static final int STATE_DOZING = 3;
+
+    /**
      * Internal method to create a display.
      * Applications should use {@link android.view.WindowManager#getDefaultDisplay()}
      * or {@link android.hardware.display.DisplayManager#getDisplay}
@@ -630,6 +660,19 @@
     }
 
     /**
+     * Gets the state of the display, such as whether it is on or off.
+     *
+     * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON},
+     * {@link #STATE_DOZING}, or {@link #STATE_UNKNOWN}.
+     */
+    public int getState() {
+        synchronized (this) {
+            updateDisplayInfoLocked();
+            return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN;
+        }
+    }
+
+    /**
      * Returns true if the specified UID has access to this display.
      * @hide
      */
@@ -720,5 +763,22 @@
                 return Integer.toString(type);
         }
     }
-}
 
+    /**
+     * @hide
+     */
+    public static String stateToString(int state) {
+        switch (state) {
+            case STATE_UNKNOWN:
+                return "UNKNOWN";
+            case STATE_OFF:
+                return "OFF";
+            case STATE_ON:
+                return "ON";
+            case STATE_DOZING:
+                return "DOZING";
+            default:
+                return Integer.toString(state);
+        }
+    }
+}
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index 7fd7b83..b0fe0fa 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -180,6 +180,11 @@
     public float physicalYDpi;
 
     /**
+     * The state of the display, such as {@link android.view.Display#STATE_ON}.
+     */
+    public int state;
+
+    /**
      * The UID of the application that owns this display, or zero if it is owned by the system.
      * <p>
      * If the display is private, then only the owner can use it.
@@ -248,6 +253,7 @@
                 && logicalDensityDpi == other.logicalDensityDpi
                 && physicalXDpi == other.physicalXDpi
                 && physicalYDpi == other.physicalYDpi
+                && state == other.state
                 && ownerUid == other.ownerUid
                 && Objects.equal(ownerPackageName, other.ownerPackageName);
     }
@@ -280,6 +286,7 @@
         logicalDensityDpi = other.logicalDensityDpi;
         physicalXDpi = other.physicalXDpi;
         physicalYDpi = other.physicalYDpi;
+        state = other.state;
         ownerUid = other.ownerUid;
         ownerPackageName = other.ownerPackageName;
     }
@@ -307,6 +314,7 @@
         logicalDensityDpi = source.readInt();
         physicalXDpi = source.readFloat();
         physicalYDpi = source.readFloat();
+        state = source.readInt();
         ownerUid = source.readInt();
         ownerPackageName = source.readString();
     }
@@ -335,6 +343,7 @@
         dest.writeInt(logicalDensityDpi);
         dest.writeFloat(physicalXDpi);
         dest.writeFloat(physicalYDpi);
+        dest.writeInt(state);
         dest.writeInt(ownerUid);
         dest.writeString(ownerPackageName);
     }
@@ -431,7 +440,7 @@
         sb.append(smallestNominalAppHeight);
         sb.append(", ");
         sb.append(refreshRate);
-        sb.append(" fps, rotation");
+        sb.append(" fps, rotation ");
         sb.append(rotation);
         sb.append(", density ");
         sb.append(logicalDensityDpi);
@@ -446,6 +455,8 @@
         if (address != null) {
             sb.append(", address ").append(address);
         }
+        sb.append(", state ");
+        sb.append(Display.stateToString(state));
         if (ownerUid != 0 || ownerPackageName != null) {
             sb.append(", owner ").append(ownerPackageName);
             sb.append(" (uid ").append(ownerUid).append(")");
diff --git a/core/java/android/view/FrameStats.java b/core/java/android/view/FrameStats.java
new file mode 100644
index 0000000..541b336
--- /dev/null
+++ b/core/java/android/view/FrameStats.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This is the base class for frame statistics.
+ */
+public abstract class FrameStats {
+    /**
+     * Undefined time.
+     */
+    public static final long UNDEFINED_TIME_NANO = -1;
+
+    protected long mRefreshPeriodNano;
+    protected long[] mFramesPresentedTimeNano;
+
+    /**
+     * Gets the refresh period of the display hosting the window(s) for
+     * which these statistics apply.
+     *
+     * @return The refresh period in nanoseconds.
+     */
+    public final long getRefreshPeriodNano() {
+        return mRefreshPeriodNano;
+    }
+
+    /**
+     * Gets the number of frames for which there is data.
+     *
+     * @return The number of frames.
+     */
+    public final int getFrameCount() {
+        return mFramesPresentedTimeNano != null
+                ? mFramesPresentedTimeNano.length : 0;
+    }
+
+    /**
+     * Gets the start time of the interval for which these statistics
+     * apply. The start interval is the time when the first frame was
+     * presented.
+     *
+     * @return The start time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+     *         if there is no frame data.
+     */
+    public final long getStartTimeNano() {
+        if (getFrameCount() <= 0) {
+            return UNDEFINED_TIME_NANO;
+        }
+        return mFramesPresentedTimeNano[0];
+    }
+
+    /**
+     * Gets the end time of the interval for which these statistics
+     * apply. The end interval is the time when the last frame was
+     * presented.
+     *
+     * @return The end time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+     *         if there is no frame data.
+     */
+    public final long getEndTimeNano() {
+        if (getFrameCount() <= 0) {
+            return UNDEFINED_TIME_NANO;
+        }
+        return mFramesPresentedTimeNano[mFramesPresentedTimeNano.length - 1];
+    }
+
+    /**
+     * Get the time a frame at a given index was presented.
+     *
+     * @param index The frame index.
+     * @return The presented time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+     *         if the frame is not presented yet.
+     */
+    public final long getFramePresentedTimeNano(int index) {
+        if (mFramesPresentedTimeNano == null) {
+            throw new IndexOutOfBoundsException();
+        }
+        return mFramesPresentedTimeNano[index];
+    }
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index c274fc4..34b85d9 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -378,17 +378,6 @@
 
     private static native void nDrawLayer(long renderer, long layer, float x, float y);
 
-    void interrupt() {
-        nInterrupt(mRenderer);
-    }
-    
-    void resume() {
-        nResume(mRenderer);
-    }
-
-    private static native void nInterrupt(long renderer);
-    private static native void nResume(long renderer);
-
     ///////////////////////////////////////////////////////////////////////////
     // Support
     ///////////////////////////////////////////////////////////////////////////
@@ -1128,11 +1117,11 @@
     }
 
     @Override
-    public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
+    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+            Paint paint) {
         int modifiers = setupModifiers(paint, MODIFIER_SHADER);
         try {
-            nDrawRoundRect(mRenderer, rect.left, rect.top, rect.right, rect.bottom,
-                    rx, ry, paint.mNativePaint);
+            nDrawRoundRect(mRenderer, left, top, right, bottom, rx, ry, paint.mNativePaint);
         } finally {
             if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers);
         }
diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java
index bcdfda6..97339cc 100644
--- a/core/java/android/view/GLRenderer.java
+++ b/core/java/android/view/GLRenderer.java
@@ -555,7 +555,7 @@
     }
 
     @Override
-    public void invokeFunctor(long functor, boolean waitForCompletion) {
+    void invokeFunctor(long functor, boolean waitForCompletion) {
         boolean needsContext = !isEnabled() || checkRenderContext() == SURFACE_STATE_ERROR;
         boolean hasContext = !needsContext;
 
@@ -1177,7 +1177,7 @@
                     callbacks.onHardwarePreDraw(canvas);
 
                     if (displayList != null) {
-                        status |= drawDisplayList(attachInfo, canvas, displayList, status);
+                        status |= drawDisplayList(canvas, displayList, status);
                     } else {
                         // Shouldn't reach here
                         view.draw(canvas);
@@ -1226,11 +1226,6 @@
         }
     }
 
-    void setDisplayListData(long displayList, long newData) {
-        nSetDisplayListData(displayList, newData);
-    }
-    private static native void nSetDisplayListData(long displayList, long newData);
-
     @Override
     void fence() {
         // Everything is immediate, so this is a no-op
@@ -1313,8 +1308,8 @@
         return status;
     }
 
-    private int drawDisplayList(View.AttachInfo attachInfo, HardwareCanvas canvas,
-            RenderNode displayList, int status) {
+    private int drawDisplayList(HardwareCanvas canvas, RenderNode displayList,
+            int status) {
 
         long drawDisplayListStartTime = 0;
         if (mProfileEnabled) {
@@ -1322,7 +1317,7 @@
         }
 
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList");
-        nUpdateRenderNodeProperties(displayList.getNativeDisplayList());
+        nPrepareTree(displayList.getNativeDisplayList());
         try {
             status |= canvas.drawDisplayList(displayList, mRedrawClip,
                     RenderNode.FLAG_CLIP_CHILDREN);
@@ -1481,7 +1476,7 @@
 
     static native void nDestroyLayer(long layerPtr);
 
-    private static native void nUpdateRenderNodeProperties(long displayListPtr);
+    private static native void nPrepareTree(long displayListPtr);
 
     class DrawPerformanceDataProvider extends GraphDataProvider {
         private final int mGraphType;
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 7d46cab..d31c79d 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -453,7 +453,7 @@
      *                          has invoked. If false, the functor may be invoked
      *                          asynchronously.
      */
-    public abstract void invokeFunctor(long functor, boolean waitForCompletion);
+    abstract void invokeFunctor(long functor, boolean waitForCompletion);
 
     /**
      * Initializes the hardware renderer for the specified surface and setup the
@@ -580,8 +580,6 @@
         mRequested = requested;
     }
 
-    abstract void setDisplayListData(long displayList, long newData);
-
     /**
      * Blocks until all previously queued work has completed.
      */
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index 8ec07ef..3670eed 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -50,7 +50,6 @@
     void moved(int newX, int newY);
     void dispatchAppVisibility(boolean visible);
     void dispatchGetNewSurface();
-    void dispatchScreenState(boolean on);
 
     /**
      * Tell the window that it is either gaining or losing focus.  Keep it up
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8f542bb..7d13399 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -37,6 +37,7 @@
 import android.view.InputChannel;
 import android.view.InputDevice;
 import android.view.IInputFilter;
+import android.view.WindowContentFrameStats;
 
 /**
  * System private interface to the window manager.
@@ -233,4 +234,25 @@
      * Device is in safe mode.
      */
     boolean isSafeModeEnabled();
+
+    /**
+     * Enables the screen if all conditions are met.
+     */
+    void enableScreenIfNeeded();
+
+    /**
+     * Clears the frame statistics for a given window.
+     *
+     * @param token The window token.
+     * @return Whether the frame statistics were cleared.
+     */
+    boolean clearWindowContentFrameStats(IBinder token);
+
+    /**
+     * Gets the content frame statistics for a given window.
+     *
+     * @param token The window token.
+     * @return The frame statistics or null if the window does not exist.
+     */
+    WindowContentFrameStats getWindowContentFrameStats(IBinder token);
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index c183f08..05e202b 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -645,12 +645,11 @@
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
     //  frameworks/native/include/android/keycodes.h
-    //  frameworks/base/include/androidfw/KeycodeLabels.h
+    //  frameworks/base/include/androidfw/InputEventAttributes.h
     //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
     //  frameworks/base/core/res/res/values/attrs.xml
     //  emulator?
     //  LAST_KEYCODE
-    //  KEYCODE_SYMBOLIC_NAMES
     //
     //  Also Android currently does not reserve code ranges for vendor-
     //  specific key codes.  If you have new key codes to have, you
@@ -658,237 +657,6 @@
     //  those new codes.  This is intended to maintain a consistent
     //  set of key code definitions across all Android devices.
 
-    // Symbolic names of all key codes.
-    private static final SparseArray<String> KEYCODE_SYMBOLIC_NAMES = new SparseArray<String>();
-    private static void populateKeycodeSymbolicNames() {
-        SparseArray<String> names = KEYCODE_SYMBOLIC_NAMES;
-        names.append(KEYCODE_UNKNOWN, "KEYCODE_UNKNOWN");
-        names.append(KEYCODE_SOFT_LEFT, "KEYCODE_SOFT_LEFT");
-        names.append(KEYCODE_SOFT_RIGHT, "KEYCODE_SOFT_RIGHT");
-        names.append(KEYCODE_HOME, "KEYCODE_HOME");
-        names.append(KEYCODE_BACK, "KEYCODE_BACK");
-        names.append(KEYCODE_CALL, "KEYCODE_CALL");
-        names.append(KEYCODE_ENDCALL, "KEYCODE_ENDCALL");
-        names.append(KEYCODE_0, "KEYCODE_0");
-        names.append(KEYCODE_1, "KEYCODE_1");
-        names.append(KEYCODE_2, "KEYCODE_2");
-        names.append(KEYCODE_3, "KEYCODE_3");
-        names.append(KEYCODE_4, "KEYCODE_4");
-        names.append(KEYCODE_5, "KEYCODE_5");
-        names.append(KEYCODE_6, "KEYCODE_6");
-        names.append(KEYCODE_7, "KEYCODE_7");
-        names.append(KEYCODE_8, "KEYCODE_8");
-        names.append(KEYCODE_9, "KEYCODE_9");
-        names.append(KEYCODE_STAR, "KEYCODE_STAR");
-        names.append(KEYCODE_POUND, "KEYCODE_POUND");
-        names.append(KEYCODE_DPAD_UP, "KEYCODE_DPAD_UP");
-        names.append(KEYCODE_DPAD_DOWN, "KEYCODE_DPAD_DOWN");
-        names.append(KEYCODE_DPAD_LEFT, "KEYCODE_DPAD_LEFT");
-        names.append(KEYCODE_DPAD_RIGHT, "KEYCODE_DPAD_RIGHT");
-        names.append(KEYCODE_DPAD_CENTER, "KEYCODE_DPAD_CENTER");
-        names.append(KEYCODE_VOLUME_UP, "KEYCODE_VOLUME_UP");
-        names.append(KEYCODE_VOLUME_DOWN, "KEYCODE_VOLUME_DOWN");
-        names.append(KEYCODE_POWER, "KEYCODE_POWER");
-        names.append(KEYCODE_CAMERA, "KEYCODE_CAMERA");
-        names.append(KEYCODE_CLEAR, "KEYCODE_CLEAR");
-        names.append(KEYCODE_A, "KEYCODE_A");
-        names.append(KEYCODE_B, "KEYCODE_B");
-        names.append(KEYCODE_C, "KEYCODE_C");
-        names.append(KEYCODE_D, "KEYCODE_D");
-        names.append(KEYCODE_E, "KEYCODE_E");
-        names.append(KEYCODE_F, "KEYCODE_F");
-        names.append(KEYCODE_G, "KEYCODE_G");
-        names.append(KEYCODE_H, "KEYCODE_H");
-        names.append(KEYCODE_I, "KEYCODE_I");
-        names.append(KEYCODE_J, "KEYCODE_J");
-        names.append(KEYCODE_K, "KEYCODE_K");
-        names.append(KEYCODE_L, "KEYCODE_L");
-        names.append(KEYCODE_M, "KEYCODE_M");
-        names.append(KEYCODE_N, "KEYCODE_N");
-        names.append(KEYCODE_O, "KEYCODE_O");
-        names.append(KEYCODE_P, "KEYCODE_P");
-        names.append(KEYCODE_Q, "KEYCODE_Q");
-        names.append(KEYCODE_R, "KEYCODE_R");
-        names.append(KEYCODE_S, "KEYCODE_S");
-        names.append(KEYCODE_T, "KEYCODE_T");
-        names.append(KEYCODE_U, "KEYCODE_U");
-        names.append(KEYCODE_V, "KEYCODE_V");
-        names.append(KEYCODE_W, "KEYCODE_W");
-        names.append(KEYCODE_X, "KEYCODE_X");
-        names.append(KEYCODE_Y, "KEYCODE_Y");
-        names.append(KEYCODE_Z, "KEYCODE_Z");
-        names.append(KEYCODE_COMMA, "KEYCODE_COMMA");
-        names.append(KEYCODE_PERIOD, "KEYCODE_PERIOD");
-        names.append(KEYCODE_ALT_LEFT, "KEYCODE_ALT_LEFT");
-        names.append(KEYCODE_ALT_RIGHT, "KEYCODE_ALT_RIGHT");
-        names.append(KEYCODE_SHIFT_LEFT, "KEYCODE_SHIFT_LEFT");
-        names.append(KEYCODE_SHIFT_RIGHT, "KEYCODE_SHIFT_RIGHT");
-        names.append(KEYCODE_TAB, "KEYCODE_TAB");
-        names.append(KEYCODE_SPACE, "KEYCODE_SPACE");
-        names.append(KEYCODE_SYM, "KEYCODE_SYM");
-        names.append(KEYCODE_EXPLORER, "KEYCODE_EXPLORER");
-        names.append(KEYCODE_ENVELOPE, "KEYCODE_ENVELOPE");
-        names.append(KEYCODE_ENTER, "KEYCODE_ENTER");
-        names.append(KEYCODE_DEL, "KEYCODE_DEL");
-        names.append(KEYCODE_GRAVE, "KEYCODE_GRAVE");
-        names.append(KEYCODE_MINUS, "KEYCODE_MINUS");
-        names.append(KEYCODE_EQUALS, "KEYCODE_EQUALS");
-        names.append(KEYCODE_LEFT_BRACKET, "KEYCODE_LEFT_BRACKET");
-        names.append(KEYCODE_RIGHT_BRACKET, "KEYCODE_RIGHT_BRACKET");
-        names.append(KEYCODE_BACKSLASH, "KEYCODE_BACKSLASH");
-        names.append(KEYCODE_SEMICOLON, "KEYCODE_SEMICOLON");
-        names.append(KEYCODE_APOSTROPHE, "KEYCODE_APOSTROPHE");
-        names.append(KEYCODE_SLASH, "KEYCODE_SLASH");
-        names.append(KEYCODE_AT, "KEYCODE_AT");
-        names.append(KEYCODE_NUM, "KEYCODE_NUM");
-        names.append(KEYCODE_HEADSETHOOK, "KEYCODE_HEADSETHOOK");
-        names.append(KEYCODE_FOCUS, "KEYCODE_FOCUS");
-        names.append(KEYCODE_PLUS, "KEYCODE_PLUS");
-        names.append(KEYCODE_MENU, "KEYCODE_MENU");
-        names.append(KEYCODE_NOTIFICATION, "KEYCODE_NOTIFICATION");
-        names.append(KEYCODE_SEARCH, "KEYCODE_SEARCH");
-        names.append(KEYCODE_MEDIA_PLAY_PAUSE, "KEYCODE_MEDIA_PLAY_PAUSE");
-        names.append(KEYCODE_MEDIA_STOP, "KEYCODE_MEDIA_STOP");
-        names.append(KEYCODE_MEDIA_NEXT, "KEYCODE_MEDIA_NEXT");
-        names.append(KEYCODE_MEDIA_PREVIOUS, "KEYCODE_MEDIA_PREVIOUS");
-        names.append(KEYCODE_MEDIA_REWIND, "KEYCODE_MEDIA_REWIND");
-        names.append(KEYCODE_MEDIA_FAST_FORWARD, "KEYCODE_MEDIA_FAST_FORWARD");
-        names.append(KEYCODE_MUTE, "KEYCODE_MUTE");
-        names.append(KEYCODE_PAGE_UP, "KEYCODE_PAGE_UP");
-        names.append(KEYCODE_PAGE_DOWN, "KEYCODE_PAGE_DOWN");
-        names.append(KEYCODE_PICTSYMBOLS, "KEYCODE_PICTSYMBOLS");
-        names.append(KEYCODE_SWITCH_CHARSET, "KEYCODE_SWITCH_CHARSET");
-        names.append(KEYCODE_BUTTON_A, "KEYCODE_BUTTON_A");
-        names.append(KEYCODE_BUTTON_B, "KEYCODE_BUTTON_B");
-        names.append(KEYCODE_BUTTON_C, "KEYCODE_BUTTON_C");
-        names.append(KEYCODE_BUTTON_X, "KEYCODE_BUTTON_X");
-        names.append(KEYCODE_BUTTON_Y, "KEYCODE_BUTTON_Y");
-        names.append(KEYCODE_BUTTON_Z, "KEYCODE_BUTTON_Z");
-        names.append(KEYCODE_BUTTON_L1, "KEYCODE_BUTTON_L1");
-        names.append(KEYCODE_BUTTON_R1, "KEYCODE_BUTTON_R1");
-        names.append(KEYCODE_BUTTON_L2, "KEYCODE_BUTTON_L2");
-        names.append(KEYCODE_BUTTON_R2, "KEYCODE_BUTTON_R2");
-        names.append(KEYCODE_BUTTON_THUMBL, "KEYCODE_BUTTON_THUMBL");
-        names.append(KEYCODE_BUTTON_THUMBR, "KEYCODE_BUTTON_THUMBR");
-        names.append(KEYCODE_BUTTON_START, "KEYCODE_BUTTON_START");
-        names.append(KEYCODE_BUTTON_SELECT, "KEYCODE_BUTTON_SELECT");
-        names.append(KEYCODE_BUTTON_MODE, "KEYCODE_BUTTON_MODE");
-        names.append(KEYCODE_ESCAPE, "KEYCODE_ESCAPE");
-        names.append(KEYCODE_FORWARD_DEL, "KEYCODE_FORWARD_DEL");
-        names.append(KEYCODE_CTRL_LEFT, "KEYCODE_CTRL_LEFT");
-        names.append(KEYCODE_CTRL_RIGHT, "KEYCODE_CTRL_RIGHT");
-        names.append(KEYCODE_CAPS_LOCK, "KEYCODE_CAPS_LOCK");
-        names.append(KEYCODE_SCROLL_LOCK, "KEYCODE_SCROLL_LOCK");
-        names.append(KEYCODE_META_LEFT, "KEYCODE_META_LEFT");
-        names.append(KEYCODE_META_RIGHT, "KEYCODE_META_RIGHT");
-        names.append(KEYCODE_FUNCTION, "KEYCODE_FUNCTION");
-        names.append(KEYCODE_SYSRQ, "KEYCODE_SYSRQ");
-        names.append(KEYCODE_BREAK, "KEYCODE_BREAK");
-        names.append(KEYCODE_MOVE_HOME, "KEYCODE_MOVE_HOME");
-        names.append(KEYCODE_MOVE_END, "KEYCODE_MOVE_END");
-        names.append(KEYCODE_INSERT, "KEYCODE_INSERT");
-        names.append(KEYCODE_FORWARD, "KEYCODE_FORWARD");
-        names.append(KEYCODE_MEDIA_PLAY, "KEYCODE_MEDIA_PLAY");
-        names.append(KEYCODE_MEDIA_PAUSE, "KEYCODE_MEDIA_PAUSE");
-        names.append(KEYCODE_MEDIA_CLOSE, "KEYCODE_MEDIA_CLOSE");
-        names.append(KEYCODE_MEDIA_EJECT, "KEYCODE_MEDIA_EJECT");
-        names.append(KEYCODE_MEDIA_RECORD, "KEYCODE_MEDIA_RECORD");
-        names.append(KEYCODE_F1, "KEYCODE_F1");
-        names.append(KEYCODE_F2, "KEYCODE_F2");
-        names.append(KEYCODE_F3, "KEYCODE_F3");
-        names.append(KEYCODE_F4, "KEYCODE_F4");
-        names.append(KEYCODE_F5, "KEYCODE_F5");
-        names.append(KEYCODE_F6, "KEYCODE_F6");
-        names.append(KEYCODE_F7, "KEYCODE_F7");
-        names.append(KEYCODE_F8, "KEYCODE_F8");
-        names.append(KEYCODE_F9, "KEYCODE_F9");
-        names.append(KEYCODE_F10, "KEYCODE_F10");
-        names.append(KEYCODE_F11, "KEYCODE_F11");
-        names.append(KEYCODE_F12, "KEYCODE_F12");
-        names.append(KEYCODE_NUM_LOCK, "KEYCODE_NUM_LOCK");
-        names.append(KEYCODE_NUMPAD_0, "KEYCODE_NUMPAD_0");
-        names.append(KEYCODE_NUMPAD_1, "KEYCODE_NUMPAD_1");
-        names.append(KEYCODE_NUMPAD_2, "KEYCODE_NUMPAD_2");
-        names.append(KEYCODE_NUMPAD_3, "KEYCODE_NUMPAD_3");
-        names.append(KEYCODE_NUMPAD_4, "KEYCODE_NUMPAD_4");
-        names.append(KEYCODE_NUMPAD_5, "KEYCODE_NUMPAD_5");
-        names.append(KEYCODE_NUMPAD_6, "KEYCODE_NUMPAD_6");
-        names.append(KEYCODE_NUMPAD_7, "KEYCODE_NUMPAD_7");
-        names.append(KEYCODE_NUMPAD_8, "KEYCODE_NUMPAD_8");
-        names.append(KEYCODE_NUMPAD_9, "KEYCODE_NUMPAD_9");
-        names.append(KEYCODE_NUMPAD_DIVIDE, "KEYCODE_NUMPAD_DIVIDE");
-        names.append(KEYCODE_NUMPAD_MULTIPLY, "KEYCODE_NUMPAD_MULTIPLY");
-        names.append(KEYCODE_NUMPAD_SUBTRACT, "KEYCODE_NUMPAD_SUBTRACT");
-        names.append(KEYCODE_NUMPAD_ADD, "KEYCODE_NUMPAD_ADD");
-        names.append(KEYCODE_NUMPAD_DOT, "KEYCODE_NUMPAD_DOT");
-        names.append(KEYCODE_NUMPAD_COMMA, "KEYCODE_NUMPAD_COMMA");
-        names.append(KEYCODE_NUMPAD_ENTER, "KEYCODE_NUMPAD_ENTER");
-        names.append(KEYCODE_NUMPAD_EQUALS, "KEYCODE_NUMPAD_EQUALS");
-        names.append(KEYCODE_NUMPAD_LEFT_PAREN, "KEYCODE_NUMPAD_LEFT_PAREN");
-        names.append(KEYCODE_NUMPAD_RIGHT_PAREN, "KEYCODE_NUMPAD_RIGHT_PAREN");
-        names.append(KEYCODE_VOLUME_MUTE, "KEYCODE_VOLUME_MUTE");
-        names.append(KEYCODE_INFO, "KEYCODE_INFO");
-        names.append(KEYCODE_CHANNEL_UP, "KEYCODE_CHANNEL_UP");
-        names.append(KEYCODE_CHANNEL_DOWN, "KEYCODE_CHANNEL_DOWN");
-        names.append(KEYCODE_ZOOM_IN, "KEYCODE_ZOOM_IN");
-        names.append(KEYCODE_ZOOM_OUT, "KEYCODE_ZOOM_OUT");
-        names.append(KEYCODE_TV, "KEYCODE_TV");
-        names.append(KEYCODE_WINDOW, "KEYCODE_WINDOW");
-        names.append(KEYCODE_GUIDE, "KEYCODE_GUIDE");
-        names.append(KEYCODE_DVR, "KEYCODE_DVR");
-        names.append(KEYCODE_BOOKMARK, "KEYCODE_BOOKMARK");
-        names.append(KEYCODE_CAPTIONS, "KEYCODE_CAPTIONS");
-        names.append(KEYCODE_SETTINGS, "KEYCODE_SETTINGS");
-        names.append(KEYCODE_TV_POWER, "KEYCODE_TV_POWER");
-        names.append(KEYCODE_TV_INPUT, "KEYCODE_TV_INPUT");
-        names.append(KEYCODE_STB_INPUT, "KEYCODE_STB_INPUT");
-        names.append(KEYCODE_STB_POWER, "KEYCODE_STB_POWER");
-        names.append(KEYCODE_AVR_POWER, "KEYCODE_AVR_POWER");
-        names.append(KEYCODE_AVR_INPUT, "KEYCODE_AVR_INPUT");
-        names.append(KEYCODE_PROG_RED, "KEYCODE_PROG_RED");
-        names.append(KEYCODE_PROG_GREEN, "KEYCODE_PROG_GREEN");
-        names.append(KEYCODE_PROG_YELLOW, "KEYCODE_PROG_YELLOW");
-        names.append(KEYCODE_PROG_BLUE, "KEYCODE_PROG_BLUE");
-        names.append(KEYCODE_APP_SWITCH, "KEYCODE_APP_SWITCH");
-        names.append(KEYCODE_BUTTON_1, "KEYCODE_BUTTON_1");
-        names.append(KEYCODE_BUTTON_2, "KEYCODE_BUTTON_2");
-        names.append(KEYCODE_BUTTON_3, "KEYCODE_BUTTON_3");
-        names.append(KEYCODE_BUTTON_4, "KEYCODE_BUTTON_4");
-        names.append(KEYCODE_BUTTON_5, "KEYCODE_BUTTON_5");
-        names.append(KEYCODE_BUTTON_6, "KEYCODE_BUTTON_6");
-        names.append(KEYCODE_BUTTON_7, "KEYCODE_BUTTON_7");
-        names.append(KEYCODE_BUTTON_8, "KEYCODE_BUTTON_8");
-        names.append(KEYCODE_BUTTON_9, "KEYCODE_BUTTON_9");
-        names.append(KEYCODE_BUTTON_10, "KEYCODE_BUTTON_10");
-        names.append(KEYCODE_BUTTON_11, "KEYCODE_BUTTON_11");
-        names.append(KEYCODE_BUTTON_12, "KEYCODE_BUTTON_12");
-        names.append(KEYCODE_BUTTON_13, "KEYCODE_BUTTON_13");
-        names.append(KEYCODE_BUTTON_14, "KEYCODE_BUTTON_14");
-        names.append(KEYCODE_BUTTON_15, "KEYCODE_BUTTON_15");
-        names.append(KEYCODE_BUTTON_16, "KEYCODE_BUTTON_16");
-        names.append(KEYCODE_LANGUAGE_SWITCH, "KEYCODE_LANGUAGE_SWITCH");
-        names.append(KEYCODE_MANNER_MODE, "KEYCODE_MANNER_MODE");
-        names.append(KEYCODE_3D_MODE, "KEYCODE_3D_MODE");
-        names.append(KEYCODE_CONTACTS, "KEYCODE_CONTACTS");
-        names.append(KEYCODE_CALENDAR, "KEYCODE_CALENDAR");
-        names.append(KEYCODE_MUSIC, "KEYCODE_MUSIC");
-        names.append(KEYCODE_CALCULATOR, "KEYCODE_CALCULATOR");
-        names.append(KEYCODE_ZENKAKU_HANKAKU, "KEYCODE_ZENKAKU_HANKAKU");
-        names.append(KEYCODE_EISU, "KEYCODE_EISU");
-        names.append(KEYCODE_MUHENKAN, "KEYCODE_MUHENKAN");
-        names.append(KEYCODE_HENKAN, "KEYCODE_HENKAN");
-        names.append(KEYCODE_KATAKANA_HIRAGANA, "KEYCODE_KATAKANA_HIRAGANA");
-        names.append(KEYCODE_YEN, "KEYCODE_YEN");
-        names.append(KEYCODE_RO, "KEYCODE_RO");
-        names.append(KEYCODE_KANA, "KEYCODE_KANA");
-        names.append(KEYCODE_ASSIST, "KEYCODE_ASSIST");
-        names.append(KEYCODE_BRIGHTNESS_DOWN, "KEYCODE_BRIGHTNESS_DOWN");
-        names.append(KEYCODE_BRIGHTNESS_UP, "KEYCODE_BRIGHTNESS_UP");
-        names.append(KEYCODE_MEDIA_AUDIO_TRACK, "KEYCODE_MEDIA_AUDIO_TRACK");
-        names.append(KEYCODE_SLEEP, "KEYCODE_SLEEP");
-        names.append(KEYCODE_WAKEUP, "KEYCODE_WAKEUP");
-    };
-
     // Symbolic names of all metakeys in bit order from least significant to most significant.
     // Accordingly there are exactly 32 values in this table.
     private static final String[] META_SYMBOLIC_NAMES = new String[] {
@@ -926,6 +694,8 @@
         "0x80000000",
     };
 
+    private static final String LABEL_PREFIX = "KEYCODE_";
+
     /**
      * @deprecated There are now more than MAX_KEYCODE keycodes.
      * Use {@link #getMaxKeyCode()} instead.
@@ -1166,7 +936,11 @@
 
     /**
      * This mask is set if the device woke because of this key event.
+     *
+     * @deprecated This flag will never be set by the system since the system
+     * consumes all wake keys itself.
      */
+    @Deprecated
     public static final int FLAG_WOKE_HERE = 0x1;
 
     /**
@@ -1363,9 +1137,8 @@
         boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
     }
 
-    static {
-        populateKeycodeSymbolicNames();
-    }
+    private static native String nativeKeyCodeToString(int keyCode);
+    private static native int nativeKeyCodeFromString(String keyCode);
 
     private KeyEvent() {
     }
@@ -1788,19 +1561,15 @@
         return mAction == ACTION_DOWN;
     }
 
-    /**
-     * Is this a system key?  System keys can not be used for menu shortcuts.
-     *
-     * TODO: this information should come from a table somewhere.
-     * TODO: should the dpad keys be here?  arguably, because they also shouldn't be menu shortcuts
+    /** Is this a system key?  System keys can not be used for menu shortcuts.
      */
     public final boolean isSystem() {
-        return native_isSystemKey(mKeyCode);
+        return isSystemKey(mKeyCode);
     }
 
     /** @hide */
-    public final boolean hasDefaultAction() {
-        return native_hasDefaultAction(mKeyCode);
+    public final boolean isWakeKey() {
+        return isWakeKey(mKeyCode);
     }
 
     /**
@@ -1883,6 +1652,62 @@
         return false;
     }
 
+
+    /** Is this a system key? System keys can not be used for menu shortcuts.
+     * @hide
+     */
+    public static final boolean isSystemKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_MENU:
+            case KeyEvent.KEYCODE_SOFT_RIGHT:
+            case KeyEvent.KEYCODE_HOME:
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_CALL:
+            case KeyEvent.KEYCODE_ENDCALL:
+            case KeyEvent.KEYCODE_VOLUME_UP:
+            case KeyEvent.KEYCODE_VOLUME_DOWN:
+            case KeyEvent.KEYCODE_VOLUME_MUTE:
+            case KeyEvent.KEYCODE_MUTE:
+            case KeyEvent.KEYCODE_POWER:
+            case KeyEvent.KEYCODE_HEADSETHOOK:
+            case KeyEvent.KEYCODE_MEDIA_PLAY:
+            case KeyEvent.KEYCODE_MEDIA_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
+            case KeyEvent.KEYCODE_MEDIA_STOP:
+            case KeyEvent.KEYCODE_MEDIA_NEXT:
+            case KeyEvent.KEYCODE_MEDIA_PREVIOUS:
+            case KeyEvent.KEYCODE_MEDIA_REWIND:
+            case KeyEvent.KEYCODE_MEDIA_RECORD:
+            case KeyEvent.KEYCODE_MEDIA_FAST_FORWARD:
+            case KeyEvent.KEYCODE_CAMERA:
+            case KeyEvent.KEYCODE_FOCUS:
+            case KeyEvent.KEYCODE_SEARCH:
+            case KeyEvent.KEYCODE_BRIGHTNESS_DOWN:
+            case KeyEvent.KEYCODE_BRIGHTNESS_UP:
+            case KeyEvent.KEYCODE_MEDIA_AUDIO_TRACK:
+            case KeyEvent.KEYCODE_DPAD_UP:
+            case KeyEvent.KEYCODE_DPAD_RIGHT:
+            case KeyEvent.KEYCODE_DPAD_DOWN:
+            case KeyEvent.KEYCODE_DPAD_LEFT:
+                return true;
+        }
+
+        return false;
+    }
+
+    /** @hide */
+    public static final boolean isWakeKey(int keyCode) {
+        switch (keyCode) {
+            case KeyEvent.KEYCODE_BACK:
+            case KeyEvent.KEYCODE_POWER:
+            case KeyEvent.KEYCODE_MENU:
+            case KeyEvent.KEYCODE_SLEEP:
+            case KeyEvent.KEYCODE_WAKEUP:
+                return true;
+        }
+        return false;
+    }
+
     /** {@inheritDoc} */
     @Override
     public final int getDeviceId() {
@@ -2862,8 +2687,8 @@
      * @see KeyCharacterMap#getDisplayLabel
      */
     public static String keyCodeToString(int keyCode) {
-        String symbolicName = KEYCODE_SYMBOLIC_NAMES.get(keyCode);
-        return symbolicName != null ? symbolicName : Integer.toString(keyCode);
+        String symbolicName = nativeKeyCodeToString(keyCode);
+        return symbolicName != null ? LABEL_PREFIX + symbolicName : Integer.toString(keyCode);
     }
 
     /**
@@ -2875,17 +2700,13 @@
      * @see #keycodeToString(int)
      */
     public static int keyCodeFromString(String symbolicName) {
-        if (symbolicName == null) {
-            throw new IllegalArgumentException("symbolicName must not be null");
+        if (symbolicName.startsWith(LABEL_PREFIX)) {
+            symbolicName = symbolicName.substring(LABEL_PREFIX.length());
         }
-
-        final int count = KEYCODE_SYMBOLIC_NAMES.size();
-        for (int i = 0; i < count; i++) {
-            if (symbolicName.equals(KEYCODE_SYMBOLIC_NAMES.valueAt(i))) {
-                return i;
-            }
+        int keyCode = nativeKeyCodeFromString(symbolicName);
+        if (keyCode > 0) {
+            return keyCode;
         }
-
         try {
             return Integer.parseInt(symbolicName, 10);
         } catch (NumberFormatException ex) {
@@ -2973,7 +2794,4 @@
         out.writeLong(mDownTime);
         out.writeLong(mEventTime);
     }
-
-    private native boolean native_isSystemKey(int keyCode);
-    private native boolean native_hasDefaultAction(int keyCode);
 }
diff --git a/core/java/android/view/MenuInflater.java b/core/java/android/view/MenuInflater.java
index a7ee12b..71296fa 100644
--- a/core/java/android/view/MenuInflater.java
+++ b/core/java/android/view/MenuInflater.java
@@ -161,6 +161,7 @@
                     } else if (tagName.equals(XML_MENU)) {
                         // A menu start tag denotes a submenu for an item
                         SubMenu subMenu = menuState.addSubMenuItem();
+                        registerMenu(subMenu, attrs);
 
                         // Parse the submenu into returned SubMenu
                         parseMenu(parser, attrs, subMenu);
@@ -183,9 +184,9 @@
                         if (!menuState.hasAddedItem()) {
                             if (menuState.itemActionProvider != null &&
                                     menuState.itemActionProvider.hasSubMenu()) {
-                                menuState.addSubMenuItem();
+                                registerMenu(menuState.addSubMenuItem(), attrs);
                             } else {
-                                menuState.addItem();
+                                registerMenu(menuState.addItem(), attrs);
                             }
                         }
                     } else if (tagName.equals(XML_MENU)) {
@@ -200,7 +201,30 @@
             eventType = parser.next();
         }
     }
-    
+
+    /**
+     * The method is a hook for layoutlib to do its magic.
+     * Nothing is needed outside of LayoutLib. However, it should not be deleted because it
+     * appears to do nothing.
+     */
+    private void registerMenu(@SuppressWarnings("unused") MenuItem item,
+            @SuppressWarnings("unused") AttributeSet set) {
+    }
+
+    /**
+     * The method is a hook for layoutlib to do its magic.
+     * Nothing is needed outside of LayoutLib. However, it should not be deleted because it
+     * appears to do nothing.
+     */
+    private void registerMenu(@SuppressWarnings("unused") SubMenu subMenu,
+            @SuppressWarnings("unused") AttributeSet set) {
+    }
+
+    // Needed by layoutlib.
+    /*package*/ Context getContext() {
+        return mContext;
+    }
+
     private static class InflatedOnMenuItemClickListener
             implements MenuItem.OnMenuItemClickListener {
         private static final Class<?>[] PARAM_TYPES = new Class[] { MenuItem.class };
@@ -446,9 +470,11 @@
             }
         }
 
-        public void addItem() {
+        public MenuItem addItem() {
             itemAdded = true;
-            setItem(menu.add(groupId, itemId, itemCategoryOrder, itemTitle));
+            MenuItem item = menu.add(groupId, itemId, itemCategoryOrder, itemTitle);
+            setItem(item);
+            return item;
         }
         
         public SubMenu addSubMenuItem() {
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 6378ffd..0626ab9 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -167,6 +167,7 @@
  */
 public final class MotionEvent extends InputEvent implements Parcelable {
     private static final long NS_PER_MS = 1000000;
+    private static final String LABEL_PREFIX = "AXIS_";
 
     /**
      * An invalid pointer id.
@@ -1369,6 +1370,9 @@
     private static native long nativeReadFromParcel(long nativePtr, Parcel parcel);
     private static native void nativeWriteToParcel(long nativePtr, Parcel parcel);
 
+    private static native String nativeAxisToString(int axis);
+    private static native int nativeAxisFromString(String label);
+
     private MotionEvent() {
     }
 
@@ -3051,8 +3055,8 @@
      * @return The symbolic name of the specified axis.
      */
     public static String axisToString(int axis) {
-        String symbolicName = AXIS_SYMBOLIC_NAMES.get(axis);
-        return symbolicName != null ? symbolicName : Integer.toString(axis);
+        String symbolicName = nativeAxisToString(axis);
+        return symbolicName != null ? LABEL_PREFIX + symbolicName : Integer.toString(axis);
     }
 
     /**
@@ -3064,17 +3068,13 @@
      * @see KeyEvent#keyCodeToString(int)
      */
     public static int axisFromString(String symbolicName) {
-        if (symbolicName == null) {
-            throw new IllegalArgumentException("symbolicName must not be null");
+        if (symbolicName.startsWith(LABEL_PREFIX)) {
+            symbolicName = symbolicName.substring(LABEL_PREFIX.length());
         }
-
-        final int count = AXIS_SYMBOLIC_NAMES.size();
-        for (int i = 0; i < count; i++) {
-            if (symbolicName.equals(AXIS_SYMBOLIC_NAMES.valueAt(i))) {
-                return i;
-            }
+        int axis = nativeAxisFromString(symbolicName);
+        if (axis >= 0) {
+            return axis;
         }
-
         try {
             return Integer.parseInt(symbolicName, 10);
         } catch (NumberFormatException ex) {
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 78ddf5b..8b80c3e0 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -20,6 +20,9 @@
 import android.graphics.Matrix;
 import android.graphics.Outline;
 
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * <p>A display list records a series of graphics related operations and can replay
  * them later. Display lists are usually built by recording operations on a
@@ -174,12 +177,23 @@
     public static final int STATUS_DREW = 0x4;
 
     private boolean mValid;
-    private final long mNativeDisplayList;
-    private HardwareRenderer mRenderer;
+    private final long mNativeRenderNode;
+
+    // We need to keep a strong reference to all running animators to ensure that
+    // they can call removeAnimator when they have finished, as the native-side
+    // object can only hold a WeakReference<> to avoid leaking memory due to
+    // cyclic references.
+    private List<RenderNodeAnimator> mActiveAnimators;
 
     private RenderNode(String name) {
-        mNativeDisplayList = nCreate();
-        nSetDisplayListName(mNativeDisplayList, name);
+        mNativeRenderNode = nCreate(name);
+    }
+
+    /**
+     * @see RenderNode#adopt(long)
+     */
+    private RenderNode(long nativePtr) {
+        mNativeRenderNode = nativePtr;
     }
 
     /**
@@ -197,12 +211,23 @@
     }
 
     /**
+     * Adopts an existing native render node.
+     *
+     * Note: This will *NOT* incRef() on the native object, however it will
+     * decRef() when it is destroyed. The caller should have already incRef'd it
+     */
+    public static RenderNode adopt(long nativePtr) {
+        return new RenderNode(nativePtr);
+    }
+
+
+    /**
      * Starts recording a display list for the render node. All
      * operations performed on the returned canvas are recorded and
      * stored in this display list.
      *
      * Calling this method will mark the render node invalid until
-     * {@link #end(HardwareRenderer, HardwareCanvas)} is called.
+     * {@link #end(HardwareCanvas)} is called.
      * Only valid render nodes can be replayed.
      *
      * @param width The width of the recording viewport
@@ -210,7 +235,7 @@
      *
      * @return A canvas to record drawing operations.
      *
-     * @see #end(HardwareRenderer, HardwareCanvas)
+     * @see #end(HardwareCanvas)
      * @see #isValid()
      */
     public HardwareCanvas start(int width, int height) {
@@ -229,21 +254,15 @@
      * @see #start(int, int)
      * @see #isValid()
      */
-    public void end(HardwareRenderer renderer, HardwareCanvas endCanvas) {
+    public void end(HardwareCanvas endCanvas) {
         if (!(endCanvas instanceof GLES20RecordingCanvas)) {
             throw new IllegalArgumentException("Passed an invalid canvas to end!");
         }
 
         GLES20RecordingCanvas canvas = (GLES20RecordingCanvas) endCanvas;
         canvas.onPostDraw();
-        long displayListData = canvas.finishRecording();
-        if (renderer != mRenderer) {
-            // If we are changing renderers first destroy with the old
-            // renderer, then set with the new one
-            destroyDisplayListData();
-        }
-        mRenderer = renderer;
-        setDisplayListData(displayListData);
+        long renderNodeData = canvas.finishRecording();
+        nSetDisplayListData(mNativeRenderNode, renderNodeData);
         canvas.recycle();
         mValid = true;
     }
@@ -258,19 +277,10 @@
     public void destroyDisplayListData() {
         if (!mValid) return;
 
-        setDisplayListData(0);
-        mRenderer = null;
+        nSetDisplayListData(mNativeRenderNode, 0);
         mValid = false;
     }
 
-    private void setDisplayListData(long newData) {
-        if (mRenderer != null) {
-            mRenderer.setDisplayListData(mNativeDisplayList, newData);
-        } else {
-            throw new IllegalStateException("Trying to set data without a renderer! data=" + newData);
-        }
-    }
-
     /**
      * Returns whether the RenderNode's display list content is currently usable.
      * If this returns false, the display list should be re-recorded prior to replaying it.
@@ -283,7 +293,7 @@
         if (!mValid) {
             throw new IllegalStateException("The display list is not valid.");
         }
-        return mNativeDisplayList;
+        return mNativeRenderNode;
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -291,15 +301,15 @@
     ///////////////////////////////////////////////////////////////////////////
 
     public boolean hasIdentityMatrix() {
-        return nHasIdentityMatrix(mNativeDisplayList);
+        return nHasIdentityMatrix(mNativeRenderNode);
     }
 
     public void getMatrix(@NonNull Matrix outMatrix) {
-        nGetTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+        nGetTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
     }
 
     public void getInverseMatrix(@NonNull Matrix outMatrix) {
-        nGetInverseTransformMatrix(mNativeDisplayList, outMatrix.native_instance);
+        nGetInverseTransformMatrix(mNativeRenderNode, outMatrix.native_instance);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -316,7 +326,7 @@
      * @hide
      */
     public void setCaching(boolean caching) {
-        nSetCaching(mNativeDisplayList, caching);
+        nSetCaching(mNativeRenderNode, caching);
     }
 
     /**
@@ -326,7 +336,7 @@
      * @param clipToBounds true if the display list should clip to its bounds
      */
     public void setClipToBounds(boolean clipToBounds) {
-        nSetClipToBounds(mNativeDisplayList, clipToBounds);
+        nSetClipToBounds(mNativeRenderNode, clipToBounds);
     }
 
     /**
@@ -337,7 +347,7 @@
      *            containing volume.
      */
     public void setProjectBackwards(boolean shouldProject) {
-        nSetProjectBackwards(mNativeDisplayList, shouldProject);
+        nSetProjectBackwards(mNativeRenderNode, shouldProject);
     }
 
     /**
@@ -346,7 +356,7 @@
      * ProjectBackwards=true directly on top of it. Default value is false.
      */
     public void setProjectionReceiver(boolean shouldRecieve) {
-        nSetProjectionReceiver(mNativeDisplayList, shouldRecieve);
+        nSetProjectionReceiver(mNativeRenderNode, shouldRecieve);
     }
 
     /**
@@ -357,14 +367,14 @@
      */
     public void setOutline(Outline outline) {
         if (outline == null) {
-            nSetOutlineEmpty(mNativeDisplayList);
+            nSetOutlineEmpty(mNativeRenderNode);
         } else if (!outline.isValid()) {
             throw new IllegalArgumentException("Outline must be valid");
         } else if (outline.mRect != null) {
-            nSetOutlineRoundRect(mNativeDisplayList, outline.mRect.left, outline.mRect.top,
+            nSetOutlineRoundRect(mNativeRenderNode, outline.mRect.left, outline.mRect.top,
                     outline.mRect.right, outline.mRect.bottom, outline.mRadius);
         } else if (outline.mPath != null) {
-            nSetOutlineConvexPath(mNativeDisplayList, outline.mPath.mNativePath);
+            nSetOutlineConvexPath(mNativeRenderNode, outline.mPath.mNativePath);
         }
     }
 
@@ -374,7 +384,7 @@
      * @param clipToOutline true if clipping to the outline.
      */
     public void setClipToOutline(boolean clipToOutline) {
-        nSetClipToOutline(mNativeDisplayList, clipToOutline);
+        nSetClipToOutline(mNativeRenderNode, clipToOutline);
     }
 
     /**
@@ -382,7 +392,7 @@
      */
     public void setRevealClip(boolean shouldClip, boolean inverseClip,
             float x, float y, float radius) {
-        nSetRevealClip(mNativeDisplayList, shouldClip, inverseClip, x, y, radius);
+        nSetRevealClip(mNativeRenderNode, shouldClip, inverseClip, x, y, radius);
     }
 
     /**
@@ -392,7 +402,7 @@
      * @param matrix A transform matrix to apply to this display list
      */
     public void setStaticMatrix(Matrix matrix) {
-        nSetStaticMatrix(mNativeDisplayList, matrix.native_instance);
+        nSetStaticMatrix(mNativeRenderNode, matrix.native_instance);
     }
 
     /**
@@ -406,7 +416,7 @@
      * @hide
      */
     public void setAnimationMatrix(Matrix matrix) {
-        nSetAnimationMatrix(mNativeDisplayList,
+        nSetAnimationMatrix(mNativeRenderNode,
                 (matrix != null) ? matrix.native_instance : 0);
     }
 
@@ -419,7 +429,7 @@
      * @see #getAlpha()
      */
     public void setAlpha(float alpha) {
-        nSetAlpha(mNativeDisplayList, alpha);
+        nSetAlpha(mNativeRenderNode, alpha);
     }
 
     /**
@@ -430,7 +440,7 @@
      * @see #setAlpha(float)
      */
     public float getAlpha() {
-        return nGetAlpha(mNativeDisplayList);
+        return nGetAlpha(mNativeRenderNode);
     }
 
     /**
@@ -445,7 +455,7 @@
      * @see #hasOverlappingRendering()
      */
     public void setHasOverlappingRendering(boolean hasOverlappingRendering) {
-        nSetHasOverlappingRendering(mNativeDisplayList, hasOverlappingRendering);
+        nSetHasOverlappingRendering(mNativeRenderNode, hasOverlappingRendering);
     }
 
     /**
@@ -457,7 +467,15 @@
      */
     public boolean hasOverlappingRendering() {
         //noinspection SimplifiableIfStatement
-        return nHasOverlappingRendering(mNativeDisplayList);
+        return nHasOverlappingRendering(mNativeRenderNode);
+    }
+
+    public void setElevation(float lift) {
+        nSetElevation(mNativeRenderNode, lift);
+    }
+
+    public float getElevation() {
+        return nGetElevation(mNativeRenderNode);
     }
 
     /**
@@ -469,7 +487,7 @@
      * @see #getTranslationX()
      */
     public void setTranslationX(float translationX) {
-        nSetTranslationX(mNativeDisplayList, translationX);
+        nSetTranslationX(mNativeRenderNode, translationX);
     }
 
     /**
@@ -478,7 +496,7 @@
      * @see #setTranslationX(float)
      */
     public float getTranslationX() {
-        return nGetTranslationX(mNativeDisplayList);
+        return nGetTranslationX(mNativeRenderNode);
     }
 
     /**
@@ -490,7 +508,7 @@
      * @see #getTranslationY()
      */
     public void setTranslationY(float translationY) {
-        nSetTranslationY(mNativeDisplayList, translationY);
+        nSetTranslationY(mNativeRenderNode, translationY);
     }
 
     /**
@@ -499,7 +517,7 @@
      * @see #setTranslationY(float)
      */
     public float getTranslationY() {
-        return nGetTranslationY(mNativeDisplayList);
+        return nGetTranslationY(mNativeRenderNode);
     }
 
     /**
@@ -509,7 +527,7 @@
      * @see #getTranslationZ()
      */
     public void setTranslationZ(float translationZ) {
-        nSetTranslationZ(mNativeDisplayList, translationZ);
+        nSetTranslationZ(mNativeRenderNode, translationZ);
     }
 
     /**
@@ -518,7 +536,7 @@
      * @see #setTranslationZ(float)
      */
     public float getTranslationZ() {
-        return nGetTranslationZ(mNativeDisplayList);
+        return nGetTranslationZ(mNativeRenderNode);
     }
 
     /**
@@ -530,7 +548,7 @@
      * @see #getRotation()
      */
     public void setRotation(float rotation) {
-        nSetRotation(mNativeDisplayList, rotation);
+        nSetRotation(mNativeRenderNode, rotation);
     }
 
     /**
@@ -539,7 +557,7 @@
      * @see #setRotation(float)
      */
     public float getRotation() {
-        return nGetRotation(mNativeDisplayList);
+        return nGetRotation(mNativeRenderNode);
     }
 
     /**
@@ -551,7 +569,7 @@
      * @see #getRotationX()
      */
     public void setRotationX(float rotationX) {
-        nSetRotationX(mNativeDisplayList, rotationX);
+        nSetRotationX(mNativeRenderNode, rotationX);
     }
 
     /**
@@ -560,7 +578,7 @@
      * @see #setRotationX(float)
      */
     public float getRotationX() {
-        return nGetRotationX(mNativeDisplayList);
+        return nGetRotationX(mNativeRenderNode);
     }
 
     /**
@@ -572,7 +590,7 @@
      * @see #getRotationY()
      */
     public void setRotationY(float rotationY) {
-        nSetRotationY(mNativeDisplayList, rotationY);
+        nSetRotationY(mNativeRenderNode, rotationY);
     }
 
     /**
@@ -581,7 +599,7 @@
      * @see #setRotationY(float)
      */
     public float getRotationY() {
-        return nGetRotationY(mNativeDisplayList);
+        return nGetRotationY(mNativeRenderNode);
     }
 
     /**
@@ -593,7 +611,7 @@
      * @see #getScaleX()
      */
     public void setScaleX(float scaleX) {
-        nSetScaleX(mNativeDisplayList, scaleX);
+        nSetScaleX(mNativeRenderNode, scaleX);
     }
 
     /**
@@ -602,7 +620,7 @@
      * @see #setScaleX(float)
      */
     public float getScaleX() {
-        return nGetScaleX(mNativeDisplayList);
+        return nGetScaleX(mNativeRenderNode);
     }
 
     /**
@@ -614,7 +632,7 @@
      * @see #getScaleY()
      */
     public void setScaleY(float scaleY) {
-        nSetScaleY(mNativeDisplayList, scaleY);
+        nSetScaleY(mNativeRenderNode, scaleY);
     }
 
     /**
@@ -623,7 +641,7 @@
      * @see #setScaleY(float)
      */
     public float getScaleY() {
-        return nGetScaleY(mNativeDisplayList);
+        return nGetScaleY(mNativeRenderNode);
     }
 
     /**
@@ -635,7 +653,7 @@
      * @see #getPivotX()
      */
     public void setPivotX(float pivotX) {
-        nSetPivotX(mNativeDisplayList, pivotX);
+        nSetPivotX(mNativeRenderNode, pivotX);
     }
 
     /**
@@ -644,7 +662,7 @@
      * @see #setPivotX(float)
      */
     public float getPivotX() {
-        return nGetPivotX(mNativeDisplayList);
+        return nGetPivotX(mNativeRenderNode);
     }
 
     /**
@@ -656,7 +674,7 @@
      * @see #getPivotY()
      */
     public void setPivotY(float pivotY) {
-        nSetPivotY(mNativeDisplayList, pivotY);
+        nSetPivotY(mNativeRenderNode, pivotY);
     }
 
     /**
@@ -665,11 +683,11 @@
      * @see #setPivotY(float)
      */
     public float getPivotY() {
-        return nGetPivotY(mNativeDisplayList);
+        return nGetPivotY(mNativeRenderNode);
     }
 
     public boolean isPivotExplicitlySet() {
-        return nIsPivotExplicitlySet(mNativeDisplayList);
+        return nIsPivotExplicitlySet(mNativeRenderNode);
     }
 
     /**
@@ -683,7 +701,7 @@
      * @see #getCameraDistance()
      */
     public void setCameraDistance(float distance) {
-        nSetCameraDistance(mNativeDisplayList, distance);
+        nSetCameraDistance(mNativeRenderNode, distance);
     }
 
     /**
@@ -692,7 +710,7 @@
      * @see #setCameraDistance(float)
      */
     public float getCameraDistance() {
-        return nGetCameraDistance(mNativeDisplayList);
+        return nGetCameraDistance(mNativeRenderNode);
     }
 
     /**
@@ -704,7 +722,7 @@
      * @see #getLeft()
      */
     public void setLeft(int left) {
-        nSetLeft(mNativeDisplayList, left);
+        nSetLeft(mNativeRenderNode, left);
     }
 
     /**
@@ -713,7 +731,7 @@
      * @see #setLeft(int)
      */
     public float getLeft() {
-        return nGetLeft(mNativeDisplayList);
+        return nGetLeft(mNativeRenderNode);
     }
 
     /**
@@ -725,7 +743,7 @@
      * @see #getTop()
      */
     public void setTop(int top) {
-        nSetTop(mNativeDisplayList, top);
+        nSetTop(mNativeRenderNode, top);
     }
 
     /**
@@ -734,7 +752,7 @@
      * @see #setTop(int)
      */
     public float getTop() {
-        return nGetTop(mNativeDisplayList);
+        return nGetTop(mNativeRenderNode);
     }
 
     /**
@@ -746,7 +764,7 @@
      * @see #getRight()
      */
     public void setRight(int right) {
-        nSetRight(mNativeDisplayList, right);
+        nSetRight(mNativeRenderNode, right);
     }
 
     /**
@@ -755,7 +773,7 @@
      * @see #setRight(int)
      */
     public float getRight() {
-        return nGetRight(mNativeDisplayList);
+        return nGetRight(mNativeRenderNode);
     }
 
     /**
@@ -767,7 +785,7 @@
      * @see #getBottom()
      */
     public void setBottom(int bottom) {
-        nSetBottom(mNativeDisplayList, bottom);
+        nSetBottom(mNativeRenderNode, bottom);
     }
 
     /**
@@ -776,7 +794,7 @@
      * @see #setBottom(int)
      */
     public float getBottom() {
-        return nGetBottom(mNativeDisplayList);
+        return nGetBottom(mNativeRenderNode);
     }
 
     /**
@@ -793,7 +811,7 @@
      * @see View#setBottom(int)
      */
     public void setLeftTopRightBottom(int left, int top, int right, int bottom) {
-        nSetLeftTopRightBottom(mNativeDisplayList, left, top, right, bottom);
+        nSetLeftTopRightBottom(mNativeRenderNode, left, top, right, bottom);
     }
 
     /**
@@ -805,7 +823,7 @@
      * @see View#offsetLeftAndRight(int)
      */
     public void offsetLeftAndRight(float offset) {
-        nOffsetLeftAndRight(mNativeDisplayList, offset);
+        nOffsetLeftAndRight(mNativeRenderNode, offset);
     }
 
     /**
@@ -817,7 +835,7 @@
      * @see View#offsetTopAndBottom(int)
      */
     public void offsetTopAndBottom(float offset) {
-        nOffsetTopAndBottom(mNativeDisplayList, offset);
+        nOffsetTopAndBottom(mNativeRenderNode, offset);
     }
 
     /**
@@ -827,80 +845,106 @@
      * @hide
      */
     public void output() {
-        nOutput(mNativeDisplayList);
+        nOutput(mNativeRenderNode);
+    }
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Animations
+    ///////////////////////////////////////////////////////////////////////////
+
+    public void addAnimator(RenderNodeAnimator animator) {
+        if (mActiveAnimators == null) {
+            mActiveAnimators = new ArrayList<RenderNodeAnimator>();
+        }
+        mActiveAnimators.add(animator);
+        nAddAnimator(mNativeRenderNode, animator.getNativeAnimator());
+    }
+
+    public void removeAnimator(RenderNodeAnimator animator) {
+        nRemoveAnimator(mNativeRenderNode, animator.getNativeAnimator());
+        mActiveAnimators.remove(animator);
     }
 
     ///////////////////////////////////////////////////////////////////////////
     // Native methods
     ///////////////////////////////////////////////////////////////////////////
 
-    private static native long nCreate();
-    private static native void nDestroyDisplayList(long displayList);
-    private static native void nSetDisplayListName(long displayList, String name);
+    private static native long nCreate(String name);
+    private static native void nDestroyRenderNode(long renderNode);
+    private static native void nSetDisplayListData(long renderNode, long newData);
 
     // Matrix
 
-    private static native void nGetTransformMatrix(long displayList, long nativeMatrix);
-    private static native void nGetInverseTransformMatrix(long displayList, long nativeMatrix);
-    private static native boolean nHasIdentityMatrix(long displayList);
+    private static native void nGetTransformMatrix(long renderNode, long nativeMatrix);
+    private static native void nGetInverseTransformMatrix(long renderNode, long nativeMatrix);
+    private static native boolean nHasIdentityMatrix(long renderNode);
 
     // Properties
 
-    private static native void nOffsetTopAndBottom(long displayList, float offset);
-    private static native void nOffsetLeftAndRight(long displayList, float offset);
-    private static native void nSetLeftTopRightBottom(long displayList, int left, int top,
+    private static native void nOffsetTopAndBottom(long renderNode, float offset);
+    private static native void nOffsetLeftAndRight(long renderNode, float offset);
+    private static native void nSetLeftTopRightBottom(long renderNode, int left, int top,
             int right, int bottom);
-    private static native void nSetBottom(long displayList, int bottom);
-    private static native void nSetRight(long displayList, int right);
-    private static native void nSetTop(long displayList, int top);
-    private static native void nSetLeft(long displayList, int left);
-    private static native void nSetCameraDistance(long displayList, float distance);
-    private static native void nSetPivotY(long displayList, float pivotY);
-    private static native void nSetPivotX(long displayList, float pivotX);
-    private static native void nSetCaching(long displayList, boolean caching);
-    private static native void nSetClipToBounds(long displayList, boolean clipToBounds);
-    private static native void nSetProjectBackwards(long displayList, boolean shouldProject);
-    private static native void nSetProjectionReceiver(long displayList, boolean shouldRecieve);
-    private static native void nSetOutlineRoundRect(long displayList, int left, int top,
+    private static native void nSetBottom(long renderNode, int bottom);
+    private static native void nSetRight(long renderNode, int right);
+    private static native void nSetTop(long renderNode, int top);
+    private static native void nSetLeft(long renderNode, int left);
+    private static native void nSetCameraDistance(long renderNode, float distance);
+    private static native void nSetPivotY(long renderNode, float pivotY);
+    private static native void nSetPivotX(long renderNode, float pivotX);
+    private static native void nSetCaching(long renderNode, boolean caching);
+    private static native void nSetClipToBounds(long renderNode, boolean clipToBounds);
+    private static native void nSetProjectBackwards(long renderNode, boolean shouldProject);
+    private static native void nSetProjectionReceiver(long renderNode, boolean shouldRecieve);
+    private static native void nSetOutlineRoundRect(long renderNode, int left, int top,
             int right, int bottom, float radius);
-    private static native void nSetOutlineConvexPath(long displayList, long nativePath);
-    private static native void nSetOutlineEmpty(long displayList);
-    private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
-    private static native void nSetRevealClip(long displayList,
+    private static native void nSetOutlineConvexPath(long renderNode, long nativePath);
+    private static native void nSetOutlineEmpty(long renderNode);
+    private static native void nSetClipToOutline(long renderNode, boolean clipToOutline);
+    private static native void nSetRevealClip(long renderNode,
             boolean shouldClip, boolean inverseClip, float x, float y, float radius);
-    private static native void nSetAlpha(long displayList, float alpha);
-    private static native void nSetHasOverlappingRendering(long displayList,
+    private static native void nSetAlpha(long renderNode, float alpha);
+    private static native void nSetHasOverlappingRendering(long renderNode,
             boolean hasOverlappingRendering);
-    private static native void nSetTranslationX(long displayList, float translationX);
-    private static native void nSetTranslationY(long displayList, float translationY);
-    private static native void nSetTranslationZ(long displayList, float translationZ);
-    private static native void nSetRotation(long displayList, float rotation);
-    private static native void nSetRotationX(long displayList, float rotationX);
-    private static native void nSetRotationY(long displayList, float rotationY);
-    private static native void nSetScaleX(long displayList, float scaleX);
-    private static native void nSetScaleY(long displayList, float scaleY);
-    private static native void nSetStaticMatrix(long displayList, long nativeMatrix);
-    private static native void nSetAnimationMatrix(long displayList, long animationMatrix);
+    private static native void nSetElevation(long renderNode, float lift);
+    private static native void nSetTranslationX(long renderNode, float translationX);
+    private static native void nSetTranslationY(long renderNode, float translationY);
+    private static native void nSetTranslationZ(long renderNode, float translationZ);
+    private static native void nSetRotation(long renderNode, float rotation);
+    private static native void nSetRotationX(long renderNode, float rotationX);
+    private static native void nSetRotationY(long renderNode, float rotationY);
+    private static native void nSetScaleX(long renderNode, float scaleX);
+    private static native void nSetScaleY(long renderNode, float scaleY);
+    private static native void nSetStaticMatrix(long renderNode, long nativeMatrix);
+    private static native void nSetAnimationMatrix(long renderNode, long animationMatrix);
 
-    private static native boolean nHasOverlappingRendering(long displayList);
-    private static native float nGetAlpha(long displayList);
-    private static native float nGetLeft(long displayList);
-    private static native float nGetTop(long displayList);
-    private static native float nGetRight(long displayList);
-    private static native float nGetBottom(long displayList);
-    private static native float nGetCameraDistance(long displayList);
-    private static native float nGetScaleX(long displayList);
-    private static native float nGetScaleY(long displayList);
-    private static native float nGetTranslationX(long displayList);
-    private static native float nGetTranslationY(long displayList);
-    private static native float nGetTranslationZ(long displayList);
-    private static native float nGetRotation(long displayList);
-    private static native float nGetRotationX(long displayList);
-    private static native float nGetRotationY(long displayList);
-    private static native boolean nIsPivotExplicitlySet(long displayList);
-    private static native float nGetPivotX(long displayList);
-    private static native float nGetPivotY(long displayList);
-    private static native void nOutput(long displayList);
+    private static native boolean nHasOverlappingRendering(long renderNode);
+    private static native float nGetAlpha(long renderNode);
+    private static native float nGetLeft(long renderNode);
+    private static native float nGetTop(long renderNode);
+    private static native float nGetRight(long renderNode);
+    private static native float nGetBottom(long renderNode);
+    private static native float nGetCameraDistance(long renderNode);
+    private static native float nGetScaleX(long renderNode);
+    private static native float nGetScaleY(long renderNode);
+    private static native float nGetElevation(long renderNode);
+    private static native float nGetTranslationX(long renderNode);
+    private static native float nGetTranslationY(long renderNode);
+    private static native float nGetTranslationZ(long renderNode);
+    private static native float nGetRotation(long renderNode);
+    private static native float nGetRotationX(long renderNode);
+    private static native float nGetRotationY(long renderNode);
+    private static native boolean nIsPivotExplicitlySet(long renderNode);
+    private static native float nGetPivotX(long renderNode);
+    private static native float nGetPivotY(long renderNode);
+    private static native void nOutput(long renderNode);
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Animations
+    ///////////////////////////////////////////////////////////////////////////
+
+    private static native void nAddAnimator(long renderNode, long animatorPtr);
+    private static native void nRemoveAnimator(long renderNode, long animatorPtr);
 
     ///////////////////////////////////////////////////////////////////////////
     // Finalization
@@ -909,7 +953,7 @@
     @Override
     protected void finalize() throws Throwable {
         try {
-            nDestroyDisplayList(mNativeDisplayList);
+            nDestroyRenderNode(mNativeRenderNode);
         } finally {
             super.finalize();
         }
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
new file mode 100644
index 0000000..b70ae3d
--- /dev/null
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.util.SparseIntArray;
+
+import java.lang.ref.WeakReference;
+
+/**
+ * @hide
+ */
+public final class RenderNodeAnimator {
+
+    // Keep in sync with enum RenderProperty in Animator.h
+    private static final int TRANSLATION_X = 0;
+    private static final int TRANSLATION_Y = 1;
+    private static final int TRANSLATION_Z = 2;
+    private static final int SCALE_X = 3;
+    private static final int SCALE_Y = 4;
+    private static final int ROTATION = 5;
+    private static final int ROTATION_X = 6;
+    private static final int ROTATION_Y = 7;
+    private static final int X = 8;
+    private static final int Y = 9;
+    private static final int Z = 10;
+    private static final int ALPHA = 11;
+
+    // ViewPropertyAnimator uses a mask for its values, we need to remap them
+    // to the enum values here. RenderPropertyAnimator can't use the mask values
+    // directly as internally it uses a lookup table so it needs the values to
+    // be sequential starting from 0
+    private static final SparseIntArray sViewPropertyAnimatorMap = new SparseIntArray(15) {{
+        put(ViewPropertyAnimator.TRANSLATION_X, TRANSLATION_X);
+        put(ViewPropertyAnimator.TRANSLATION_Y, TRANSLATION_Y);
+        put(ViewPropertyAnimator.TRANSLATION_Z, TRANSLATION_Z);
+        put(ViewPropertyAnimator.SCALE_X, SCALE_X);
+        put(ViewPropertyAnimator.SCALE_Y, SCALE_Y);
+        put(ViewPropertyAnimator.ROTATION, ROTATION);
+        put(ViewPropertyAnimator.ROTATION_X, ROTATION_X);
+        put(ViewPropertyAnimator.ROTATION_Y, ROTATION_Y);
+        put(ViewPropertyAnimator.X, X);
+        put(ViewPropertyAnimator.Y, Y);
+        put(ViewPropertyAnimator.Z, Z);
+        put(ViewPropertyAnimator.ALPHA, ALPHA);
+    }};
+
+    // Keep in sync DeltaValueType in Animator.h
+    private static final int DELTA_TYPE_ABSOLUTE = 0;
+    private static final int DELTA_TYPE_DELTA = 1;
+
+    private RenderNode mTarget;
+    private long mNativePtr;
+
+    public int mapViewPropertyToRenderProperty(int viewProperty) {
+        return sViewPropertyAnimatorMap.get(viewProperty);
+    }
+
+    public RenderNodeAnimator(int property, int deltaType, float deltaValue) {
+        mNativePtr = nCreateAnimator(new WeakReference<RenderNodeAnimator>(this),
+                property, deltaType, deltaValue);
+    }
+
+    public void start(View target) {
+        mTarget = target.mRenderNode;
+        mTarget.addAnimator(this);
+        // Kick off a frame to start the process
+        target.invalidateViewProperty(true, false);
+    }
+
+    public void cancel() {
+        mTarget.removeAnimator(this);
+    }
+
+    public void setDuration(int duration) {
+        nSetDuration(mNativePtr, duration);
+    }
+
+    long getNativeAnimator() {
+        return mNativePtr;
+    }
+
+    private void onFinished() {
+        mTarget.removeAnimator(this);
+    }
+
+    // Called by native
+    private static void callOnFinished(WeakReference<RenderNodeAnimator> weakThis) {
+        RenderNodeAnimator animator = weakThis.get();
+        if (animator != null) {
+            animator.onFinished();
+        }
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            nUnref(mNativePtr);
+            mNativePtr = 0;
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static native long nCreateAnimator(WeakReference<RenderNodeAnimator> weakThis,
+            int property, int deltaValueType, float deltaValue);
+    private static native void nSetDuration(long nativePtr, int duration);
+    private static native void nUnref(long nativePtr);
+}
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index 5a8d2c8..2d55a01 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -20,7 +20,6 @@
 import android.graphics.Bitmap;
 import android.graphics.Rect;
 import android.graphics.Region;
-import android.view.Surface;
 import android.os.IBinder;
 import android.util.Log;
 import android.view.Surface.OutOfResourcesException;
@@ -59,6 +58,11 @@
     private static native void nativeSetWindowCrop(long nativeObject, int l, int t, int r, int b);
     private static native void nativeSetLayerStack(long nativeObject, int layerStack);
 
+    private static native boolean nativeClearContentFrameStats(long nativeObject);
+    private static native boolean nativeGetContentFrameStats(long nativeObject, WindowContentFrameStats outStats);
+    private static native boolean nativeClearAnimationFrameStats();
+    private static native boolean nativeGetAnimationFrameStats(WindowAnimationFrameStats outStats);
+
     private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
     private static native IBinder nativeCreateDisplay(String name, boolean secure);
     private static native void nativeDestroyDisplay(IBinder displayToken);
@@ -357,6 +361,24 @@
         nativeSetTransparentRegionHint(mNativeObject, region);
     }
 
+    public boolean clearContentFrameStats() {
+        checkNotReleased();
+        return nativeClearContentFrameStats(mNativeObject);
+    }
+
+    public boolean getContentFrameStats(WindowContentFrameStats outStats) {
+        checkNotReleased();
+        return nativeGetContentFrameStats(mNativeObject, outStats);
+    }
+
+    public static boolean clearAnimationFrameStats() {
+        return nativeClearAnimationFrameStats();
+    }
+
+    public static boolean getAnimationFrameStats(WindowAnimationFrameStats outStats) {
+        return nativeGetAnimationFrameStats(outStats);
+    }
+
     /**
      * Sets an alpha value for the entire Surface.  This value is combined with the
      * per-pixel alpha.  It may be used with opaque Surfaces.
@@ -542,7 +564,6 @@
         return nativeGetBuiltInDisplay(builtInDisplayId);
     }
 
-
     /**
      * Copy the current screen contents into the provided {@link Surface}
      *
@@ -592,7 +613,6 @@
         screenshot(display, consumer, 0, 0, 0, 0, true, false);
     }
 
-
     /**
      * Copy the current screen contents into a bitmap and return it.
      *
@@ -626,8 +646,8 @@
     }
 
     /**
-     * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
-     * Surfaces in the screenshot.
+     * Like {@link SurfaceControl#screenshot(int, int, int, int, boolean)} but
+     * includes all Surfaces in the screenshot.
      *
      * @param width The desired width of the returned bitmap; the raw
      * screen will be scaled down to this size.
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 23123dd..4a2cc1a 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -422,7 +422,8 @@
         mWindowType = type;
     }
 
-    private void updateWindow(boolean force, boolean redrawNeeded) {
+    /** @hide */
+    protected void updateWindow(boolean force, boolean redrawNeeded) {
         if (!mHaveFrame) {
             return;
         }
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java
index 2e0f509..eaec8ab 100644
--- a/core/java/android/view/ThreadedRenderer.java
+++ b/core/java/android/view/ThreadedRenderer.java
@@ -50,21 +50,25 @@
 public class ThreadedRenderer extends HardwareRenderer {
     private static final String LOGTAG = "ThreadedRenderer";
 
-    private static final Rect NULL_RECT = new Rect(-1, -1, -1, -1);
+    private static final Rect NULL_RECT = new Rect();
 
     private int mWidth, mHeight;
     private long mNativeProxy;
     private boolean mInitialized = false;
+    private RenderNode mRootNode;
 
     ThreadedRenderer(boolean translucent) {
-        mNativeProxy = nCreateProxy(translucent);
+        long rootNodePtr = nCreateRootRenderNode();
+        mRootNode = RenderNode.adopt(rootNodePtr);
+        mRootNode.setClipToBounds(false);
+        mNativeProxy = nCreateProxy(translucent, rootNodePtr);
     }
 
     @Override
     void destroy(boolean full) {
         mInitialized = false;
         updateEnabledState(null);
-        nDestroyCanvas(mNativeProxy);
+        nDestroyCanvasAndSurface(mNativeProxy);
     }
 
     private void updateEnabledState(Surface surface) {
@@ -127,6 +131,7 @@
     void setup(int width, int height) {
         mWidth = width;
         mHeight = height;
+        mRootNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
         nSetup(mNativeProxy, width, height);
     }
 
@@ -165,15 +170,7 @@
     public void repeatLastDraw() {
     }
 
-    @Override
-    void setDisplayListData(long displayList, long newData) {
-        nSetDisplayListData(mNativeProxy, displayList, newData);
-    }
-
-    @Override
-    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
-        attachInfo.mIgnoreDirtyState = true;
-        attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+    private void updateRootDisplayList(View view, HardwareDrawCallbacks callbacks) {
         view.mPrivateFlags |= View.PFLAG_DRAWN;
 
         view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED)
@@ -181,30 +178,46 @@
         view.mPrivateFlags &= ~View.PFLAG_INVALIDATED;
 
         Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList");
-        RenderNode displayList = view.getDisplayList();
-        Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        HardwareCanvas canvas = mRootNode.start(mWidth, mHeight);
+        try {
+            callbacks.onHardwarePostDraw(canvas);
+            canvas.drawDisplayList(view.getDisplayList());
+            callbacks.onHardwarePostDraw(canvas);
+        } finally {
+            mRootNode.end(canvas);
+            Trace.traceEnd(Trace.TRACE_TAG_VIEW);
+        }
 
         view.mRecreateDisplayList = false;
+    }
+
+    @Override
+    void draw(View view, AttachInfo attachInfo, HardwareDrawCallbacks callbacks, Rect dirty) {
+        attachInfo.mIgnoreDirtyState = true;
+        attachInfo.mDrawingTime = SystemClock.uptimeMillis();
+
+        updateRootDisplayList(view, callbacks);
+
+        attachInfo.mIgnoreDirtyState = false;
 
         if (dirty == null) {
             dirty = NULL_RECT;
         }
-        nDrawDisplayList(mNativeProxy, displayList.getNativeDisplayList(),
-                dirty.left, dirty.top, dirty.right, dirty.bottom);
+        nSyncAndDrawFrame(mNativeProxy, dirty.left, dirty.top, dirty.right, dirty.bottom);
     }
 
     @Override
     void detachFunctor(long functor) {
-        nDetachFunctor(mNativeProxy, functor);
+        // no-op, we never attach functors to need to detach them
     }
 
     @Override
     void attachFunctor(AttachInfo attachInfo, long functor) {
-        nAttachFunctor(mNativeProxy, functor);
+        invokeFunctor(functor, true);
     }
 
     @Override
-    public void invokeFunctor(long functor, boolean waitForCompletion) {
+    void invokeFunctor(long functor, boolean waitForCompletion) {
         nInvokeFunctor(mNativeProxy, functor, waitForCompletion);
     }
 
@@ -280,7 +293,8 @@
     /** @hide */
     public static native void postToRenderThread(Runnable runnable);
 
-    private static native long nCreateProxy(boolean translucent);
+    private static native long nCreateRootRenderNode();
+    private static native long nCreateProxy(boolean translucent, long rootRenderNode);
     private static native void nDeleteProxy(long nativeProxy);
 
     private static native boolean nInitialize(long nativeProxy, Surface window);
@@ -289,13 +303,11 @@
     private static native void nSetup(long nativeProxy, int width, int height);
     private static native void nSetDisplayListData(long nativeProxy, long displayList,
             long newData);
-    private static native void nDrawDisplayList(long nativeProxy, long displayList,
+    private static native void nSyncAndDrawFrame(long nativeProxy,
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
     private static native void nRunWithGlContext(long nativeProxy, Runnable runnable);
-    private static native void nDestroyCanvas(long nativeProxy);
+    private static native void nDestroyCanvasAndSurface(long nativeProxy);
 
-    private static native void nAttachFunctor(long nativeProxy, long functor);
-    private static native void nDetachFunctor(long nativeProxy, long functor);
     private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion);
 
     private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 6c414f6..85e3b3d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -27,7 +27,6 @@
 import android.content.res.Resources;
 import android.content.res.TypedArray;
 import android.graphics.Bitmap;
-import android.graphics.Camera;
 import android.graphics.Canvas;
 import android.graphics.Insets;
 import android.graphics.Interpolator;
@@ -720,6 +719,11 @@
     private static boolean sIgnoreMeasureCache = false;
 
     /**
+     * Ignore the clipBounds of this view for the children.
+     */
+    static boolean sIgnoreClipBoundsForChildren = false;
+
+    /**
      * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
      * calling setFlags.
      */
@@ -2371,24 +2375,26 @@
     static final int PFLAG3_CALLED_SUPER = 0x10;
 
     /**
-     * Flag indicating that an view will be clipped to its outline.
-     */
-    static final int PFLAG3_CLIP_TO_OUTLINE = 0x20;
-
-    /**
      * Flag indicating that a view's outline has been specifically defined.
      */
-    static final int PFLAG3_OUTLINE_DEFINED = 0x40;
+    static final int PFLAG3_OUTLINE_DEFINED = 0x20;
 
     /**
      * Flag indicating that we're in the process of applying window insets.
      */
-    static final int PFLAG3_APPLYING_INSETS = 0x80;
+    static final int PFLAG3_APPLYING_INSETS = 0x40;
 
     /**
      * Flag indicating that we're in the process of fitting system windows using the old method.
      */
-    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x100;
+    static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80;
+
+    /**
+     * Flag indicating that nested scrolling is enabled for this view.
+     * The view will optionally cooperate with views up its parent chain to allow for
+     * integrated nested scrolling along the same axis.
+     */
+    static final int PFLAG3_NESTED_SCROLLING_ENABLED = 0x200;
 
     /* End of masks for mPrivateFlags3 */
 
@@ -2842,6 +2848,21 @@
     public static final int SCREEN_STATE_ON = 0x1;
 
     /**
+     * Indicates no axis of view scrolling.
+     */
+    public static final int SCROLL_AXIS_NONE = 0;
+
+    /**
+     * Indicates scrolling along the horizontal axis.
+     */
+    public static final int SCROLL_AXIS_HORIZONTAL = 1 << 0;
+
+    /**
+     * Indicates scrolling along the vertical axis.
+     */
+    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
+
+    /**
      * Controls the over-scroll mode for this view.
      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
@@ -2963,17 +2984,11 @@
     /**
      * Current clip bounds. to which all drawing of this view are constrained.
      */
-    private Rect mClipBounds = null;
+    Rect mClipBounds = null;
 
     private boolean mLastIsOpaque;
 
     /**
-     * Convenience value to check for float values that are close enough to zero to be considered
-     * zero.
-     */
-    private static final float NONZERO_EPSILON = .001f;
-
-    /**
      * The distance in pixels from the left edge of this view's parent
      * to the left edge of this view.
      * {@hide}
@@ -3238,9 +3253,7 @@
 
     /**
      * Stores the outline of the view, passed down to the DisplayList level for
-     * defining shadow shape and clipping.
-     *
-     * TODO: once RenderNode is long-lived, remove this and rely on native copy.
+     * defining shadow shape.
      */
     private Outline mOutline;
 
@@ -3474,6 +3487,14 @@
     ViewOverlay mOverlay;
 
     /**
+     * The currently active parent view for receiving delegated nested scrolling events.
+     * This is set by {@link #startNestedScroll(int)} during a touch interaction and cleared
+     * by {@link #stopNestedScroll()} at the same point where we clear
+     * requestDisallowInterceptTouchEvent.
+     */
+    private ViewParent mNestedScrollingParent;
+
+    /**
      * Consistency verifier for debugging purposes.
      * @hide
      */
@@ -3483,6 +3504,8 @@
 
     private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
 
+    private int[] mTempNestedScrollConsumed;
+
     /**
      * Simple constructor to use when creating a view from code.
      *
@@ -3517,6 +3540,9 @@
             // of whether a layout was requested on that View.
             sIgnoreMeasureCache = targetSdkVersion < KITKAT;
 
+            // Older apps may need this to ignore the clip bounds
+            sIgnoreClipBoundsForChildren = targetSdkVersion < L;
+
             sCompatibilityDone = true;
         }
     }
@@ -3623,6 +3649,7 @@
         float tx = 0;
         float ty = 0;
         float tz = 0;
+        float elevation = 0;
         float rotation = 0;
         float rotationX = 0;
         float rotationY = 0;
@@ -3706,6 +3733,10 @@
                     tz = a.getDimensionPixelOffset(attr, 0);
                     transformSet = true;
                     break;
+                case com.android.internal.R.styleable.View_elevation:
+                    elevation = a.getDimensionPixelOffset(attr, 0);
+                    transformSet = true;
+                    break;
                 case com.android.internal.R.styleable.View_rotation:
                     rotation = a.getFloat(attr, 0);
                     transformSet = true;
@@ -3961,6 +3992,9 @@
                 case R.styleable.View_sharedElementName:
                     setSharedElementName(a.getString(attr));
                     break;
+                case R.styleable.View_nestedScrollingEnabled:
+                    setNestedScrollingEnabled(a.getBoolean(attr, false));
+                    break;
             }
         }
 
@@ -4051,6 +4085,7 @@
             setTranslationX(tx);
             setTranslationY(ty);
             setTranslationZ(tz);
+            setElevation(elevation);
             setRotation(rotation);
             setRotationX(rotationX);
             setRotationY(rotationY);
@@ -4735,13 +4770,13 @@
     private void manageFocusHotspot(boolean focused, View v) {
         if (mBackground != null && mBackground.supportsHotspots()) {
             final Rect r = new Rect();
-            if (v != null) {
+            if (!focused && v != null) {
                 v.getBoundsOnScreen(r);
                 final int[] location = new int[2];
                 getLocationOnScreen(location);
                 r.offset(-location[0], -location[1]);
             } else {
-                r.set(mLeft, mTop, mRight, mBottom);
+                r.set(0, 0, mRight - mLeft, mBottom - mTop);
             }
 
             final float x = r.exactCenterX();
@@ -4856,16 +4891,13 @@
         if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
             mPrivateFlags &= ~PFLAG_FOCUSED;
 
-            if (hasFocus()) {
-                manageFocusHotspot(false, focused);
-            }
-
             if (propagate && mParent != null) {
                 mParent.clearChildFocus(this);
             }
 
             onFocusChanged(false, 0, null);
 
+            manageFocusHotspot(false, focused);
             refreshDrawableState();
 
             if (propagate && (!refocus || !rootViewRequestFocus())) {
@@ -7977,27 +8009,46 @@
      * @return True if the event was handled by the view, false otherwise.
      */
     public boolean dispatchTouchEvent(MotionEvent event) {
+        boolean result = false;
+
         if (mInputEventConsistencyVerifier != null) {
             mInputEventConsistencyVerifier.onTouchEvent(event, 0);
         }
 
+        final int actionMasked = event.getActionMasked();
+        if (actionMasked == MotionEvent.ACTION_DOWN) {
+            // Defensive cleanup for new gesture
+            stopNestedScroll();
+        }
+
         if (onFilterTouchEventForSecurity(event)) {
             //noinspection SimplifiableIfStatement
             ListenerInfo li = mListenerInfo;
-            if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
+            if (li != null && li.mOnTouchListener != null
+                    && (mViewFlags & ENABLED_MASK) == ENABLED
                     && li.mOnTouchListener.onTouch(this, event)) {
-                return true;
+                result = true;
             }
 
-            if (onTouchEvent(event)) {
-                return true;
+            if (!result && onTouchEvent(event)) {
+                result = true;
             }
         }
 
-        if (mInputEventConsistencyVerifier != null) {
+        if (!result && mInputEventConsistencyVerifier != null) {
             mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
         }
-        return false;
+
+        // Clean up after nested scrolls if this is the end of a gesture;
+        // also cancel it if we tried an ACTION_DOWN but we didn't want the rest
+        // of the gesture.
+        if (actionMasked == MotionEvent.ACTION_UP ||
+                actionMasked == MotionEvent.ACTION_CANCEL ||
+                (actionMasked == MotionEvent.ACTION_DOWN && !result)) {
+            stopNestedScroll();
+        }
+
+        return result;
     }
 
     /**
@@ -8790,11 +8841,6 @@
                             && !pointInView(event.getX(), event.getY()))) {
                 mSendingHoverAccessibilityEvents = false;
                 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
-                // If the window does not have input focus we take away accessibility
-                // focus as soon as the user stop hovering over the view.
-                if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
-                    getViewRootImpl().setAccessibilityFocus(null, null);
-                }
             }
         }
 
@@ -10395,6 +10441,48 @@
         setTranslationY(y - mTop);
     }
 
+    /**
+     * The visual z position of this view, in pixels. This is equivalent to the
+     * {@link #setTranslationZ(float) translationZ} property plus the current
+     * {@link #getElevation() elevation} property.
+     *
+     * @return The visual z position of this view, in pixels.
+     */
+    @ViewDebug.ExportedProperty(category = "drawing")
+    public float getZ() {
+        return getElevation() + getTranslationZ();
+    }
+
+    /**
+     * Sets the visual z position of this view, in pixels. This is equivalent to setting the
+     * {@link #setTranslationZ(float) translationZ} property to be the difference between
+     * the x value passed in and the current {@link #getElevation() elevation} property.
+     *
+     * @param z The visual z position of this view, in pixels.
+     */
+    public void setZ(float z) {
+        setTranslationZ(z - getElevation());
+    }
+
+    @ViewDebug.ExportedProperty(category = "drawing")
+    public float getElevation() {
+        return mRenderNode.getElevation();
+    }
+
+    /**
+     * Sets the base depth location of this view.
+     *
+     * @attr ref android.R.styleable#View_elevation
+     */
+    public void setElevation(float elevation) {
+        if (elevation != getElevation()) {
+            invalidateViewProperty(true, false);
+            mRenderNode.setElevation(elevation);
+            invalidateViewProperty(false, true);
+
+            invalidateParentIfNeededAndWasQuickRejected();
+        }
+    }
 
     /**
      * The horizontal location of this view relative to its {@link #getLeft() left} position.
@@ -10462,9 +10550,9 @@
     }
 
     /**
-     * The depth location of this view relative to its parent.
+     * The depth location of this view relative to its {@link #getElevation() elevation}.
      *
-     * @return The depth of this view relative to its parent.
+     * @return The depth of this view relative to its elevation.
      */
     @ViewDebug.ExportedProperty(category = "drawing")
     public float getTranslationZ() {
@@ -10472,7 +10560,7 @@
     }
 
     /**
-     * Sets the depth location of this view relative to its parent.
+     * Sets the depth location of this view relative to its {@link #getElevation() elevation}.
      *
      * @attr ref android.R.styleable#View_translationZ
      */
@@ -10525,16 +10613,13 @@
 
     /**
      * Sets the outline of the view, which defines the shape of the shadow it
-     * casts, and can used for clipping.
+     * casts.
      * <p>
      * If the outline is not set or is null, shadows will be cast from the
-     * bounds of the View, and clipToOutline will be ignored.
+     * bounds of the View.
      *
      * @param outline The new outline of the view.
      *         Must be {@link android.graphics.Outline#isValid() valid.}
-     *
-     * @see #getClipToOutline()
-     * @see #setClipToOutline(boolean)
      */
     public void setOutline(@Nullable Outline outline) {
         if (outline != null && !outline.isValid()) {
@@ -10555,39 +10640,27 @@
         mRenderNode.setOutline(mOutline);
     }
 
-    /**
-     * Returns whether the outline of the View will be used for clipping.
-     *
-     * @see #setOutline(Outline)
-     */
-    public final boolean getClipToOutline() {
-        return ((mPrivateFlags3 & PFLAG3_CLIP_TO_OUTLINE) != 0);
-    }
+    // TODO: remove
+    public final boolean getClipToOutline() { return false; }
+    public void setClipToOutline(boolean clipToOutline) {}
 
-    /**
-     * Sets whether the outline of the View will be used for clipping.
-     * <p>
-     * The current implementation of outline clipping uses
-     * {@link Canvas#clipPath(Path) path clipping},
-     * and thus does not support anti-aliasing, and is expensive in terms of
-     * graphics performance. Therefore, it is strongly recommended that this
-     * property only be set temporarily, as in an animation. For the same
-     * reasons, there is no parallel XML attribute for this property.
-     * <p>
-     * If the outline of the view is not set or is empty, no clipping will be
-     * performed.
-     *
-     * @see #setOutline(Outline)
-     */
-    public void setClipToOutline(boolean clipToOutline) {
-        // TODO : Add a fast invalidation here.
-        if (getClipToOutline() != clipToOutline) {
-            if (clipToOutline) {
-                mPrivateFlags3 |= PFLAG3_CLIP_TO_OUTLINE;
+    private void queryOutlineFromBackgroundIfUndefined() {
+        if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) {
+            // Outline not currently defined, query from background
+            if (mOutline == null) {
+                mOutline = new Outline();
             } else {
-                mPrivateFlags3 &= ~PFLAG3_CLIP_TO_OUTLINE;
+                //invalidate outline, to ensure background calculates it
+                mOutline.set(null);
             }
-            mRenderNode.setClipToOutline(clipToOutline);
+            if (mBackground.getOutline(mOutline)) {
+                if (!mOutline.isValid()) {
+                    throw new IllegalStateException("Background drawable failed to build outline");
+                }
+                mRenderNode.setOutline(mOutline);
+            } else {
+                mRenderNode.setOutline(null);
+            }
         }
     }
 
@@ -11160,7 +11233,7 @@
             }
 
             // Damage the entire IsolatedZVolume recieving this view's shadow.
-            if (isHardwareAccelerated() && getTranslationZ() != 0) {
+            if (isHardwareAccelerated() && getZ() != 0) {
                 damageShadowReceiver();
             }
         }
@@ -11236,7 +11309,7 @@
         } else {
             damageInParent();
         }
-        if (isHardwareAccelerated() && invalidateParent && getTranslationZ() != 0) {
+        if (isHardwareAccelerated() && invalidateParent && getZ() != 0) {
             damageShadowReceiver();
         }
     }
@@ -12737,10 +12810,15 @@
         mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
         mPrivateFlags3 &= ~PFLAG3_IS_LAID_OUT;
 
+        if (mBackground != null) {
+            mBackground.clearHotspots();
+        }
+
         removeUnsetPressCallback();
         removeLongPressCallback();
         removePerformClickCallback();
         removeSendViewScrolledAccessibilityEventCallback();
+        stopNestedScroll();
 
         destroyDrawingCache();
         destroyLayer(false);
@@ -13549,11 +13627,10 @@
      * @return A new or reused DisplayList object.
      */
     private void updateDisplayListIfDirty(@NonNull RenderNode renderNode, boolean isLayer) {
-        final HardwareRenderer renderer = getHardwareRenderer();
         if (renderNode == null) {
             throw new IllegalArgumentException("RenderNode must not be null");
         }
-        if (renderer == null || !canHaveDisplayList()) {
+        if (!canHaveDisplayList()) {
             // can't populate RenderNode, don't try
             return;
         }
@@ -13627,21 +13704,13 @@
                     }
                 }
             } finally {
-                renderNode.end(renderer, canvas);
+                renderNode.end(canvas);
                 renderNode.setCaching(caching);
                 if (isLayer) {
                     renderNode.setLeftTopRightBottom(0, 0, width, height);
                 } else {
                     setDisplayListProperties(renderNode);
                 }
-
-                if (renderer != getHardwareRenderer()) {
-                    Log.w(VIEW_LOG_TAG, "View was detached during a draw() call!");
-                    // TODO: Should this be elevated to a crash?
-                    // For now have it behaves the same as it previously did, it
-                    // will result in the DisplayListData being destroyed later
-                    // than it could be but oh well...
-                }
             }
         } else if (!isLayer) {
             mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
@@ -14854,11 +14923,7 @@
         if (mBackgroundSizeChanged) {
             background.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
             mBackgroundSizeChanged = false;
-            if ((mPrivateFlags3 & PFLAG3_OUTLINE_DEFINED) == 0) {
-                // Outline not currently define, query from background
-                mOutline = background.getOutline();
-                mRenderNode.setOutline(mOutline);
-            }
+            queryOutlineFromBackgroundIfUndefined();
         }
 
         // Attempt to use a display list if requested.
@@ -14912,8 +14977,11 @@
         final int width = bounds.width();
         final int height = bounds.height();
         final HardwareCanvas canvas = displayList.start(width, height);
-        drawable.draw(canvas);
-        displayList.end(getHardwareRenderer(), canvas);
+        try {
+            drawable.draw(canvas);
+        } finally {
+            displayList.end(canvas);
+        }
 
         // Set up drawable properties that are view-independent.
         displayList.setLeftTopRightBottom(bounds.left, bounds.top, bounds.right, bounds.bottom);
@@ -15257,7 +15325,7 @@
      * @param drawable the drawable to invalidate
      */
     @Override
-    public void invalidateDrawable(Drawable drawable) {
+    public void invalidateDrawable(@NonNull Drawable drawable) {
         if (verifyDrawable(drawable)) {
             final Rect dirty = drawable.getDirtyBounds();
             final int scrollX = mScrollX;
@@ -15265,6 +15333,10 @@
 
             invalidate(dirty.left + scrollX, dirty.top + scrollY,
                     dirty.right + scrollX, dirty.bottom + scrollY);
+
+            if (drawable == mBackground) {
+                queryOutlineFromBackgroundIfUndefined();
+            }
         }
     }
 
@@ -17148,8 +17220,8 @@
             // If the screen is off assume the animation start time is now instead of
             // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
             // would cause the animation to start when the screen turns back on
-            if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
-                    animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
+            if (mAttachInfo != null && mAttachInfo.mDisplayState == Display.STATE_OFF
+                    && animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
                 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
             }
             animation.reset();
@@ -17913,6 +17985,249 @@
     }
 
     /**
+     * Enable or disable nested scrolling for this view.
+     *
+     * <p>If this property is set to true the view will be permitted to initiate nested
+     * scrolling operations with a compatible parent view in the current hierarchy. If this
+     * view does not implement nested scrolling this will have no effect.</p>
+     *
+     * @param enabled true to enable nested scrolling, false to disable
+     *
+     * @see #isNestedScrollingEnabled()
+     */
+    public void setNestedScrollingEnabled(boolean enabled) {
+        if (enabled) {
+            mPrivateFlags3 |= PFLAG3_NESTED_SCROLLING_ENABLED;
+        } else {
+            mPrivateFlags3 &= ~PFLAG3_NESTED_SCROLLING_ENABLED;
+        }
+    }
+
+    /**
+     * Returns true if nested scrolling is enabled for this view.
+     *
+     * <p>If nested scrolling is enabled and this View class implementation supports it,
+     * this view will act as a nested scrolling child view when applicable, forwarding data
+     * about the scroll operation in progress to a compatible and cooperating nested scrolling
+     * parent.</p>
+     *
+     * @return true if nested scrolling is enabled
+     *
+     * @see #setNestedScrollingEnabled(boolean)
+     */
+    public boolean isNestedScrollingEnabled() {
+        return (mPrivateFlags3 & PFLAG3_NESTED_SCROLLING_ENABLED) ==
+                PFLAG3_NESTED_SCROLLING_ENABLED;
+    }
+
+    /**
+     * Begin a nestable scroll operation along the given axes.
+     *
+     * <p>A view starting a nested scroll promises to abide by the following contract:</p>
+     *
+     * <p>The view will call startNestedScroll upon initiating a scroll operation. In the case
+     * of a touch scroll this corresponds to the initial {@link MotionEvent#ACTION_DOWN}.
+     * In the case of touch scrolling the nested scroll will be terminated automatically in
+     * the same manner as {@link ViewParent#requestDisallowInterceptTouchEvent(boolean)}.
+     * In the event of programmatic scrolling the caller must explicitly call
+     * {@link #stopNestedScroll()} to indicate the end of the nested scroll.</p>
+     *
+     * <p>If <code>startNestedScroll</code> returns true, a cooperative parent was found.
+     * If it returns false the caller may ignore the rest of this contract until the next scroll.
+     * Calling startNestedScroll while a nested scroll is already in progress will return true.</p>
+     *
+     * <p>At each incremental step of the scroll the caller should invoke
+     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll}
+     * once it has calculated the requested scrolling delta. If it returns true the nested scrolling
+     * parent at least partially consumed the scroll and the caller should adjust the amount it
+     * scrolls by.</p>
+     *
+     * <p>After applying the remainder of the scroll delta the caller should invoke
+     * {@link #dispatchNestedScroll(int, int, int, int, int[]) dispatchNestedScroll}, passing
+     * both the delta consumed and the delta unconsumed. A nested scrolling parent may treat
+     * these values differently. See {@link ViewParent#onNestedScroll(View, int, int, int, int)}.
+     * </p>
+     *
+     * @param axes Flags consisting of a combination of {@link #SCROLL_AXIS_HORIZONTAL} and/or
+     *             {@link #SCROLL_AXIS_VERTICAL}.
+     * @return true if a cooperative parent was found and nested scrolling has been enabled for
+     *         the current gesture.
+     *
+     * @see #stopNestedScroll()
+     * @see #dispatchNestedPreScroll(int, int, int[], int[])
+     * @see #dispatchNestedScroll(int, int, int, int, int[])
+     */
+    public boolean startNestedScroll(int axes) {
+        if (hasNestedScrollingParent()) {
+            // Already in progress
+            return true;
+        }
+        if (isNestedScrollingEnabled()) {
+            ViewParent p = getParent();
+            View child = this;
+            while (p != null) {
+                try {
+                    if (p.onStartNestedScroll(child, this, axes)) {
+                        mNestedScrollingParent = p;
+                        p.onNestedScrollAccepted(child, this, axes);
+                        return true;
+                    }
+                } catch (AbstractMethodError e) {
+                    Log.e(VIEW_LOG_TAG, "ViewParent " + p + " does not implement interface " +
+                            "method onStartNestedScroll", e);
+                    // Allow the search upward to continue
+                }
+                if (p instanceof View) {
+                    child = (View) p;
+                }
+                p = p.getParent();
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Stop a nested scroll in progress.
+     *
+     * <p>Calling this method when a nested scroll is not currently in progress is harmless.</p>
+     *
+     * @see #startNestedScroll(int)
+     */
+    public void stopNestedScroll() {
+        if (mNestedScrollingParent != null) {
+            mNestedScrollingParent.onStopNestedScroll(this);
+            mNestedScrollingParent = null;
+        }
+    }
+
+    /**
+     * Returns true if this view has a nested scrolling parent.
+     *
+     * <p>The presence of a nested scrolling parent indicates that this view has initiated
+     * a nested scroll and it was accepted by an ancestor view further up the view hierarchy.</p>
+     *
+     * @return whether this view has a nested scrolling parent
+     */
+    public boolean hasNestedScrollingParent() {
+        return mNestedScrollingParent != null;
+    }
+
+    /**
+     * Dispatch one step of a nested scroll in progress.
+     *
+     * <p>Implementations of views that support nested scrolling should call this to report
+     * info about a scroll in progress to the current nested scrolling parent. If a nested scroll
+     * is not currently in progress or nested scrolling is not
+     * {@link #isNestedScrollingEnabled() enabled} for this view this method does nothing.</p>
+     *
+     * <p>Compatible View implementations should also call
+     * {@link #dispatchNestedPreScroll(int, int, int[], int[]) dispatchNestedPreScroll} before
+     * consuming a component of the scroll event themselves.</p>
+     *
+     * @param dxConsumed Horizontal distance in pixels consumed by this view during this scroll step
+     * @param dyConsumed Vertical distance in pixels consumed by this view during this scroll step
+     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by this view
+     * @param dyUnconsumed Horizontal scroll distance in pixels not consumed by this view
+     * @param offsetInWindow Optional. If not null, on return this will contain the offset
+     *                       in local view coordinates of this view from before this operation
+     *                       to after it completes. View implementations may use this to adjust
+     *                       expected input coordinate tracking.
+     * @return true if the event was dispatched, false if it could not be dispatched.
+     * @see #dispatchNestedPreScroll(int, int, int[], int[])
+     */
+    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow) {
+        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
+            int startX = 0;
+            int startY = 0;
+            if (offsetInWindow != null) {
+                getLocationInWindow(offsetInWindow);
+                startX = offsetInWindow[0];
+                startY = offsetInWindow[1];
+            }
+
+            mNestedScrollingParent.onNestedScroll(this, dxConsumed, dyConsumed,
+                    dxUnconsumed, dyUnconsumed);
+
+            if (offsetInWindow != null) {
+                getLocationInWindow(offsetInWindow);
+                offsetInWindow[0] -= startX;
+                offsetInWindow[1] -= startY;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Dispatch one step of a nested scroll in progress before this view consumes any portion of it.
+     *
+     * <p>Nested pre-scroll events are to nested scroll events what touch intercept is to touch.
+     * <code>dispatchNestedPreScroll</code> offers an opportunity for the parent view in a nested
+     * scrolling operation to consume some or all of the scroll operation before the child view
+     * consumes it.</p>
+     *
+     * @param dx Horizontal scroll distance in pixels
+     * @param dy Vertical scroll distance in pixels
+     * @param consumed Output. If not null, consumed[0] will contain the consumed component of dx
+     *                 and consumed[1] the consumed dy.
+     * @param offsetInWindow Optional. If not null, on return this will contain the offset
+     *                       in local view coordinates of this view from before this operation
+     *                       to after it completes. View implementations may use this to adjust
+     *                       expected input coordinate tracking.
+     * @return true if the parent consumed some or all of the scroll delta
+     * @see #dispatchNestedScroll(int, int, int, int, int[])
+     */
+    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
+        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
+            int startX = 0;
+            int startY = 0;
+            if (offsetInWindow != null) {
+                getLocationInWindow(offsetInWindow);
+                startX = offsetInWindow[0];
+                startY = offsetInWindow[1];
+            }
+
+            if (consumed == null) {
+                if (mTempNestedScrollConsumed == null) {
+                    mTempNestedScrollConsumed = new int[2];
+                }
+                consumed = mTempNestedScrollConsumed;
+            }
+            consumed[0] = 0;
+            consumed[1] = 0;
+            mNestedScrollingParent.onNestedPreScroll(this, dx, dy, consumed);
+
+            if (offsetInWindow != null) {
+                getLocationInWindow(offsetInWindow);
+                offsetInWindow[0] -= startX;
+                offsetInWindow[1] -= startY;
+            }
+            return consumed[0] != 0 || consumed[1] != 0;
+        }
+        return false;
+    }
+
+    /**
+     * Dispatch a fling to a nested scrolling parent.
+     *
+     * <p>If a nested scrolling child view would normally fling but it is at the edge of its
+     * own content it should use this method to delegate the fling to its nested scrolling parent.
+     * The view implementation can use a {@link VelocityTracker} to obtain the velocity values
+     * to pass.</p>
+     *
+     * @param velocityX Horizontal fling velocity in pixels per second
+     * @param velocityY Vertical fling velocity in pixels per second
+     * @return true if the nested scrolling parent consumed the fling
+     */
+    public boolean dispatchNestedFling(float velocityX, float velocityY) {
+        if (isNestedScrollingEnabled() && mNestedScrollingParent != null) {
+            return mNestedScrollingParent.onNestedFling(this, velocityX, velocityY);
+        }
+        return false;
+    }
+
+    /**
      * Gets a scale factor that determines the distance the view should scroll
      * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
      * @return The vertical scroll scale factor.
@@ -18549,6 +18864,22 @@
     };
 
     /**
+     * A Property wrapper around the <code>z</code> functionality handled by the
+     * {@link View#setZ(float)} and {@link View#getZ()} methods.
+     */
+    public static final Property<View, Float> Z = new FloatProperty<View>("z") {
+        @Override
+        public void setValue(View object, float value) {
+            object.setZ(value);
+        }
+
+        @Override
+        public Float get(View object) {
+            return object.getZ();
+        }
+    };
+
+    /**
      * A Property wrapper around the <code>rotation</code> functionality handled by the
      * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
      */
@@ -19128,7 +19459,7 @@
      * A set of information given to a view when it is attached to its parent
      * window.
      */
-    static class AttachInfo {
+    final static class AttachInfo {
         interface Callbacks {
             void playSoundEffect(int effectId);
             boolean performHapticFeedback(int effectId, boolean always);
@@ -19191,7 +19522,14 @@
         boolean mHardwareAccelerationRequested;
         HardwareRenderer mHardwareRenderer;
 
-        boolean mScreenOn;
+        /**
+         * The state of the display to which the window is attached, as reported
+         * by {@link Display#getState()}.  Note that the display state constants
+         * declared by {@link Display} do not exactly line up with the screen state
+         * constants declared by {@link View} (there are more display states than
+         * screen states).
+         */
+        int mDisplayState = Display.STATE_UNKNOWN;
 
         /**
          * Scale factor used by the compatibility mode
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index d2c6302..8865ab4 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -460,6 +460,13 @@
     @ViewDebug.ExportedProperty(category = "layout")
     private int mChildCountWithTransientState = 0;
 
+    /**
+     * Currently registered axes for nested scrolling. Flag set consisting of
+     * {@link #SCROLL_AXIS_HORIZONTAL} {@link #SCROLL_AXIS_VERTICAL} or {@link #SCROLL_AXIS_NONE}
+     * for null.
+     */
+    private int mNestedScrollAxes;
+
     public ViewGroup(Context context) {
         this(context, null);
     }
@@ -2011,6 +2018,7 @@
         clearTouchTargets();
         resetCancelNextUpFlag(this);
         mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
+        mNestedScrollAxes = SCROLL_AXIS_NONE;
     }
 
     /**
@@ -2305,11 +2313,13 @@
 
     /**
      * Changes whether or not this ViewGroup should be treated as a single entity during
-     * ActivityTransitions.
+     * Activity Transitions.
      * @param isTransitionGroup Whether or not the ViewGroup should be treated as a unit
      *                          in Activity transitions. If false, the ViewGroup won't transition,
      *                          only its children. If true, the entire ViewGroup will transition
      *                          together.
+     * @see android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
+     * android.app.ActivityOptions.ActivityTransitionListener)
      */
     public void setTransitionGroup(boolean isTransitionGroup) {
         mGroupFlags |= FLAG_IS_TRANSITION_GROUP_SET;
@@ -2332,6 +2342,7 @@
 
         if (disallowIntercept) {
             mGroupFlags |= FLAG_DISALLOW_INTERCEPT;
+            stopNestedScroll();
         } else {
             mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
         }
@@ -2960,14 +2971,24 @@
             }
         }
 
-        int saveCount = 0;
+        int clipSaveCount = 0;
         final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;
+        boolean hasClipBounds = mClipBounds != null && !sIgnoreClipBoundsForChildren;
+        boolean clippingNeeded = clipToPadding || hasClipBounds;
+
+        if (clippingNeeded) {
+            clipSaveCount = canvas.save();
+        }
+
         if (clipToPadding) {
-            saveCount = canvas.save();
             canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,
                     mScrollX + mRight - mLeft - mPaddingRight,
                     mScrollY + mBottom - mTop - mPaddingBottom);
+        }
 
+        if (hasClipBounds) {
+            canvas.clipRect(mClipBounds.left, mClipBounds.top, mClipBounds.right,
+                    mClipBounds.bottom);
         }
 
         // We will draw our child's animation, let's reset the flag
@@ -3008,8 +3029,8 @@
             onDebugDraw(canvas);
         }
 
-        if (clipToPadding) {
-            canvas.restoreToCount(saveCount);
+        if (clippingNeeded) {
+            canvas.restoreToCount(clipSaveCount);
         }
 
         // mGroupFlags might have been updated by drawChild()
@@ -5844,6 +5865,74 @@
         return true;
     }
 
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+        return false;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public void onNestedScrollAccepted(View child, View target, int axes) {
+        mNestedScrollAxes = axes;
+    }
+
+    /**
+     * @inheritDoc
+     *
+     * <p>The default implementation of onStopNestedScroll calls
+     * {@link #stopNestedScroll()} to halt any recursive nested scrolling in progress.</p>
+     */
+    @Override
+    public void onStopNestedScroll(View child) {
+        // Stop any recursive nested scrolling.
+        stopNestedScroll();
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed) {
+        // Do nothing
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
+        // Do nothing
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public boolean onNestedFling(View target, float velocityX, float velocityY) {
+        return false;
+    }
+
+    /**
+     * Return the current axes of nested scrolling for this ViewGroup.
+     *
+     * <p>A ViewGroup returning something other than {@link #SCROLL_AXIS_NONE} is currently
+     * acting as a nested scrolling parent for one or more descendant views in the hierarchy.</p>
+     *
+     * @return Flags indicating the current axes of nested scrolling
+     * @see #SCROLL_AXIS_HORIZONTAL
+     * @see #SCROLL_AXIS_VERTICAL
+     * @see #SCROLL_AXIS_NONE
+     */
+    public int getNestedScrollAxes() {
+        return mNestedScrollAxes;
+    }
+
     /** @hide */
     protected void onSetLayoutParams(View child, LayoutParams layoutParams) {
     }
diff --git a/core/java/android/view/ViewParent.java b/core/java/android/view/ViewParent.java
index 01376934..3cd6449 100644
--- a/core/java/android/view/ViewParent.java
+++ b/core/java/android/view/ViewParent.java
@@ -407,4 +407,119 @@
      * {@link View#TEXT_ALIGNMENT_VIEW_END}
      */
     public int getTextAlignment();
+
+    /**
+     * React to a descendant view initiating a nestable scroll operation, claiming the
+     * nested scroll operation if appropriate.
+     *
+     * <p>This method will be called in response to a descendant view invoking
+     * {@link View#startNestedScroll(int)}. Each parent up the view hierarchy will be
+     * given an opportunity to respond and claim the nested scrolling operation by returning
+     * <code>true</code>.</p>
+     *
+     * <p>This method may be overridden by ViewParent implementations to indicate when the view
+     * is willing to support a nested scrolling operation that is about to begin. If it returns
+     * true, this ViewParent will become the target view's nested scrolling parent for the duration
+     * of the scroll operation in progress. When the nested scroll is finished this ViewParent
+     * will receive a call to {@link #onStopNestedScroll(View)}.
+     * </p>
+     *
+     * @param child Direct child of this ViewParent containing target
+     * @param target View that initiated the nested scroll
+     * @param nestedScrollAxes Flags consisting of {@link View#SCROLL_AXIS_HORIZONTAL},
+     *                         {@link View#SCROLL_AXIS_VERTICAL} or both
+     * @return true if this ViewParent accepts the nested scroll operation
+     */
+    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes);
+
+    /**
+     * React to the successful claiming of a nested scroll operation.
+     *
+     * <p>This method will be called after
+     * {@link #onStartNestedScroll(View, View, int) onStartNestedScroll} returns true. It offers
+     * an opportunity for the view and its superclasses to perform initial configuration
+     * for the nested scroll. Implementations of this method should always call their superclass's
+     * implementation of this method if one is present.</p>
+     *
+     * @param child Direct child of this ViewParent containing target
+     * @param target View that initiated the nested scroll
+     * @param nestedScrollAxes Flags consisting of {@link View#SCROLL_AXIS_HORIZONTAL},
+     *                         {@link View#SCROLL_AXIS_VERTICAL} or both
+     * @see #onStartNestedScroll(View, View, int)
+     * @see #onStopNestedScroll(View)
+     */
+    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes);
+
+    /**
+     * React to a nested scroll operation ending.
+     *
+     * <p>Perform cleanup after a nested scrolling operation.
+     * This method will be called when a nested scroll stops, for example when a nested touch
+     * scroll ends with a {@link MotionEvent#ACTION_UP} or {@link MotionEvent#ACTION_CANCEL} event.
+     * Implementations of this method should always call their superclass's implementation of this
+     * method if one is present.</p>
+     *
+     * @param target View that initiated the nested scroll
+     */
+    public void onStopNestedScroll(View target);
+
+    /**
+     * React to a nested scroll in progress.
+     *
+     * <p>This method will be called when the ViewParent's current nested scrolling child view
+     * dispatches a nested scroll event. To receive calls to this method the ViewParent must have
+     * previously returned <code>true</code> for a call to
+     * {@link #onStartNestedScroll(View, View, int)}.</p>
+     *
+     * <p>Both the consumed and unconsumed portions of the scroll distance are reported to the
+     * ViewParent. An implementation may choose to use the consumed portion to match or chase scroll
+     * position of multiple child elements, for example. The unconsumed portion may be used to
+     * allow continuous dragging of multiple scrolling or draggable elements, such as scrolling
+     * a list within a vertical drawer where the drawer begins dragging once the edge of inner
+     * scrolling content is reached.</p>
+     *
+     * @param target The descendent view controlling the nested scroll
+     * @param dxConsumed Horizontal scroll distance in pixels already consumed by target
+     * @param dyConsumed Vertical scroll distance in pixels already consumed by target
+     * @param dxUnconsumed Horizontal scroll distance in pixels not consumed by target
+     * @param dyUnconsumed Vertical scroll distance in pixels not consumed by target
+     */
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed);
+
+    /**
+     * React to a nested scroll in progress before the target view consumes a portion of the scroll.
+     *
+     * <p>When working with nested scrolling often the parent view may want an opportunity
+     * to consume the scroll before the nested scrolling child does. An example of this is a
+     * drawer that contains a scrollable list. The user will want to be able to scroll the list
+     * fully into view before the list itself begins scrolling.</p>
+     *
+     * <p><code>onNestedPreScroll</code> is called when a nested scrolling child invokes
+     * {@link View#dispatchNestedPreScroll(int, int, int[], int[])}. The implementation should
+     * report how any pixels of the scroll reported by dx, dy were consumed in the
+     * <code>consumed</code> array. Index 0 corresponds to dx and index 1 corresponds to dy.
+     * This parameter will never be null. Initial values for consumed[0] and consumed[1]
+     * will always be 0.</p>
+     *
+     * @param target View that initiated the nested scroll
+     * @param dx Horizontal scroll distance in pixels
+     * @param dy Vertical scroll distance in pixels
+     * @param consumed Output. The horizontal and vertical scroll distance consumed by this parent
+     */
+    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed);
+
+    /**
+     * Request a fling from a nested scroll.
+     *
+     * <p>If a nested scrolling child view would normally fling but it is at the edge of
+     * its own content, it can delegate the fling to its nested scrolling parent instead.
+     * This method allows the parent to optionally consume the fling.</p>
+     *
+     * @param target View that initiated the nested scroll
+     * @param velocityX Horizontal velocity in pixels per second.
+     * @param velocityY Vertical velocity in pixels per second
+     * @return true if this parent consumed the fling
+     */
+    public boolean onNestedFling(View target, float velocityX, float velocityY);
 }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index 6b21451..11d2622 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -133,21 +133,22 @@
      * Constants used to associate a property being requested and the mechanism used to set
      * the property (this class calls directly into View to set the properties in question).
      */
-    private static final int NONE           = 0x0000;
-    private static final int TRANSLATION_X  = 0x0001;
-    private static final int TRANSLATION_Y  = 0x0002;
-    private static final int TRANSLATION_Z  = 0x0004;
-    private static final int SCALE_X        = 0x0008;
-    private static final int SCALE_Y        = 0x0010;
-    private static final int ROTATION       = 0x0020;
-    private static final int ROTATION_X     = 0x0040;
-    private static final int ROTATION_Y     = 0x0080;
-    private static final int X              = 0x0100;
-    private static final int Y              = 0x0200;
-    private static final int ALPHA          = 0x0400;
+    static final int NONE           = 0x0000;
+    static final int TRANSLATION_X  = 0x0001;
+    static final int TRANSLATION_Y  = 0x0002;
+    static final int TRANSLATION_Z  = 0x0004;
+    static final int SCALE_X        = 0x0008;
+    static final int SCALE_Y        = 0x0010;
+    static final int ROTATION       = 0x0020;
+    static final int ROTATION_X     = 0x0040;
+    static final int ROTATION_Y     = 0x0080;
+    static final int X              = 0x0100;
+    static final int Y              = 0x0200;
+    static final int Z              = 0x0400;
+    static final int ALPHA          = 0x0800;
 
     private static final int TRANSFORM_MASK = TRANSLATION_X | TRANSLATION_Y | TRANSLATION_Z |
-            SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y;
+            SCALE_X | SCALE_Y | ROTATION | ROTATION_X | ROTATION_Y | X | Y | Z;
 
     /**
      * The mechanism by which the user can request several properties that are then animated
@@ -470,6 +471,32 @@
     }
 
     /**
+     * This method will cause the View's <code>z</code> property to be animated to the
+     * specified value. Animations already running on the property will be canceled.
+     *
+     * @param value The value to be animated to.
+     * @see View#setZ(float)
+     * @return This object, allowing calls to methods in this class to be chained.
+     */
+    public ViewPropertyAnimator z(float value) {
+        animateProperty(Z, value);
+        return this;
+    }
+
+    /**
+     * This method will cause the View's <code>z</code> property to be animated by the
+     * specified value. Animations already running on the property will be canceled.
+     *
+     * @param value The amount to be animated by, as an offset from the current value.
+     * @see View#setZ(float)
+     * @return This object, allowing calls to methods in this class to be chained.
+     */
+    public ViewPropertyAnimator zBy(float value) {
+        animatePropertyBy(Z, value);
+        return this;
+    }
+
+    /**
      * This method will cause the View's <code>rotation</code> property to be animated to the
      * specified value. Animations already running on the property will be canceled.
      *
@@ -957,6 +984,9 @@
             case Y:
                 renderNode.setTranslationY(value - mView.mTop);
                 break;
+            case Z:
+                renderNode.setTranslationZ(value - renderNode.getElevation());
+                break;
             case ALPHA:
                 info.mAlpha = value;
                 renderNode.setAlpha(value);
@@ -993,6 +1023,8 @@
                 return mView.mLeft + node.getTranslationX();
             case Y:
                 return mView.mTop + node.getTranslationY();
+            case Z:
+                return node.getElevation() + node.getTranslationZ();
             case ALPHA:
                 return mView.mTransformationInfo.mAlpha;
         }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 2d503bf..14e422c 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -37,6 +37,8 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
+import android.hardware.display.DisplayManager.DisplayListener;
 import android.media.AudioManager;
 import android.os.Binder;
 import android.os.Bundle;
@@ -134,6 +136,7 @@
     final Context mContext;
     final IWindowSession mWindowSession;
     final Display mDisplay;
+    final DisplayManager mDisplayManager;
     final String mBasePackageName;
 
     final int[] mTmpLocation = new int[2];
@@ -370,9 +373,7 @@
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
         mFallbackEventHandler = PolicyManager.makeNewFallbackEventHandler(context);
         mChoreographer = Choreographer.getInstance();
-
-        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
-        mAttachInfo.mScreenOn = powerManager.isScreenOn();
+        mDisplayManager = (DisplayManager)context.getSystemService(Context.DISPLAY_SERVICE);
         loadSystemProperties();
     }
 
@@ -427,6 +428,10 @@
         synchronized (this) {
             if (mView == null) {
                 mView = view;
+
+                mAttachInfo.mDisplayState = mDisplay.getState();
+                mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+
                 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
@@ -673,6 +678,14 @@
         }
     }
 
+    public boolean invokeFunctor(long functor, boolean waitForCompletion) {
+        if (mAttachInfo.mHardwareRenderer == null || !mAttachInfo.mHardwareRenderer.isEnabled()) {
+            return false;
+        }
+        mAttachInfo.mHardwareRenderer.invokeFunctor(functor, waitForCompletion);
+        return true;
+    }
+
     private void enableHardwareAcceleration(WindowManager.LayoutParams attrs) {
         mAttachInfo.mHardwareAccelerated = false;
         mAttachInfo.mHardwareAccelerationRequested = false;
@@ -797,18 +810,43 @@
         scheduleTraversals();
     }
 
-    void handleScreenStateChange(boolean on) {
-        if (on != mAttachInfo.mScreenOn) {
-            mAttachInfo.mScreenOn = on;
-            if (mView != null) {
-                mView.dispatchScreenStateChanged(on ? View.SCREEN_STATE_ON : View.SCREEN_STATE_OFF);
-            }
-            if (on) {
-                mFullRedrawNeeded = true;
-                scheduleTraversals();
+    private final DisplayListener mDisplayListener = new DisplayListener() {
+        @Override
+        public void onDisplayChanged(int displayId) {
+            if (mView != null && mDisplay.getDisplayId() == displayId) {
+                final int oldDisplayState = mAttachInfo.mDisplayState;
+                final int newDisplayState = mDisplay.getState();
+                if (oldDisplayState != newDisplayState) {
+                    mAttachInfo.mDisplayState = newDisplayState;
+                    if (oldDisplayState != Display.STATE_UNKNOWN) {
+                        final int oldScreenState = toViewScreenState(oldDisplayState);
+                        final int newScreenState = toViewScreenState(newDisplayState);
+                        if (oldScreenState != newScreenState) {
+                            mView.dispatchScreenStateChanged(newScreenState);
+                        }
+                        if (oldDisplayState == Display.STATE_OFF) {
+                            // Draw was suppressed so we need to for it to happen here.
+                            mFullRedrawNeeded = true;
+                            scheduleTraversals();
+                        }
+                    }
+                }
             }
         }
-    }
+
+        @Override
+        public void onDisplayRemoved(int displayId) {
+        }
+
+        @Override
+        public void onDisplayAdded(int displayId) {
+        }
+
+        private int toViewScreenState(int displayState) {
+            return displayState == Display.STATE_OFF ?
+                    View.SCREEN_STATE_OFF : View.SCREEN_STATE_ON;
+        }
+    };
 
     @Override
     public void requestFitSystemWindows() {
@@ -1141,6 +1179,19 @@
         m.preTranslate(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
     }
 
+    void dispatchApplyInsets(View host) {
+        mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
+        boolean isRound = false;
+        if ((mWindowAttributes.flags & WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN) != 0
+                && mDisplay.getDisplayId() == 0) {
+            // we're fullscreen and not hosted in an ActivityView
+            isRound = mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_windowIsRound);
+        }
+        host.dispatchApplyWindowInsets(new WindowInsets(
+                mFitSystemWindowsInsets, isRound));
+    }
+
     private void performTraversals() {
         // cache mView since it is used so much below...
         final View host = mView;
@@ -1227,8 +1278,7 @@
             }
             host.dispatchAttachedToWindow(attachInfo, 0);
             attachInfo.mTreeObserver.dispatchOnWindowAttachedChange(true);
-            mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
-            host.fitSystemWindows(mFitSystemWindowsInsets);
+            dispatchApplyInsets(host);
             //Log.i(TAG, "Screen on initialized: " + attachInfo.mKeepScreenOn);
 
         } else {
@@ -1353,9 +1403,8 @@
 
         if (mFitSystemWindowsRequested) {
             mFitSystemWindowsRequested = false;
-            mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
             mLastOverscanRequested = mAttachInfo.mOverscanRequested;
-            host.fitSystemWindows(mFitSystemWindowsInsets);
+            dispatchApplyInsets(host);
             if (mLayoutRequested) {
                 // Short-circuit catching a new layout request here, so
                 // we don't need to go through two layout passes when things
@@ -1473,43 +1522,46 @@
                         mResizeBuffer.prepare(mWidth, mHeight, false);
                         RenderNode layerRenderNode = mResizeBuffer.startRecording();
                         HardwareCanvas layerCanvas = layerRenderNode.start(mWidth, mHeight);
-                        final int restoreCount = layerCanvas.save();
+                        try {
+                            final int restoreCount = layerCanvas.save();
 
-                        int yoff;
-                        final boolean scrolling = mScroller != null
-                                && mScroller.computeScrollOffset();
-                        if (scrolling) {
-                            yoff = mScroller.getCurrY();
-                            mScroller.abortAnimation();
-                        } else {
-                            yoff = mScrollY;
+                            int yoff;
+                            final boolean scrolling = mScroller != null
+                                    && mScroller.computeScrollOffset();
+                            if (scrolling) {
+                                yoff = mScroller.getCurrY();
+                                mScroller.abortAnimation();
+                            } else {
+                                yoff = mScrollY;
+                            }
+
+                            layerCanvas.translate(0, -yoff);
+                            if (mTranslator != null) {
+                                mTranslator.translateCanvas(layerCanvas);
+                            }
+
+                            RenderNode renderNode = mView.mRenderNode;
+                            if (renderNode != null && renderNode.isValid()) {
+                                layerCanvas.drawDisplayList(renderNode, null,
+                                        RenderNode.FLAG_CLIP_CHILDREN);
+                            } else {
+                                mView.draw(layerCanvas);
+                            }
+
+                            drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
+
+                            mResizeBufferStartTime = SystemClock.uptimeMillis();
+                            mResizeBufferDuration = mView.getResources().getInteger(
+                                    com.android.internal.R.integer.config_mediumAnimTime);
+
+                            layerCanvas.restoreToCount(restoreCount);
+                            layerRenderNode.end(layerCanvas);
+                            layerRenderNode.setCaching(true);
+                            layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
+                            mTempRect.set(0, 0, mWidth, mHeight);
+                        } finally {
+                            mResizeBuffer.endRecording(mTempRect);
                         }
-
-                        layerCanvas.translate(0, -yoff);
-                        if (mTranslator != null) {
-                            mTranslator.translateCanvas(layerCanvas);
-                        }
-
-                        RenderNode renderNode = mView.mRenderNode;
-                        if (renderNode != null && renderNode.isValid()) {
-                            layerCanvas.drawDisplayList(renderNode, null,
-                                    RenderNode.FLAG_CLIP_CHILDREN);
-                        } else {
-                            mView.draw(layerCanvas);
-                        }
-
-                        drawAccessibilityFocusedDrawableIfNeeded(layerCanvas);
-
-                        mResizeBufferStartTime = SystemClock.uptimeMillis();
-                        mResizeBufferDuration = mView.getResources().getInteger(
-                                com.android.internal.R.integer.config_mediumAnimTime);
-
-                        layerCanvas.restoreToCount(restoreCount);
-                        layerRenderNode.end(mAttachInfo.mHardwareRenderer, layerCanvas);
-                        layerRenderNode.setCaching(true);
-                        layerRenderNode.setLeftTopRightBottom(0, 0, mWidth, mHeight);
-                        mTempRect.set(0, 0, mWidth, mHeight);
-                        mResizeBuffer.endRecording(mTempRect);
                         mAttachInfo.mHardwareRenderer.flushLayerUpdates();
                     }
                     mAttachInfo.mContentInsets.set(mPendingContentInsets);
@@ -1529,8 +1581,7 @@
                     mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
                     mLastOverscanRequested = mAttachInfo.mOverscanRequested;
                     mFitSystemWindowsRequested = false;
-                    mFitSystemWindowsInsets.set(mAttachInfo.mContentInsets);
-                    host.fitSystemWindows(mFitSystemWindowsInsets);
+                    dispatchApplyInsets(host);
                 }
                 if (visibleInsetsChanged) {
                     mAttachInfo.mVisibleInsets.set(mPendingVisibleInsets);
@@ -2174,10 +2225,7 @@
             mResizePaint.setAlpha(mResizeAlpha);
             canvas.drawHardwareLayer(mResizeBuffer, 0.0f, mHardwareYOffset, mResizePaint);
         }
-        // TODO: this
-        if (!HardwareRenderer.sUseRenderThread) {
-            drawAccessibilityFocusedDrawableIfNeeded(canvas);
-        }
+        drawAccessibilityFocusedDrawableIfNeeded(canvas);
     }
 
     /**
@@ -2247,7 +2295,7 @@
     }
 
     private void performDraw() {
-        if (!mAttachInfo.mScreenOn && !mReportNextDraw) {
+        if (mAttachInfo.mDisplayState == Display.STATE_OFF && !mReportNextDraw) {
             return;
         }
 
@@ -2873,6 +2921,8 @@
             mInputChannel = null;
         }
 
+        mDisplayManager.unregisterDisplayListener(mDisplayListener);
+
         unscheduleTraversals();
     }
 
@@ -2910,7 +2960,7 @@
             }
         }
     }
-    
+
     /**
      * Return true if child is an ancestor of parent, (or equal to the parent).
      */
@@ -2952,7 +3002,6 @@
     private final static int MSG_DISPATCH_SYSTEM_UI_VISIBILITY = 17;
     private final static int MSG_UPDATE_CONFIGURATION = 18;
     private final static int MSG_PROCESS_INPUT_EVENTS = 19;
-    private final static int MSG_DISPATCH_SCREEN_STATE = 20;
     private final static int MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST = 21;
     private final static int MSG_DISPATCH_DONE_ANIMATING = 22;
     private final static int MSG_INVALIDATE_WORLD = 23;
@@ -2999,8 +3048,6 @@
                     return "MSG_UPDATE_CONFIGURATION";
                 case MSG_PROCESS_INPUT_EVENTS:
                     return "MSG_PROCESS_INPUT_EVENTS";
-                case MSG_DISPATCH_SCREEN_STATE:
-                    return "MSG_DISPATCH_SCREEN_STATE";
                 case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST:
                     return "MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST";
                 case MSG_DISPATCH_DONE_ANIMATING:
@@ -3165,8 +3212,11 @@
                 doDie();
                 break;
             case MSG_DISPATCH_INPUT_EVENT: {
-                InputEvent event = (InputEvent)msg.obj;
-                enqueueInputEvent(event, null, 0, true);
+                SomeArgs args = (SomeArgs)msg.obj;
+                InputEvent event = (InputEvent)args.arg1;
+                InputEventReceiver receiver = (InputEventReceiver)args.arg2;
+                enqueueInputEvent(event, receiver, 0, true);
+                args.recycle();
             } break;
             case MSG_DISPATCH_KEY_FROM_IME: {
                 if (LOCAL_LOGV) Log.v(
@@ -3214,11 +3264,6 @@
                 }
                 updateConfiguration(config, false);
             } break;
-            case MSG_DISPATCH_SCREEN_STATE: {
-                if (mView != null) {
-                    handleScreenStateChange(msg.arg1 == 1);
-                }
-            } break;
             case MSG_CLEAR_ACCESSIBILITY_FOCUS_HOST: {
                 setAccessibilityFocus(null, null);
             } break;
@@ -3691,7 +3736,8 @@
                     if (result == InputMethodManager.DISPATCH_HANDLED) {
                         return FINISH_HANDLED;
                     } else if (result == InputMethodManager.DISPATCH_NOT_HANDLED) {
-                        return FINISH_NOT_HANDLED;
+                        // The IME could not handle it, so skip along to the next InputStage
+                        return FORWARD;
                     } else {
                         return DEFER; // callback will be invoked later
                     }
@@ -5752,7 +5798,14 @@
     }
 
     public void dispatchInputEvent(InputEvent event) {
-        Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, event);
+        dispatchInputEvent(event, null);
+    }
+
+    public void dispatchInputEvent(InputEvent event, InputEventReceiver receiver) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = event;
+        args.arg2 = receiver;
+        Message msg = mHandler.obtainMessage(MSG_DISPATCH_INPUT_EVENT, args);
         msg.setAsynchronous(true);
         mHandler.sendMessage(msg);
     }
@@ -5789,18 +5842,19 @@
         }
     }
 
+    public void dispatchUnhandledInputEvent(InputEvent event) {
+        if (event instanceof KeyEvent) {
+            dispatchUnhandledKey((KeyEvent) event);
+            return;
+        }
+    }
+
     public void dispatchAppVisibility(boolean visible) {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_APP_VISIBILITY);
         msg.arg1 = visible ? 1 : 0;
         mHandler.sendMessage(msg);
     }
 
-    public void dispatchScreenStateChange(boolean on) {
-        Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATE);
-        msg.arg1 = on ? 1 : 0;
-        mHandler.sendMessage(msg);
-    }
-
     public void dispatchGetNewSurface() {
         Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE);
         mHandler.sendMessage(msg);
@@ -6054,6 +6108,33 @@
         // Do nothing.
     }
 
+    @Override
+    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+        return false;
+    }
+
+    @Override
+    public void onStopNestedScroll(View target) {
+    }
+
+    @Override
+    public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes) {
+    }
+
+    @Override
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed) {
+    }
+
+    @Override
+    public void onNestedPreScroll(View target, int dx, int dy, int[] consumed) {
+    }
+
+    @Override
+    public boolean onNestedFling(View target, float velocityX, float velocityY) {
+        return false;
+    }
+
     void changeCanvasOpacity(boolean opaque) {
         // TODO(romainguy): recreate Canvas (software or hardware) to reflect the opacity change.
         Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque);
@@ -6139,14 +6220,6 @@
         }
 
         @Override
-        public void dispatchScreenState(boolean on) {
-            final ViewRootImpl viewAncestor = mViewAncestor.get();
-            if (viewAncestor != null) {
-                viewAncestor.dispatchScreenStateChange(on);
-            }
-        }
-
-        @Override
         public void dispatchGetNewSurface() {
             final ViewRootImpl viewAncestor = mViewAncestor.get();
             if (viewAncestor != null) {
diff --git a/core/java/android/view/VolumePanel.java b/core/java/android/view/VolumePanel.java
index b05225b..4730e59 100644
--- a/core/java/android/view/VolumePanel.java
+++ b/core/java/android/view/VolumePanel.java
@@ -56,10 +56,8 @@
  *
  * @hide
  */
-public class VolumePanel extends Handler implements OnSeekBarChangeListener, View.OnClickListener,
-        VolumeController
-{
-    private static final String TAG = "VolumePanel";
+public class VolumePanel extends Handler implements VolumeController {
+    private static final String TAG = VolumePanel.class.getSimpleName();
     private static boolean LOGD = false;
 
     /**
@@ -187,7 +185,7 @@
             this.iconMuteRes = iconMuteRes;
             this.show = show;
         }
-    };
+    }
 
     // List of stream types and their order
     private static final StreamResources[] STREAMS = {
@@ -238,6 +236,7 @@
             cleanUp();
         }
 
+        @Override
         public void onDismiss(DialogInterface unused) {
             mContext.unregisterReceiver(this);
             cleanUp();
@@ -253,14 +252,14 @@
     }
 
 
-    public VolumePanel(final Context context, AudioService volumeService) {
+    public VolumePanel(Context context, AudioService volumeService) {
         mContext = context;
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
         mAudioService = volumeService;
 
         // For now, only show master volume if master volume is supported
-        boolean useMasterVolume = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_useMasterVolume);
+        final Resources res = context.getResources();
+        final boolean useMasterVolume = res.getBoolean(R.bool.config_useMasterVolume);
         if (useMasterVolume) {
             for (int i = 0; i < STREAMS.length; i++) {
                 StreamResources streamRes = STREAMS[i];
@@ -268,21 +267,8 @@
             }
         }
 
-        LayoutInflater inflater = (LayoutInflater) context
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View view = mView = inflater.inflate(R.layout.volume_adjust, null);
-        mView.setOnTouchListener(new View.OnTouchListener() {
-            public boolean onTouch(View v, MotionEvent event) {
-                resetTimeout();
-                return false;
-            }
-        });
-        mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel);
-        mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group);
-        mMoreButton = (ImageView) mView.findViewById(R.id.expand_button);
-        mDivider = (ImageView) mView.findViewById(R.id.expand_button_divider);
-
-        mDialog = new Dialog(context, R.style.Theme_Panel_Volume) {
+        mDialog = new Dialog(context) {
+            @Override
             public boolean onTouchEvent(MotionEvent event) {
                 if (isShowing() && event.getAction() == MotionEvent.ACTION_OUTSIDE &&
                         sConfirmSafeVolumeDialog == null) {
@@ -292,47 +278,65 @@
                 return false;
             }
         };
-        mDialog.setTitle("Volume control"); // No need to localize
-        mDialog.setContentView(mView);
+
+        // Change some window properties
+        final Window window = mDialog.getWindow();
+        final LayoutParams lp = window.getAttributes();
+        lp.token = null;
+        // Offset from the top
+        lp.y = res.getDimensionPixelOffset(R.dimen.volume_panel_top);
+        lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
+        lp.windowAnimations = R.style.Animation_VolumePanel;
+        window.setAttributes(lp);
+        window.setGravity(Gravity.TOP);
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
+        window.requestFeature(Window.FEATURE_NO_TITLE);
+        window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE
+                | LayoutParams.FLAG_NOT_TOUCH_MODAL
+                | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
+
+        mDialog.setCanceledOnTouchOutside(true);
+        mDialog.setContentView(R.layout.volume_adjust);
         mDialog.setOnDismissListener(new OnDismissListener() {
+            @Override
             public void onDismiss(DialogInterface dialog) {
                 mActiveStreamType = -1;
                 mAudioManager.forceVolumeControlStream(mActiveStreamType);
             }
         });
-        // Change some window properties
-        Window window = mDialog.getWindow();
-        window.setGravity(Gravity.TOP);
-        LayoutParams lp = window.getAttributes();
-        lp.token = null;
-        // Offset from the top
-        lp.y = mContext.getResources().getDimensionPixelOffset(
-                com.android.internal.R.dimen.volume_panel_top);
-        lp.type = LayoutParams.TYPE_VOLUME_OVERLAY;
-        lp.width = LayoutParams.WRAP_CONTENT;
-        lp.height = LayoutParams.WRAP_CONTENT;
-        window.setAttributes(lp);
-        window.addFlags(LayoutParams.FLAG_NOT_FOCUSABLE | LayoutParams.FLAG_NOT_TOUCH_MODAL
-                | LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH);
+
+        mDialog.create();
+
+        mView = window.findViewById(R.id.content);
+        mView.setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View v, MotionEvent event) {
+                resetTimeout();
+                return false;
+            }
+        });
+
+        mPanel = (ViewGroup) mView.findViewById(R.id.visible_panel);
+        mSliderGroup = (ViewGroup) mView.findViewById(R.id.slider_group);
+        mMoreButton = mView.findViewById(R.id.expand_button);
+        mDivider = mView.findViewById(R.id.expand_button_divider);
 
         mToneGenerators = new ToneGenerator[AudioSystem.getNumStreamTypes()];
-        mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
-
+        mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
         mVoiceCapable = context.getResources().getBoolean(R.bool.config_voice_capable);
+
+        // If we don't want to show multiple volumes, hide the settings button
+        // and divider.
         mShowCombinedVolumes = !mVoiceCapable && !useMasterVolume;
-        // If we don't want to show multiple volumes, hide the settings button and divider
         if (!mShowCombinedVolumes) {
             mMoreButton.setVisibility(View.GONE);
             mDivider.setVisibility(View.GONE);
         } else {
-            mMoreButton.setOnClickListener(this);
+            mMoreButton.setOnClickListener(mClickListener);
         }
 
-        boolean masterVolumeOnly = context.getResources().getBoolean(
-                com.android.internal.R.bool.config_useMasterVolume);
-        boolean masterVolumeKeySounds = mContext.getResources().getBoolean(
-                com.android.internal.R.bool.config_useVolumeKeySounds);
-
+        final boolean masterVolumeOnly = res.getBoolean(R.bool.config_useMasterVolume);
+        final boolean masterVolumeKeySounds = res.getBoolean(R.bool.config_useVolumeKeySounds);
         mPlayMasterStreamTones = masterVolumeOnly && masterVolumeKeySounds;
 
         listenToRingerMode();
@@ -347,7 +351,7 @@
         final IntentFilter filter = new IntentFilter();
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         mContext.registerReceiver(new BroadcastReceiver() {
-
+            @Override
             public void onReceive(Context context, Intent intent) {
                 final String action = intent.getAction();
 
@@ -400,17 +404,21 @@
     }
 
     private void createSliders() {
-        LayoutInflater inflater = (LayoutInflater) mContext
-                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+        final Resources res = mContext.getResources();
+        final LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(
+                Context.LAYOUT_INFLATER_SERVICE);
+
         mStreamControls = new HashMap<Integer, StreamControl>(STREAMS.length);
-        Resources res = mContext.getResources();
+
         for (int i = 0; i < STREAMS.length; i++) {
             StreamResources streamRes = STREAMS[i];
-            int streamType = streamRes.streamType;
+
+            final int streamType = streamRes.streamType;
             if (mVoiceCapable && streamRes == StreamResources.NotificationStream) {
                 streamRes = StreamResources.RingerStream;
             }
-            StreamControl sc = new StreamControl();
+
+            final StreamControl sc = new StreamControl();
             sc.streamType = streamType;
             sc.group = (ViewGroup) inflater.inflate(R.layout.volume_adjust_item, null);
             sc.group.setTag(sc);
@@ -421,10 +429,10 @@
             sc.iconMuteRes = streamRes.iconMuteRes;
             sc.icon.setImageResource(sc.iconRes);
             sc.seekbarView = (SeekBar) sc.group.findViewById(R.id.seekbar);
-            int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
+            final int plusOne = (streamType == AudioSystem.STREAM_BLUETOOTH_SCO ||
                     streamType == AudioSystem.STREAM_VOICE_CALL) ? 1 : 0;
             sc.seekbarView.setMax(getStreamMaxVolume(streamType) + plusOne);
-            sc.seekbarView.setOnSeekBarChangeListener(this);
+            sc.seekbarView.setOnSeekBarChangeListener(mSeekListener);
             sc.seekbarView.setTag(sc);
             mStreamControls.put(streamType, sc);
         }
@@ -433,7 +441,7 @@
     private void reorderSliders(int activeStreamType) {
         mSliderGroup.removeAllViews();
 
-        StreamControl active = mStreamControls.get(activeStreamType);
+        final StreamControl active = mStreamControls.get(activeStreamType);
         if (active == null) {
             Log.e("VolumePanel", "Missing stream type! - " + activeStreamType);
             mActiveStreamType = -1;
@@ -486,10 +494,6 @@
         }
     }
 
-    private boolean isExpanded() {
-        return mMoreButton.getVisibility() != View.VISIBLE;
-    }
-
     private void expand() {
         final int count = mSliderGroup.getChildCount();
         for (int i = 0; i < count; i++) {
@@ -527,6 +531,7 @@
         obtainMessage(MSG_VOLUME_CHANGED, streamType, flags).sendToTarget();
     }
 
+    @Override
     public void postRemoteVolumeChanged(int streamType, int flags) {
         if (hasMessages(MSG_REMOTE_VOLUME_CHANGED)) return;
         synchronized (this) {
@@ -538,6 +543,7 @@
         obtainMessage(MSG_REMOTE_VOLUME_CHANGED, streamType, flags).sendToTarget();
     }
 
+    @Override
     public void postRemoteSliderVisibility(boolean visible) {
         obtainMessage(MSG_SLIDER_VISIBILITY_CHANGED,
                 AudioService.STREAM_REMOTE_MUSIC, visible ? 1 : 0).sendToTarget();
@@ -554,6 +560,7 @@
      * as a request to update the volume), the application will likely set a new volume. If the UI
      * is still up, we need to refresh the display to show this new value.
      */
+    @Override
     public void postHasNewRemotePlaybackInfo() {
         if (hasMessages(MSG_REMOTE_VOLUME_UPDATE_IF_SHOWN)) return;
         // don't create or prevent resources to be freed, if they disappear, this update came too
@@ -733,7 +740,7 @@
             int stream = (streamType == AudioService.STREAM_REMOTE_MUSIC) ? -1 : streamType;
             // when the stream is for remote playback, use -1 to reset the stream type evaluation
             mAudioManager.forceVolumeControlStream(stream);
-            mDialog.setContentView(mView);
+
             // Showing dialog - use collapsed state
             if (mShowCombinedVolumes) {
                 collapse();
@@ -865,6 +872,7 @@
                         .setMessage(com.android.internal.R.string.safe_media_volume_warning)
                         .setPositiveButton(com.android.internal.R.string.yes,
                                             new DialogInterface.OnClickListener() {
+                            @Override
                             public void onClick(DialogInterface dialog, int which) {
                                 mAudioService.disableSafeMediaVolume();
                             }
@@ -1021,39 +1029,48 @@
         sendMessage(obtainMessage(MSG_TIMEOUT));
     }
 
-    public void onProgressChanged(SeekBar seekBar, int progress,
-            boolean fromUser) {
-        final Object tag = seekBar.getTag();
-        if (fromUser && tag instanceof StreamControl) {
-            StreamControl sc = (StreamControl) tag;
-            if (getStreamVolume(sc.streamType) != progress) {
-                setStreamVolume(sc.streamType, progress, 0);
+    private final OnSeekBarChangeListener mSeekListener = new OnSeekBarChangeListener() {
+        @Override
+        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+            final Object tag = seekBar.getTag();
+            if (fromUser && tag instanceof StreamControl) {
+                StreamControl sc = (StreamControl) tag;
+                if (getStreamVolume(sc.streamType) != progress) {
+                    setStreamVolume(sc.streamType, progress, 0);
+                }
+            }
+            resetTimeout();
+        }
+
+        @Override
+        public void onStartTrackingTouch(SeekBar seekBar) {
+        }
+
+        @Override
+        public void onStopTrackingTouch(SeekBar seekBar) {
+            final Object tag = seekBar.getTag();
+            if (tag instanceof StreamControl) {
+                StreamControl sc = (StreamControl) tag;
+                // Because remote volume updates are asynchronous, AudioService
+                // might have received a new remote volume value since the
+                // finger adjusted the slider. So when the progress of the
+                // slider isn't being tracked anymore, adjust the slider to the
+                // last "published" remote volume value, so the UI reflects the
+                // actual volume.
+                if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
+                    seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC));
+                }
             }
         }
-        resetTimeout();
-    }
+    };
 
-    public void onStartTrackingTouch(SeekBar seekBar) {
-    }
-
-    public void onStopTrackingTouch(SeekBar seekBar) {
-        final Object tag = seekBar.getTag();
-        if (tag instanceof StreamControl) {
-            StreamControl sc = (StreamControl) tag;
-            // because remote volume updates are asynchronous, AudioService might have received
-            // a new remote volume value since the finger adjusted the slider. So when the
-            // progress of the slider isn't being tracked anymore, adjust the slider to the last
-            // "published" remote volume value, so the UI reflects the actual volume.
-            if (sc.streamType == AudioService.STREAM_REMOTE_MUSIC) {
-                seekBar.setProgress(getStreamVolume(AudioService.STREAM_REMOTE_MUSIC));
+    private final View.OnClickListener mClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            if (v == mMoreButton) {
+                expand();
             }
+            resetTimeout();
         }
-    }
-
-    public void onClick(View v) {
-        if (v == mMoreButton) {
-            expand();
-        }
-        resetTimeout();
-    }
+    };
 }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 7bd1f56..9c44bd1 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -32,8 +32,6 @@
 import android.transition.TransitionManager;
 import android.view.accessibility.AccessibilityEvent;
 
-import java.util.Map;
-
 /**
  * Abstract base class for a top-level window look and behavior policy.  An
  * instance of this class should be used as the top-level view added to the
@@ -1385,86 +1383,132 @@
     }
 
     /**
-     * Set options that can affect the transition behavior within this window.
-     * @param options Options to set or null for none
-     * @hide
+     * Sets the Transition that will be used to move Views into the initial scene. The entering
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
+     * entering Views will remain unaffected.
+     * @param transition The Transition to use to move Views into the initial Scene.
      */
-    public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
-    }
+    public void setEnterTransition(Transition transition) {}
 
     /**
-     * A callback for Window transitions to be told when the shared element is ready to be shown
-     * and start the transition to its target location.
-     * @hide
+     * Sets the Transition that will be used to move Views out of the scene when starting a
+     * new Activity. The exiting Views will be those that are regular Views or ViewGroups that
+     * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as exiting is governed by changing visibility
+     * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+     * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     * @param transition The Transition to use to move Views out of the scene when calling a
+     *                   new Activity.
      */
-    public interface SceneTransitionListener {
-        void nullPendingTransition();
-        void convertFromTranslucent();
-        void convertToTranslucent();
-        void sharedElementStart(Transition transition);
-        void sharedElementEnd();
-    }
+    public void setExitTransition(Transition transition) {}
 
     /**
-     * Controls how the Activity's start Scene is faded in and when the enter scene
-     * is triggered to start.
-     * <p>When allow is true, the enter Scene will begin as soon as possible
-     * and the background will fade in when all shared elements are ready to begin
-     * transitioning. If allow is false, the Activity enter Scene and
-     * background fade will be triggered when the calling Activity's exit transition
-     * completes.</p>
-     * @param allow Set to true to have the Activity enter scene transition in
-     *              as early as possible or set to false to wait for the calling
-     *              Activity to exit first. The default value is true.
+     * Returns the transition used to move Views into the initial scene. The entering
+     * Views will be those that are regular Views or ViewGroups that have
+     * {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as entering is governed by changing visibility from
+     * {@link View#INVISIBLE} to {@link View#VISIBLE}. If <code>transition</code> is null,
+     * entering Views will remain unaffected.  Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
+     * @return the Transition to use to move Views into the initial Scene.
      */
-    public void setAllowOverlappingEnterTransition(boolean allow) {
-    }
+    public Transition getEnterTransition() { return null; }
 
     /**
-     * Controls how the Activity's Scene fades out and when the calling Activity's
-     * enter scene is triggered when finishing to return to a calling Activity.
-     * <p>When allow is true, the Scene will fade out quickly
-     * and inform the calling Activity to transition in when the fade completes.
-     * When allow is false, the calling Activity will transition in after
-     * the Activity's Scene has exited.
-     * </p>
-     * @param allow Set to true to have the Activity fade out as soon as possible
-     *              and transition in the calling Activity. The default value is
-     *              true.
+     * Returns the Transition that will be used to move Views out of the scene when starting a
+     * new Activity. The exiting Views will be those that are regular Views or ViewGroups that
+     * have {@link ViewGroup#isTransitionGroup} return true. Typical Transitions will extend
+     * {@link android.transition.Visibility} as exiting is governed by changing visibility
+     * from {@link View#VISIBLE} to {@link View#INVISIBLE}. If transition is null, the views will
+     * remain unaffected. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     * @return the Transition to use to move Views out of the scene when calling a
+     * new Activity.
      */
-    public void setAllowOverlappingExitTransition(boolean allow) {
-    }
+    public Transition getExitTransition() { return null; }
 
     /**
-     * Start the exit transition.
-     * @hide
+     * Sets the Transition that will be used for shared elements transferred into the content
+     * Scene. Typical Transitions will affect size and location, such as
+     * {@link android.transition.MoveImage} and {@link android.transition.ChangeBounds}. A null
+     * value will cause transferred shared elements to blink to the final position.
+     * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     * @param transition The Transition to use for shared elements transferred into the content
+     *                   Scene.
      */
-    public Bundle startExitTransitionToCallee(Bundle options) {
-        return null;
-    }
+    public void setSharedElementEnterTransition(Transition transition) {}
 
     /**
-     * Starts the transition back to the calling Activity.
-     * onTransitionEnd will be called on the current thread if there is no exit transition.
-     * @hide
+     * Returns the Transition that will be used for shared elements transferred into the content
+     * Scene. Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     * @return Transition to use for sharend elements transferred into the content Scene.
      */
-    public void startExitTransitionToCaller(Runnable onTransitionEnd) {
-        onTransitionEnd.run();
-    }
-
-    /** @hide */
-    public void restoreViewVisibilityAfterTransitionToCallee() {
-    }
+    public Transition getSharedElementEnterTransition() { return null; }
 
     /**
-     * On entering Activity Scene transitions, shared element names may be mapped from a
-     * source Activity's specified name to a unique shared element name in the View hierarchy.
-     * Under most circumstances, mapping is not necessary - a single View will have the
-     * shared element name given by the calling Activity. However, if there are several similar
-     * Views (e.g. in a ListView), the correct shared element must be mapped.
-     * @param sharedElementNames A mapping from the calling Activity's assigned shared element
-     *                           name to a unique shared element name in the View hierarchy.
+     * Sets the Transition that will be used for shared elements after starting a new Activity
+     * before the shared elements are transferred to the called Activity. If the shared elements
+     * must animate during the exit transition, this Transition should be used. Upon completion,
+     * the shared elements may be transferred to the started Activity.
+     * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     * @param transition The Transition to use for shared elements in the launching Window
+     *                   prior to transferring to the launched Activity's Window.
      */
-    public void mapTransitionTargets(Map<String, String> sharedElementNames) {
-    }
+    public void setSharedElementExitTransition(Transition transition) {}
+
+    /**
+     * Returns the Transition to use for shared elements in the launching Window prior
+     * to transferring to the launched Activity's Window.
+     * Requires {@link #FEATURE_CONTENT_TRANSITIONS}.
+     *
+     * @return the Transition to use for shared elements in the launching Window prior
+     * to transferring to the launched Activity's Window.
+     */
+    public Transition getSharedElementExitTransition() { return null; }
+
+    /**
+     * Controls how the transition set in
+     * {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit
+     * transition of the calling Activity. When true, the transition will start as soon as possible.
+     * When false, the transition will wait until the remote exiting transition completes before
+     * starting.
+     * @param allow true to start the enter transition when possible or false to
+     *              wait until the exiting transition completes.
+     */
+    public void setAllowEnterTransitionOverlap(boolean allow) {}
+
+    /**
+     * Returns how the transition set in
+     * {@link #setEnterTransition(android.transition.Transition)} overlaps with the exit
+     * transition of the calling Activity. When true, the transition will start as soon as possible.
+     * When false, the transition will wait until the remote exiting transition completes before
+     * starting.
+     * @return true when the enter transition should start as soon as possible or false to
+     * when it should wait until the exiting transition completes.
+     */
+    public boolean getAllowEnterTransitionOverlap() { return true; }
+
+    /**
+     * Controls how the transition set in
+     * {@link #setExitTransition(android.transition.Transition)} overlaps with the exit
+     * transition of the called Activity when reentering after if finishes. When true,
+     * the transition will start as soon as possible. When false, the transition will wait
+     * until the called Activity's exiting transition completes before starting.
+     * @param allow true to start the transition when possible or false to wait until the
+     *              called Activity's exiting transition completes.
+     */
+    public void setAllowExitTransitionOverlap(boolean allow) {}
+
+    /**
+     * Returns how the transition set in
+     * {@link #setExitTransition(android.transition.Transition)} overlaps with the exit
+     * transition of the called Activity when reentering after if finishes. When true,
+     * the transition will start as soon as possible. When false, the transition will wait
+     * until the called Activity's exiting transition completes before starting.
+     * @return true when the transition should start when possible or false when it should wait
+     * until the called Activity's exiting transition completes.
+     */
+    public boolean getAllowExitTransitionOverlap() { return true; }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/view/WindowAnimationFrameStats.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/view/WindowAnimationFrameStats.aidl
index 0377123..77f544b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/view/WindowAnimationFrameStats.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.view;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable WindowAnimationFrameStats;
diff --git a/core/java/android/view/WindowAnimationFrameStats.java b/core/java/android/view/WindowAnimationFrameStats.java
new file mode 100644
index 0000000..c60b96c
--- /dev/null
+++ b/core/java/android/view/WindowAnimationFrameStats.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window animation frame statistics. For example, a window
+ * animation is usually performed when the application is transitioning from one
+ * activity to another. The frame statistics are a snapshot for the time interval
+ * from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience the system should
+ * run window animations at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the system does not render a frame every refresh
+ * period the user will see irregular window transitions. The time when the frame was
+ * actually presented on the display by calling {@link #getFramePresentedTimeNano(int)}.
+ */
+public final class WindowAnimationFrameStats extends FrameStats implements Parcelable {
+    /**
+     * @hide
+     */
+    public WindowAnimationFrameStats() {
+        /* do nothing */
+    }
+
+    /**
+     * Initializes this isntance.
+     *
+     * @param refreshPeriodNano The display refresh period.
+     * @param framesPresentedTimeNano The presented frame times.
+     *
+     * @hide
+     */
+    public void init(long refreshPeriodNano, long[] framesPresentedTimeNano) {
+        mRefreshPeriodNano = refreshPeriodNano;
+        mFramesPresentedTimeNano = framesPresentedTimeNano;
+    }
+
+    private WindowAnimationFrameStats(Parcel parcel) {
+        mRefreshPeriodNano = parcel.readLong();
+        mFramesPresentedTimeNano = parcel.createLongArray();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeLong(mRefreshPeriodNano);
+        parcel.writeLongArray(mFramesPresentedTimeNano);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("WindowAnimationFrameStats[");
+        builder.append("frameCount:" + getFrameCount());
+        builder.append(", fromTimeNano:" + getStartTimeNano());
+        builder.append(", toTimeNano:" + getEndTimeNano());
+        builder.append(']');
+        return builder.toString();
+    }
+
+    public static final Creator<WindowAnimationFrameStats> CREATOR =
+            new Creator<WindowAnimationFrameStats>() {
+                @Override
+                public WindowAnimationFrameStats createFromParcel(Parcel parcel) {
+                    return new WindowAnimationFrameStats(parcel);
+                }
+
+                @Override
+                public WindowAnimationFrameStats[] newArray(int size) {
+                    return new WindowAnimationFrameStats[size];
+                }
+            };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/android/view/WindowContentFrameStats.aidl
similarity index 62%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/android/view/WindowContentFrameStats.aidl
index 0377123..aa9c2d6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/android/view/WindowContentFrameStats.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2012 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.
  * You may obtain a copy of the License at
  *
- *      http://www.apache.org/licenses/LICENSE-2.0
+ *     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,
@@ -14,10 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package android.view;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
-}
+parcelable WindowContentFrameStats;
diff --git a/core/java/android/view/WindowContentFrameStats.java b/core/java/android/view/WindowContentFrameStats.java
new file mode 100644
index 0000000..c6da2fb
--- /dev/null
+++ b/core/java/android/view/WindowContentFrameStats.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * This class contains window content frame statistics. For example, a window content
+ * is rendred in frames when a view is scrolled. The frame statistics are a snapshot
+ * for the time interval from {@link #getStartTimeNano()} to {@link #getEndTimeNano()}.
+ * <p>
+ * The key idea is that in order to provide a smooth user experience an application
+ * has to draw a frame at a specific time interval obtained by calling {@link
+ * #getRefreshPeriodNano()}. If the application does not render a frame every refresh
+ * period the user will see irregular UI transitions.
+ * </p>
+ * <p>
+ * An application posts a frame for presentation by synchronously rendering its contents
+ * in a buffer which is then posted or posting a buffer to which the application is
+ * asychronously rendering the content via GL. After the frame is posted and rendered
+ * (potentially asynchronosly) it is presented to the user. The time a frame was posted
+ * can be obtained via {@link #getFramePostedTimeNano(int)}, the time a frame content
+ * was rendered and ready for dsiplay (GL case) via {@link #getFrameReadyTimeNano(int)},
+ * and the time a frame was presented on the screen via {@link #getFramePresentedTimeNano(int)}.
+ * </p>
+ */
+public final class WindowContentFrameStats extends FrameStats implements Parcelable {
+    private long[] mFramesPostedTimeNano;
+    private long[] mFramesReadyTimeNano;
+
+    /**
+     * @hide
+     */
+    public WindowContentFrameStats() {
+        /* do nothing */
+    }
+
+    /**
+     * Initializes this isntance.
+     *
+     * @param refreshPeriodNano The display refresh period.
+     * @param framesPostedTimeNano The times in milliseconds for when the frame contents were posted.
+     * @param framesPresentedTimeNano The times in milliseconds for when the frame contents were presented.
+     * @param framesReadyTimeNano The times in milliseconds for when the frame contents were ready to be presented.
+     *
+     * @hide
+     */
+    public void init(long refreshPeriodNano, long[] framesPostedTimeNano,
+            long[] framesPresentedTimeNano, long[] framesReadyTimeNano) {
+        mRefreshPeriodNano = refreshPeriodNano;
+        mFramesPostedTimeNano = framesPostedTimeNano;
+        mFramesPresentedTimeNano = framesPresentedTimeNano;
+        mFramesReadyTimeNano = framesReadyTimeNano;
+    }
+
+    private WindowContentFrameStats(Parcel parcel) {
+        mRefreshPeriodNano = parcel.readLong();
+        mFramesPostedTimeNano = parcel.createLongArray();
+        mFramesPresentedTimeNano = parcel.createLongArray();
+        mFramesReadyTimeNano = parcel.createLongArray();
+    }
+
+    /**
+     * Get the time a frame at a given index was posted by the producer (e.g. the application).
+     * It is either explicitly set or defaulted to the time when the render buffer was posted.
+     * <p>
+     * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+     * asynchronously in GL. To get the time the frame content was completely rendered and
+     * ready to display call {@link #getFrameReadyTimeNano(int)}.
+     * </p>
+     *
+     * @param index The frame index.
+     * @return The posted time in nanoseconds.
+     */
+    public long getFramePostedTimeNano(int index) {
+        if (mFramesPostedTimeNano == null) {
+            throw new IndexOutOfBoundsException();
+        }
+        return mFramesPostedTimeNano[index];
+    }
+
+    /**
+     * Get the time a frame at a given index was ready for presentation.
+     * <p>
+     * <strong>Note:</strong> A frame can be posted and still it contents being rendered
+     * asynchronously in GL. In such a case this is the time when the frame contents were
+     * completely rendered.
+     * </p>
+     *
+     * @param index The frame index.
+     * @return The ready time in nanoseconds or {@link #UNDEFINED_TIME_NANO}
+     *         if the frame is not ready yet.
+     */
+    public long getFrameReadyTimeNano(int index) {
+        if (mFramesReadyTimeNano == null) {
+            throw new IndexOutOfBoundsException();
+        }
+        return mFramesReadyTimeNano[index];
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel parcel, int flags) {
+        parcel.writeLong(mRefreshPeriodNano);
+        parcel.writeLongArray(mFramesPostedTimeNano);
+        parcel.writeLongArray(mFramesPresentedTimeNano);
+        parcel.writeLongArray(mFramesReadyTimeNano);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("WindowContentFrameStats[");
+        builder.append("frameCount:" + getFrameCount());
+        builder.append(", fromTimeNano:" + getStartTimeNano());
+        builder.append(", toTimeNano:" + getEndTimeNano());
+        builder.append(']');
+        return builder.toString();
+    }
+
+    public static final Parcelable.Creator<WindowContentFrameStats> CREATOR =
+            new Creator<WindowContentFrameStats>() {
+                @Override
+                public WindowContentFrameStats createFromParcel(Parcel parcel) {
+                    return new WindowContentFrameStats(parcel);
+                }
+
+                @Override
+                public WindowContentFrameStats[] newArray(int size) {
+                    return new WindowContentFrameStats[size];
+                }
+            };
+}
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index cdfcb43..2160efe 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -33,6 +33,7 @@
     private Rect mSystemWindowInsets;
     private Rect mWindowDecorInsets;
     private Rect mTempRect;
+    private boolean mIsRound;
 
     private static final Rect EMPTY_RECT = new Rect(0, 0, 0, 0);
 
@@ -46,8 +47,19 @@
 
     /** @hide */
     public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets) {
+        this(systemWindowInsets, windowDecorInsets, false);
+    }
+
+    /** @hide */
+    public WindowInsets(Rect systemWindowInsets, boolean isRound) {
+        this(systemWindowInsets, EMPTY_RECT, isRound);
+    }
+
+    /** @hide */
+    public WindowInsets(Rect systemWindowInsets, Rect windowDecorInsets, boolean isRound) {
         mSystemWindowInsets = systemWindowInsets;
         mWindowDecorInsets = windowDecorInsets;
+        mIsRound = isRound;
     }
 
     /**
@@ -58,12 +70,12 @@
     public WindowInsets(WindowInsets src) {
         mSystemWindowInsets = src.mSystemWindowInsets;
         mWindowDecorInsets = src.mWindowDecorInsets;
+        mIsRound = src.mIsRound;
     }
 
     /** @hide */
     public WindowInsets(Rect systemWindowInsets) {
-        mSystemWindowInsets = systemWindowInsets;
-        mWindowDecorInsets = EMPTY_RECT;
+        this(systemWindowInsets, EMPTY_RECT);
     }
 
     /**
@@ -220,6 +232,20 @@
         return hasSystemWindowInsets() || hasWindowDecorInsets();
     }
 
+    /**
+     * Returns true if the associated window has a round shape.
+     *
+     * <p>A round window's left, top, right and bottom edges reach all the way to the
+     * associated edges of the window but the corners may not be visible. Views responding
+     * to round insets should take care to not lay out critical elements within the corners
+     * where they may not be accessible.</p>
+     *
+     * @return True if the window is round
+     */
+    public boolean isRound() {
+        return mIsRound;
+    }
+
     public WindowInsets cloneWithSystemWindowInsetsConsumed() {
         final WindowInsets result = new WindowInsets(this);
         result.mSystemWindowInsets = new Rect(0, 0, 0, 0);
@@ -273,6 +299,6 @@
     @Override
     public String toString() {
         return "WindowInsets{systemWindowInsets=" + mSystemWindowInsets + " windowDecorInsets=" +
-                mWindowDecorInsets + "}";
+                mWindowDecorInsets + (isRound() ? "round}" : "}");
     }
 }
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 53a4c0d0..032a82f 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -49,7 +49,7 @@
 public interface WindowManager extends ViewManager {
     /**
      * Exception that is thrown when trying to add view whose
-     * {@link WindowManager.LayoutParams} {@link WindowManager.LayoutParams#token}
+     * {@link LayoutParams} {@link LayoutParams#token}
      * is invalid.
      */
     public static class BadTokenException extends RuntimeException {
@@ -173,7 +173,6 @@
          * @see #TYPE_SEARCH_BAR
          * @see #TYPE_PHONE
          * @see #TYPE_SYSTEM_ALERT
-         * @see #TYPE_KEYGUARD
          * @see #TYPE_TOAST
          * @see #TYPE_SYSTEM_OVERLAY
          * @see #TYPE_PRIORITY_PHONE
@@ -197,7 +196,6 @@
             @ViewDebug.IntToString(from = TYPE_SEARCH_BAR, to = "TYPE_SEARCH_BAR"),
             @ViewDebug.IntToString(from = TYPE_PHONE, to = "TYPE_PHONE"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ALERT, to = "TYPE_SYSTEM_ALERT"),
-            @ViewDebug.IntToString(from = TYPE_KEYGUARD, to = "TYPE_KEYGUARD"),
             @ViewDebug.IntToString(from = TYPE_TOAST, to = "TYPE_TOAST"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_OVERLAY, to = "TYPE_SYSTEM_OVERLAY"),
             @ViewDebug.IntToString(from = TYPE_PRIORITY_PHONE, to = "TYPE_PRIORITY_PHONE"),
@@ -341,13 +339,13 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
-        
+
         /**
          * Window type: keyguard window.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
-        
+
         /**
          * Window type: transient notifications.
          * In multiuser systems shows only on the owning user's window.
@@ -610,7 +608,10 @@
          * screen is pressed, you will receive this first touch event.  Usually
          * the first touch event is consumed by the system since the user can
          * not see what they are pressing on.
+         *
+         * @deprecated This flag has no effect.
          */
+        @Deprecated
         public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
         
         /** Window flag: as long as this window is visible to the user, keep
@@ -913,7 +914,6 @@
          */
         public static final int FLAG_NEEDS_MENU_KEY = 0x40000000;
 
-
         /**
          * Various behavioral options/flags.  Default is none.
          * 
@@ -1087,6 +1087,14 @@
         public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200;
 
         /**
+         * Flag whether the current window is a keyguard window, meaning that it will hide all other
+         * windows behind it except for windows with flag {@link #FLAG_SHOW_WHEN_LOCKED} set.
+         * Further, this can only be set by {@link LayoutParams#TYPE_STATUS_BAR}.
+         * {@hide}
+         */
+        public static final int PRIVATE_FLAG_KEYGUARD = 0x00000400;
+
+        /**
          * Control flags that are private to the platform.
          * @hide
          */
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index bd203c8..c524611 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -76,22 +76,14 @@
 public interface WindowManagerPolicy {
     // Policy flags.  These flags are also defined in frameworks/base/include/ui/Input.h.
     public final static int FLAG_WAKE = 0x00000001;
-    public final static int FLAG_WAKE_DROPPED = 0x00000002;
-    public final static int FLAG_SHIFT = 0x00000004;
-    public final static int FLAG_CAPS_LOCK = 0x00000008;
-    public final static int FLAG_ALT = 0x00000010;
-    public final static int FLAG_ALT_GR = 0x00000020;
-    public final static int FLAG_MENU = 0x00000040;
-    public final static int FLAG_LAUNCHER = 0x00000080;
-    public final static int FLAG_VIRTUAL = 0x00000100;
+    public final static int FLAG_VIRTUAL = 0x00000002;
 
     public final static int FLAG_INJECTED = 0x01000000;
     public final static int FLAG_TRUSTED = 0x02000000;
     public final static int FLAG_FILTERED = 0x04000000;
     public final static int FLAG_DISABLE_KEY_REPEAT = 0x08000000;
 
-    public final static int FLAG_WOKE_HERE = 0x10000000;
-    public final static int FLAG_BRIGHT_HERE = 0x20000000;
+    public final static int FLAG_INTERACTIVE = 0x20000000;
     public final static int FLAG_PASS_TO_USER = 0x40000000;
 
     // Flags used for indicating whether the internal and/or external input devices
@@ -744,11 +736,10 @@
      * because it's the most fragile.
      * @param event The key event.
      * @param policyFlags The policy flags associated with the key.
-     * @param isScreenOn True if the screen is already on
      *
      * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
      */
-    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
     /**
      * Called from the input reader thread before a motion is enqueued when the screen is off.
@@ -761,7 +752,7 @@
      *
      * @return Actions flags: may be {@link #ACTION_PASS_TO_USER}.
      */
-    public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
+    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
 
     /**
      * Called from the input dispatcher thread before a key is dispatched to a window.
@@ -1007,6 +998,14 @@
     public void dismissKeyguardLw();
 
     /**
+     * Ask the policy whether the Keyguard has drawn. If the Keyguard is disabled, this method
+     * returns true as soon as we know that Keyguard is disabled.
+     *
+     * @return true if the keyguard has drawn.
+     */
+    public boolean isKeyguardDrawnLw();
+
+    /**
      * Given an orientation constant, returns the appropriate surface rotation,
      * taking into account sensors, docking mode, rotation lock, and other factors.
      *
diff --git a/core/java/android/view/accessibility/AccessibilityInteractionClient.java b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
index 4dd8dcb..5b9372d 100644
--- a/core/java/android/view/accessibility/AccessibilityInteractionClient.java
+++ b/core/java/android/view/accessibility/AccessibilityInteractionClient.java
@@ -163,6 +163,19 @@
     }
 
     /**
+     * Gets the root {@link AccessibilityNodeInfo} in a given window.
+     *
+     * @param connectionId The id of a connection for interacting with the system.
+     * @param windowId The window id.
+     * @return The root {@link AccessibilityNodeInfo} if found, null otherwise.
+     */
+    public AccessibilityNodeInfo getRootInWindow(int connectionId, int windowId) {
+        return findAccessibilityNodeInfoByAccessibilityId(connectionId, windowId,
+                AccessibilityNodeInfo.ROOT_NODE_ID, false,
+                AccessibilityNodeInfo.FLAG_PREFETCH_DESCENDANTS);
+    }
+
+    /**
      * Gets the info for a window.
      *
      * @param connectionId The id of a connection for interacting with the system.
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index a6904f7..9d10930 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -77,6 +77,9 @@
     public static final int ACTIVE_WINDOW_ID = UNDEFINED_ITEM_ID;
 
     /** @hide */
+    public static final int ANY_WINDOW_ID = -2;
+
+    /** @hide */
     public static final int FLAG_PREFETCH_PREDECESSORS = 0x00000001;
 
     /** @hide */
diff --git a/core/java/android/view/accessibility/IAccessibilityManager.aidl b/core/java/android/view/accessibility/IAccessibilityManager.aidl
index fe3e5c6..b6570cc 100644
--- a/core/java/android/view/accessibility/IAccessibilityManager.aidl
+++ b/core/java/android/view/accessibility/IAccessibilityManager.aidl
@@ -57,4 +57,6 @@
 
     void temporaryEnableAccessibilityStateUntilKeyguardRemoved(in ComponentName service,
             boolean touchExplorationEnabled);
+
+    IBinder getWindowToken(int windowId);
 }
diff --git a/core/java/android/view/inputmethod/InputMethodInfo.java b/core/java/android/view/inputmethod/InputMethodInfo.java
index f8160c8..bc2d7ec 100644
--- a/core/java/android/view/inputmethod/InputMethodInfo.java
+++ b/core/java/android/view/inputmethod/InputMethodInfo.java
@@ -259,7 +259,7 @@
     public InputMethodInfo(String packageName, String className,
             CharSequence label, String settingsActivity) {
         this(buildDummyResolveInfo(packageName, className, label), false, settingsActivity, null,
-                0, false);
+                0, false /* forceDefault */, true /* supportsSwitchingToNextInputMethod */);
     }
 
     /**
@@ -269,6 +269,17 @@
     public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
             String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
             boolean forceDefault) {
+        this(ri, isAuxIme, settingsActivity, subtypes, isDefaultResId,
+                forceDefault, true /* supportsSwitchingToNextInputMethod */);
+    }
+
+    /**
+     * Temporary API for creating a built-in input method for test.
+     * @hide
+     */
+    public InputMethodInfo(ResolveInfo ri, boolean isAuxIme,
+            String settingsActivity, List<InputMethodSubtype> subtypes, int isDefaultResId,
+            boolean forceDefault, boolean supportsSwitchingToNextInputMethod) {
         final ServiceInfo si = ri.serviceInfo;
         mService = ri;
         mId = new ComponentName(si.packageName, si.name).flattenToShortString();
@@ -277,7 +288,7 @@
         mIsAuxIme = isAuxIme;
         mSubtypes = new InputMethodSubtypeArray(subtypes);
         mForceDefault = forceDefault;
-        mSupportsSwitchingToNextInputMethod = true;
+        mSupportsSwitchingToNextInputMethod = supportsSwitchingToNextInputMethod;
     }
 
     private static ResolveInfo buildDummyResolveInfo(String packageName, String className,
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index e3bd9fd..0227873 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -317,6 +317,10 @@
     int mCursorSelEnd;
     int mCursorCandStart;
     int mCursorCandEnd;
+    /**
+     * The buffer to retrieve the view location in screen coordinates in {@link #updateCursor}.
+     */
+    private final int[] mViewTopLeft = new int[2];
 
     // -----------------------------------------------------------
     
@@ -1487,12 +1491,26 @@
             return false;
         }
         synchronized (mH) {
-            return mCursorAnchorMonitorMode ==
-                    InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT;
+            return (mCursorAnchorMonitorMode &
+                    InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
         }
     }
 
     /**
+     * Returns true if the current input method wants to receive the cursor rectangle in
+     * screen coordinates rather than local coordinates in the attached view.
+     *
+     * @hide
+     */
+    public boolean usesScreenCoordinatesForCursorLocked() {
+        // {@link InputMethodService#CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT} also means
+        // that {@link InputMethodService#onUpdateCursor} should provide the cursor rectangle
+        // in screen coordinates rather than local coordinates.
+        return (mCursorAnchorMonitorMode &
+                InputMethodService.CURSOR_ANCHOR_MONITOR_MODE_CURSOR_RECT) != 0;
+    }
+
+    /**
      * Set cursor/anchor monitor mode via {@link com.android.server.InputMethodManagerService}.
      * This is an internal method for {@link android.inputmethodservice.InputMethodService} and
      * should never be used from IMEs and applications.
@@ -1518,15 +1536,18 @@
                     || mCurrentTextBoxAttribute == null || mCurMethod == null) {
                 return;
             }
-            
             mTmpCursorRect.set(left, top, right, bottom);
             if (!mCursorRect.equals(mTmpCursorRect)) {
                 if (DEBUG) Log.d(TAG, "updateCursor");
 
                 try {
                     if (DEBUG) Log.v(TAG, "CURSOR CHANGE: " + mCurMethod);
-                    mCurMethod.updateCursor(mTmpCursorRect);
                     mCursorRect.set(mTmpCursorRect);
+                    if (usesScreenCoordinatesForCursorLocked()) {
+                        view.getLocationOnScreen(mViewTopLeft);
+                        mTmpCursorRect.offset(mViewTopLeft[0], mViewTopLeft[1]);
+                    }
+                    mCurMethod.updateCursor(mTmpCursorRect);
                 } catch (RemoteException e) {
                     Log.w(TAG, "IME died: " + mCurId, e);
                 }
diff --git a/core/java/android/webkit/ClientCertRequest.java b/core/java/android/webkit/ClientCertRequest.java
new file mode 100644
index 0000000..8951786
--- /dev/null
+++ b/core/java/android/webkit/ClientCertRequest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.security.Principal;
+import java.security.PrivateKey;
+import java.security.cert.X509Certificate;
+
+/**
+ * ClientCertRequest: The user receives an instance of this class as
+ * a parameter of {@link WebViewClient#onReceivedClientCertRequest}.
+ * The request includes the parameters to choose the client certificate,
+ * such as the host name and the port number requesting the cert, the acceptable
+ * key types and the principals.
+ *
+ * The user should call one of the interface methods to indicate how to deal
+ * with the client certificate request. All methods should be called on
+ * UI thread.
+ *
+ * WebView caches the {@link #proceed} and {@link #cancel} responses in memory
+ * and uses them to handle future client certificate requests for the same
+ * host/port pair. The user can clear the cached data using
+ * {@link WebView#clearClientCertPreferences}.
+ *
+ * TODO(sgurun) unhide
+ * @hide
+ */
+public interface ClientCertRequest {
+    /**
+     * Returns the acceptable types of asymmetric keys (can be null).
+     */
+    public String[] getKeyTypes();
+
+    /**
+     * Returns the acceptable certificate issuers for the certificate
+     *            matching the private key (can be null).
+     */
+    public Principal[] getPrincipals();
+
+    /**
+     * Returns the host name of the server requesting the certificate.
+     */
+    public String getHost();
+
+    /**
+     * Returns the port number of the server requesting the certificate.
+     */
+    public int getPort();
+
+    /**
+     * Proceed with the specified private key and client certificate chain.
+     * Remember the user's positive choice and use it for future requests.
+     */
+    public void proceed(PrivateKey privateKey, X509Certificate[] chain);
+
+    /**
+     * Ignore the request for now. Do not remember user's choice.
+     */
+    public void ignore();
+
+    /**
+     * Cancel this request. Remember the user's choice and use it for
+     * future requests.
+     */
+    public void cancel();
+}
diff --git a/core/java/android/webkit/PermissionRequest.java b/core/java/android/webkit/PermissionRequest.java
new file mode 100644
index 0000000..2f8850b
--- /dev/null
+++ b/core/java/android/webkit/PermissionRequest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import android.net.Uri;
+
+/**
+ * This class wraps a permission request, and is used to request permission for
+ * the web content to access the resources.
+ *
+ * Either {@link #grant(long) grant()} or {@link #deny()} must be called to response the
+ * request, otherwise, {@link WebChromeClient#onPermissionRequest(PermissionRequest)} will
+ * not be invoked again if there is other permission request in this WebView.
+ *
+ * @hide
+ */
+public interface PermissionRequest {
+    /**
+     * Resource belongs to geolocation service.
+     */
+    public final static long RESOURCE_GEOLOCATION = 1 << 0;
+    /**
+     * Resource belongs to video capture device, like camera.
+     */
+    public final static long RESOURCE_VIDEO_CAPTURE = 1 << 1;
+    /**
+     * Resource belongs to audio capture device, like microphone.
+     */
+    public final static long RESOURCE_AUDIO_CAPTURE = 1 << 2;
+
+    /**
+     * @return the origin of web content which attempt to access the restricted
+     *         resources.
+     */
+    public Uri getOrigin();
+
+    /**
+     * @return a bit mask of resources the web content wants to access.
+     */
+    public long getResources();
+
+    /**
+     * Call this method to grant origin the permission to access the given resources.
+     * The granted permission is only valid for this WebView.
+     *
+     * @param resources the resources granted to be accessed by origin, to grant
+     *        request, the requested resources returned by {@link #getResources()}
+     *        must be equals or a subset of granted resources.
+     *        This parameter is designed to avoid granting permission by accident
+     *        especially when new resources are requested by web content.
+     *        Calling grant(getResources()) has security issue, the new permission
+     *        will be granted without being noticed.
+     */
+    public void grant(long resources);
+
+    /**
+     * Call this method to deny the request.
+     */
+    public void deny();
+}
diff --git a/core/java/android/webkit/WebChromeClient.java b/core/java/android/webkit/WebChromeClient.java
index aa57423..60cba86 100644
--- a/core/java/android/webkit/WebChromeClient.java
+++ b/core/java/android/webkit/WebChromeClient.java
@@ -296,6 +296,30 @@
     public void onGeolocationPermissionsHidePrompt() {}
 
     /**
+     * Notify the host application that web content is requesting permission to
+     * access the specified resources and the permission currently isn't granted
+     * or denied. The host application must invoke {@link PermissionRequest#grant(long)}
+     * or {@link PermissionRequest#deny()}.
+     *
+     * If this method isn't overridden, the permission is denied.
+     *
+     * @param request the PermissionRequest from current web content.
+     * @hide
+     */
+    public void onPermissionRequest(PermissionRequest request) {
+        request.deny();
+    }
+
+    /**
+     * Notify the host application that the given permission request
+     * has been canceled. Any related UI should therefore be hidden.
+     *
+     * @param request the PermissionRequest need be canceled.
+     * @hide
+     */
+    public void onPermissionRequestCanceled(PermissionRequest request) {}
+
+    /**
      * Tell the client that a JavaScript execution timeout has occured. And the
      * client may decide whether or not to interrupt the execution. If the
      * client returns true, the JavaScript will be interrupted. If the client
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 81d36a4..efb246a 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -25,6 +25,7 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.Build;
 import android.os.Bundle;
@@ -484,7 +485,7 @@
      * @param privateBrowsing whether this WebView will be initialized in
      *                        private mode
      *
-     * @deprecated Private browsing is no longer supported directly via 
+     * @deprecated Private browsing is no longer supported directly via
      * WebView and will be removed in a future release. Prefer using
      * {@link WebSettings}, {@link WebViewDatabase}, {@link CookieManager}
      * and {@link WebStorage} for fine-grained control of privacy data.
@@ -700,7 +701,7 @@
      */
     @Deprecated
     public static void enablePlatformNotifications() {
-        getFactory().getStatics().setPlatformNotificationsEnabled(true);
+        // noop
     }
 
     /**
@@ -712,7 +713,7 @@
      */
     @Deprecated
     public static void disablePlatformNotifications() {
-        getFactory().getStatics().setPlatformNotificationsEnabled(false);
+        // noop
     }
 
     /**
@@ -1135,9 +1136,18 @@
     }
 
     /**
+     * @deprecated Use {@link #createPrintDocumentAdapter(String)} which requires user
+     *             to provide a print document name.
+     */
+    @Deprecated
+    public PrintDocumentAdapter createPrintDocumentAdapter() {
+        checkThread();
+        if (DebugFlags.TRACE_API) Log.d(LOGTAG, "createPrintDocumentAdapter");
+        return mProvider.createPrintDocumentAdapter("default");
+    }
+
+    /**
      * Creates a PrintDocumentAdapter that provides the content of this Webview for printing.
-     * Only supported for API levels
-     * {@link android.os.Build.VERSION_CODES#KITKAT} and above.
      *
      * The adapter works by converting the Webview contents to a PDF stream. The Webview cannot
      * be drawn during the conversion process - any such draws are undefined. It is recommended
@@ -1145,11 +1155,14 @@
      * temporarily hide a visible WebView by using a custom PrintDocumentAdapter instance
      * wrapped around the object returned and observing the onStart and onFinish methods. See
      * {@link android.print.PrintDocumentAdapter} for more information.
+     *
+     * @param documentName  The user-facing name of the printed document. See
+     *                      {@link android.print.PrintDocumentInfo}
      */
-    public PrintDocumentAdapter createPrintDocumentAdapter() {
+    public PrintDocumentAdapter createPrintDocumentAdapter(String documentName) {
         checkThread();
         if (DebugFlags.TRACE_API) Log.d(LOGTAG, "createPrintDocumentAdapter");
-        return mProvider.createPrintDocumentAdapter();
+        return mProvider.createPrintDocumentAdapter(documentName);
     }
 
     /**
@@ -1463,6 +1476,24 @@
     }
 
     /**
+     * Clears the client certificate preferences table stored in response
+     * to proceeding/cancelling client cert requests. Note that webview
+     * automatically clears these preferences when it receives a
+     * {@link KeyChain.ACTION_STORAGE_CHANGED}
+     *
+     * @param resultCallback A callback to be invoked when client certs are cleared.
+     *                       The embedder can pass null if not interested in the callback.
+     *
+     * TODO(sgurun) unhide
+     * @hide
+     */
+    public void clearClientCertPreferences(ValueCallback<Void> resultCallback) {
+        checkThread();
+        if (DebugFlags.TRACE_API) Log.d(LOGTAG, "clearClientCertPreferences");
+        mProvider.clearClientCertPreferences(resultCallback);
+    }
+
+    /**
      * Gets the WebBackForwardList for this WebView. This contains the
      * back/forward list for use in querying each item in the history stack.
      * This is a copy of the private WebBackForwardList so it contains only a
@@ -1579,6 +1610,8 @@
      * @return the address, or if no address is found, null
      */
     public static String findAddress(String addr) {
+        // TODO: Rewrite this in Java so it is not needed to start up chromium
+        // Could also be deprecated
         return getFactory().getStatics().findAddress(addr);
     }
 
@@ -1640,6 +1673,21 @@
     }
 
     /**
+     * Preauthorize the given origin to access resources.
+     * This authorization only valid for this WebView instance life cycle and
+     * will not retained.
+     *
+     * @param origin the origin authorized to access resources
+     * @param resources the resource authorized to be accessed by origin.
+     *
+     * @hide
+     */
+    public void preauthorizePermission(Uri origin, long resources) {
+        checkThread();
+        mProvider.preauthorizePermission(origin, resources);
+    }
+
+    /**
      * Sets the Picture listener. This is an interface used to receive
      * notifications of a new Picture.
      *
@@ -1691,6 +1739,9 @@
      * thread of this WebView. Care is therefore required to maintain thread
      * safety.</li>
      * <li> The Java object's fields are not accessible.</li>
+     * <li> For applications targeted to API level {@link android.os.Build.VERSION_CODES#L}
+     * and above, methods of injected Java objects are enumerable from
+     * JavaScript.</li>
      * </ul>
      *
      * @param object the Java object to inject into this WebView's JavaScript
diff --git a/core/java/android/webkit/WebViewClient.java b/core/java/android/webkit/WebViewClient.java
index e8974c6..688c251 100644
--- a/core/java/android/webkit/WebViewClient.java
+++ b/core/java/android/webkit/WebViewClient.java
@@ -22,6 +22,8 @@
 import android.view.KeyEvent;
 import android.view.ViewRootImpl;
 
+import java.security.Principal;
+
 public class WebViewClient {
 
     /**
@@ -205,6 +207,30 @@
     }
 
     /**
+     * Notify the host application to handle a SSL client certificate
+     * request. The host application is responsible for showing the UI
+     * if desired and providing the keys. There are three ways to
+     * respond: proceed(), cancel() or ignore(). Webview remembers the
+     * response if proceed() or cancel() is called and does not
+     * call onReceivedClientCertRequest() again for the same host and port
+     * pair. Webview does not remember the response if ignore() is called.
+     *
+     * This method is called on the UI thread. During the callback, the
+     * connection is suspended.
+     *
+     * The default behavior is to cancel, returning no client certificate.
+     *
+     * @param view The WebView that is initiating the callback
+     * @param request An instance of a {@link ClientCertRequest}
+     *
+     * TODO(sgurun) unhide
+     * @hide
+     */
+    public void onReceivedClientCertRequest(WebView view, ClientCertRequest request) {
+        request.cancel();
+    }
+
+    /**
      * Notifies the host application that the WebView received an HTTP
      * authentication request. The host application can use the supplied
      * {@link HttpAuthHandler} to set the WebView's response to the request.
diff --git a/core/java/android/webkit/WebViewProvider.java b/core/java/android/webkit/WebViewProvider.java
index 696aad4..efa5497 100644
--- a/core/java/android/webkit/WebViewProvider.java
+++ b/core/java/android/webkit/WebViewProvider.java
@@ -23,6 +23,7 @@
 import android.graphics.Picture;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.net.Uri;
 import android.net.http.SslCertificate;
 import android.os.Bundle;
 import android.os.Message;
@@ -147,7 +148,7 @@
 
     public Picture capturePicture();
 
-    public PrintDocumentAdapter createPrintDocumentAdapter();
+    public PrintDocumentAdapter createPrintDocumentAdapter(String documentName);
 
     public float getScale();
 
@@ -197,6 +198,8 @@
 
     public void clearSslPreferences();
 
+    public void clearClientCertPreferences(ValueCallback<Void> resultCallback);
+
     public WebBackForwardList copyBackForwardList();
 
     public void setFindListener(WebView.FindListener listener);
@@ -245,6 +248,8 @@
 
     public View findHierarchyView(String className, int hashCode);
 
+    public void preauthorizePermission(Uri origin, long resources);
+
     //-------------------------------------------------------------------------
     // Provider internal methods
     //-------------------------------------------------------------------------
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 96a2ab5..becda67 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -543,7 +543,7 @@
     /**
      * The last CheckForTap runnable we posted, if any
      */
-    private Runnable mPendingCheckForTap;
+    private CheckForTap mPendingCheckForTap;
 
     /**
      * The last CheckForKeyLongPress runnable we posted, if any
@@ -2126,7 +2126,9 @@
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         super.onLayout(changed, l, t, r, b);
+
         mInLayout = true;
+
         final int childCount = getChildCount();
         if (changed) {
             for (int i = 0; i < childCount; i++) {
@@ -3185,7 +3187,10 @@
         return INVALID_ROW_ID;
     }
 
-    final class CheckForTap implements Runnable {
+    private final class CheckForTap implements Runnable {
+        float x;
+        float y;
+
         @Override
         public void run() {
             if (mTouchMode == TOUCH_MODE_DOWN) {
@@ -3205,7 +3210,7 @@
                         final boolean longClickable = isLongClickable();
 
                         if (mSelector != null) {
-                            Drawable d = mSelector.getCurrent();
+                            final Drawable d = mSelector.getCurrent();
                             if (d != null && d instanceof TransitionDrawable) {
                                 if (longClickable) {
                                     ((TransitionDrawable) d).startTransition(longPressTimeout);
@@ -3213,6 +3218,9 @@
                                     ((TransitionDrawable) d).resetTransition();
                                 }
                             }
+                            if (d.supportsHotspots()) {
+                                d.setHotspot(R.attr.state_pressed, x, y);
+                            }
                         }
 
                         if (longClickable) {
@@ -3596,6 +3604,8 @@
                         mPendingCheckForTap = new CheckForTap();
                     }
 
+                    mPendingCheckForTap.x = ev.getX();
+                    mPendingCheckForTap.y = ev.getY();
                     postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
                 }
             }
@@ -3705,6 +3715,9 @@
                                 if (d != null && d instanceof TransitionDrawable) {
                                     ((TransitionDrawable) d).resetTransition();
                                 }
+                                if (mSelector.supportsHotspots()) {
+                                    mSelector.setHotspot(R.attr.state_pressed, x, ev.getY());
+                                }
                             }
                             if (mTouchModeReset != null) {
                                 removeCallbacks(mTouchModeReset);
@@ -3716,6 +3729,9 @@
                                     mTouchMode = TOUCH_MODE_REST;
                                     child.setPressed(false);
                                     setPressed(false);
+                                    if (mSelector != null && mSelector.supportsHotspots()) {
+                                        mSelector.removeHotspot(R.attr.state_pressed);
+                                    }
                                     if (!mDataChanged && !mIsDetaching && isAttachedToWindow()) {
                                         performClick.run();
                                     }
@@ -7167,7 +7183,7 @@
 
             final int itemCount = getCount();
             final int clampedPosition = MathUtils.constrain(targetPosition, 0, itemCount - 1);
-            final int clampedBoundPosition = MathUtils.constrain(boundPosition, 0, itemCount - 1);
+            final int clampedBoundPosition = MathUtils.constrain(boundPosition, -1, itemCount - 1);
             final int firstPosition = getFirstVisiblePosition();
             final int lastPosition = firstPosition + getChildCount();
             final int targetRow = getRowForPosition(clampedPosition);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 438a9da..225cd6d 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -29,6 +29,8 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.internal.R;
+
 public abstract class AbsSeekBar extends ProgressBar {
     private Drawable mThumb;
     private int mThumbOffset;
@@ -289,28 +291,39 @@
      */
     private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
         int available = w - mPaddingLeft - mPaddingRight;
-        int thumbWidth = thumb.getIntrinsicWidth();
-        int thumbHeight = thumb.getIntrinsicHeight();
+        final int thumbWidth = thumb.getIntrinsicWidth();
+        final int thumbHeight = thumb.getIntrinsicHeight();
         available -= thumbWidth;
 
         // The extra space for the thumb to move on the track
         available += mThumbOffset * 2;
 
-        int thumbPos = (int) (scale * available + 0.5f);
+        final int thumbPos = (int) (scale * available + 0.5f);
 
-        int topBound, bottomBound;
+        final int top, bottom;
         if (gap == Integer.MIN_VALUE) {
-            Rect oldBounds = thumb.getBounds();
-            topBound = oldBounds.top;
-            bottomBound = oldBounds.bottom;
+            final Rect oldBounds = thumb.getBounds();
+            top = oldBounds.top;
+            bottom = oldBounds.bottom;
         } else {
-            topBound = gap;
-            bottomBound = gap + thumbHeight;
+            top = gap;
+            bottom = gap + thumbHeight;
         }
-        
-        // Canvas will be translated, so 0,0 is where we start drawing
+
         final int left = (isLayoutRtl() && mMirrorForRtl) ? available - thumbPos : thumbPos;
-        thumb.setBounds(left, topBound, left + thumbWidth, bottomBound);
+        final int right = left + thumbWidth;
+
+        final Drawable background = getBackground();
+        if (background != null && background.supportsHotspots()) {
+            final Rect bounds = mThumb.getBounds();
+            final int offsetX = mPaddingLeft - mThumbOffset;
+            final int offsetY = mPaddingTop;
+            background.setHotspotBounds(left + offsetX, bounds.top + offsetY,
+                    right + offsetX, bounds.bottom + offsetY);
+        }
+
+        // Canvas will be translated, so 0,0 is where we start drawing
+        thumb.setBounds(left, top, right, bottom);
     }
 
     /**
@@ -328,6 +341,7 @@
     @Override
     protected synchronized void onDraw(Canvas canvas) {
         super.onDraw(canvas);
+
         if (mThumb != null) {
             canvas.save();
             // Translate the padding. For the x, we need to allow the thumb to
@@ -424,10 +438,24 @@
         return true;
     }
 
+    private void setHotspot(int id, float x, float y) {
+        final Drawable bg = getBackground();
+        if (bg != null && bg.supportsHotspots()) {
+            bg.setHotspot(id, x, y);
+        }
+    }
+
+    private void clearHotspot(int id) {
+        final Drawable bg = getBackground();
+        if (bg != null && bg.supportsHotspots()) {
+            bg.removeHotspot(id);
+        }
+    }
+
     private void trackTouchEvent(MotionEvent event) {
         final int width = getWidth();
         final int available = width - mPaddingLeft - mPaddingRight;
-        int x = (int)event.getX();
+        final int x = (int) event.getX();
         float scale;
         float progress = 0;
         if (isLayoutRtl() && mMirrorForRtl) {
@@ -451,7 +479,8 @@
         }
         final int max = getMax();
         progress += scale * max;
-        
+
+        setHotspot(R.attr.state_pressed, x, (int) event.getY());
         setProgress((int) progress, true);
     }
 
@@ -477,6 +506,7 @@
      * canceled.
      */
     void onStopTrackingTouch() {
+        clearHotspot(R.attr.state_pressed);
         mIsDragging = false;
     }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 4298545..9e17cca 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -261,15 +261,13 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-
         final Drawable buttonDrawable = mButtonDrawable;
         if (buttonDrawable != null) {
             final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
             final int drawableHeight = buttonDrawable.getIntrinsicHeight();
             final int drawableWidth = buttonDrawable.getIntrinsicWidth();
 
-            int top = 0;
+            final int top;
             switch (verticalGravity) {
                 case Gravity.BOTTOM:
                     top = getHeight() - drawableHeight;
@@ -277,12 +275,24 @@
                 case Gravity.CENTER_VERTICAL:
                     top = (getHeight() - drawableHeight) / 2;
                     break;
+                default:
+                    top = 0;
             }
-            int bottom = top + drawableHeight;
-            int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
-            int right = isLayoutRtl() ? getWidth() : drawableWidth;
+            final int bottom = top + drawableHeight;
+            final int left = isLayoutRtl() ? getWidth() - drawableWidth : 0;
+            final int right = isLayoutRtl() ? getWidth() : drawableWidth;
 
             buttonDrawable.setBounds(left, top, right, bottom);
+
+            final Drawable background = getBackground();
+            if (background != null && background.supportsHotspots()) {
+                background.setHotspotBounds(left, top, right, bottom);
+            }
+        }
+
+        super.onDraw(canvas);
+
+        if (buttonDrawable != null) {
             buttonDrawable.draw(canvas);
         }
     }
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 14e7951c..b0a4e24 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1338,7 +1338,6 @@
 
         layout.drawBackground(canvas, highlight, highlightPaint, cursorOffsetVertical,
                 firstLine, lastLine);
-        final HardwareRenderer renderer = mTextView.getHardwareRenderer();
 
         if (layout instanceof DynamicLayout) {
             if (mTextDisplayLists == null) {
@@ -1402,7 +1401,7 @@
                             // No need to untranslate, previous context is popped after
                             // drawDisplayList
                         } finally {
-                            blockDisplayList.end(renderer, hardwareCanvas);
+                            blockDisplayList.end(hardwareCanvas);
                             // Same as drawDisplayList below, handled by our TextView's parent
                             blockDisplayList.setClipToBounds(false);
                         }
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 00b2c13..d6fa05a 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1991,7 +1991,16 @@
             , '\u0669',
             // Extended Arabic-Indic
             '\u06f0', '\u06f1', '\u06f2', '\u06f3', '\u06f4', '\u06f5', '\u06f6', '\u06f7', '\u06f8'
-            , '\u06f9'
+            , '\u06f9',
+            // Hindi and Marathi (Devanagari script)
+            '\u0966', '\u0967', '\u0968', '\u0969', '\u096a', '\u096b', '\u096c', '\u096d', '\u096e'
+            , '\u096f',
+            // Bengali
+            '\u09e6', '\u09e7', '\u09e8', '\u09e9', '\u09ea', '\u09eb', '\u09ec', '\u09ed', '\u09ee'
+            , '\u09ef',
+            // Kannada
+            '\u0ce6', '\u0ce7', '\u0ce8', '\u0ce9', '\u0cea', '\u0ceb', '\u0cec', '\u0ced', '\u0cee'
+            , '\u0cef'
     };
 
     /**
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 74b41c9..0c31496 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -256,6 +256,16 @@
         }
     }
 
+    /**
+     * Assigns the drawable that is to be drawn on top of the assigned contact photo.
+     *
+     * @param overlay Drawable to be drawn over the assigned contact photo. Must have a non-zero
+     *         instrinsic width and height.
+     */
+    public void setOverlay(Drawable overlay) {
+        mOverlay = overlay;
+    }
+
     private void onContactUriChanged() {
         setEnabled(isAssigned());
     }
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 082d728..7e8f6b4 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -138,6 +138,12 @@
     private int mActivePointerId = INVALID_POINTER;
 
     /**
+     * Used during scrolling to retrieve the new offset within the window.
+     */
+    private final int[] mScrollOffset = new int[2];
+    private final int[] mScrollConsumed = new int[2];
+
+    /**
      * The StrictMode "critical time span" objects to catch animation
      * stutters.  Non-null when a time-sensitive animation is
      * in-flight.  Must call finish() on them when done animating.
@@ -505,7 +511,7 @@
 
                 final int y = (int) ev.getY(pointerIndex);
                 final int yDiff = Math.abs(y - mLastMotionY);
-                if (yDiff > mTouchSlop) {
+                if (yDiff > mTouchSlop && (getNestedScrollAxes() & SCROLL_AXIS_VERTICAL) == 0) {
                     mIsBeingDragged = true;
                     mLastMotionY = y;
                     initVelocityTrackerIfNotExists();
@@ -547,6 +553,7 @@
                 if (mIsBeingDragged && mScrollStrictSpan == null) {
                     mScrollStrictSpan = StrictMode.enterCriticalSpan("ScrollView-scroll");
                 }
+                startNestedScroll(SCROLL_AXIS_VERTICAL);
                 break;
             }
 
@@ -559,6 +566,7 @@
                 if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0, getScrollRange())) {
                     postInvalidateOnAnimation();
                 }
+                stopNestedScroll();
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 onSecondaryPointerUp(ev);
@@ -606,6 +614,7 @@
                 // Remember where the motion event started
                 mLastMotionY = (int) ev.getY();
                 mActivePointerId = ev.getPointerId(0);
+                startNestedScroll(SCROLL_AXIS_VERTICAL);
                 break;
             }
             case MotionEvent.ACTION_MOVE:
@@ -617,6 +626,9 @@
 
                 final int y = (int) ev.getY(activePointerIndex);
                 int deltaY = mLastMotionY - y;
+                if (dispatchNestedPreScroll(0, deltaY, mScrollConsumed, mScrollOffset)) {
+                    deltaY -= mScrollConsumed[1] + mScrollOffset[1];
+                }
                 if (!mIsBeingDragged && Math.abs(deltaY) > mTouchSlop) {
                     final ViewParent parent = getParent();
                     if (parent != null) {
@@ -633,22 +645,25 @@
                     // Scroll to follow the motion event
                     mLastMotionY = y;
 
-                    final int oldX = mScrollX;
                     final int oldY = mScrollY;
                     final int range = getScrollRange();
                     final int overscrollMode = getOverScrollMode();
-                    final boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
+                    boolean canOverscroll = overscrollMode == OVER_SCROLL_ALWAYS ||
                             (overscrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && range > 0);
 
                     // Calling overScrollBy will call onOverScrolled, which
                     // calls onScrollChanged if applicable.
-                    if (overScrollBy(0, deltaY, 0, mScrollY,
-                            0, range, 0, mOverscrollDistance, true)) {
+                    if (overScrollBy(0, deltaY, 0, mScrollY, 0, range, 0, mOverscrollDistance, true)
+                            && !hasNestedScrollingParent()) {
                         // Break our velocity if we hit a scroll barrier.
                         mVelocityTracker.clear();
                     }
 
-                    if (canOverscroll) {
+                    final int scrolledDeltaY = mScrollY - oldY;
+                    final int unconsumedY = deltaY - scrolledDeltaY;
+                    if (dispatchNestedScroll(0, scrolledDeltaY, 0, unconsumedY, mScrollOffset)) {
+                        mLastMotionY -= mScrollOffset[1];
+                    } else if (canOverscroll) {
                         final int pulledToY = oldY + deltaY;
                         if (pulledToY < 0) {
                             mEdgeGlowTop.onPull((float) deltaY / getHeight());
@@ -674,15 +689,11 @@
                     velocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
                     int initialVelocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
-                    if (getChildCount() > 0) {
-                        if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
-                            fling(-initialVelocity);
-                        } else {
-                            if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,
-                                    getScrollRange())) {
-                                postInvalidateOnAnimation();
-                            }
-                        }
+                    if ((Math.abs(initialVelocity) > mMinimumVelocity)) {
+                        flingWithNestedDispatch(-initialVelocity);
+                    } else if (mScroller.springBack(mScrollX, mScrollY, 0, 0, 0,
+                            getScrollRange())) {
+                        postInvalidateOnAnimation();
                     }
 
                     mActivePointerId = INVALID_POINTER;
@@ -1553,6 +1564,15 @@
         }
     }
 
+    private void flingWithNestedDispatch(int velocityY) {
+        if (mScrollY == 0 && velocityY < 0 ||
+                mScrollY == getScrollRange() && velocityY > 0) {
+            dispatchNestedFling(0, velocityY);
+        } else {
+            fling(velocityY);
+        }
+    }
+
     private void endDrag() {
         mIsBeingDragged = false;
 
@@ -1603,6 +1623,34 @@
     }
 
     @Override
+    public boolean onStartNestedScroll(View child, View target, int nestedScrollAxes) {
+        return (nestedScrollAxes & SCROLL_AXIS_VERTICAL) != 0;
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public void onStopNestedScroll(View target) {
+        super.onStopNestedScroll(target);
+    }
+
+    @Override
+    public void onNestedScroll(View target, int dxConsumed, int dyConsumed,
+            int dxUnconsumed, int dyUnconsumed) {
+        scrollBy(0, dyUnconsumed);
+    }
+
+    /**
+     * @inheritDoc
+     */
+    @Override
+    public boolean onNestedFling(View target, float velocityX, float velocityY) {
+        flingWithNestedDispatch((int) velocityY);
+        return true;
+    }
+
+    @Override
     public void draw(Canvas canvas) {
         super.draw(canvas);
         if (mEdgeGlowTop != null) {
diff --git a/core/java/android/widget/ShareActionProvider.java b/core/java/android/widget/ShareActionProvider.java
index 64a1574..cde8080 100644
--- a/core/java/android/widget/ShareActionProvider.java
+++ b/core/java/android/widget/ShareActionProvider.java
@@ -161,9 +161,11 @@
     @Override
     public View onCreateActionView() {
         // Create the view and set its data model.
-        ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
         ActivityChooserView activityChooserView = new ActivityChooserView(mContext);
-        activityChooserView.setActivityChooserModel(dataModel);
+        if (!activityChooserView.isInEditMode()) {
+            ActivityChooserModel dataModel = ActivityChooserModel.get(mContext, mShareHistoryFileName);
+            activityChooserView.setActivityChooserModel(dataModel);
+        }
 
         // Lookup and set the expand action icon.
         TypedValue outTypedValue = new TypedValue();
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 3d23e4d..08af4de 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -773,8 +773,6 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        super.onDraw(canvas);
-
         final Rect tempRect = mTempRect;
         final Drawable trackDrawable = mTrackDrawable;
         final Drawable thumbDrawable = mThumbDrawable;
@@ -785,16 +783,12 @@
         final int switchRight = mSwitchRight;
         final int switchBottom = mSwitchBottom;
         trackDrawable.setBounds(switchLeft, switchTop, switchRight, switchBottom);
-        trackDrawable.draw(canvas);
-
-        final int saveCount = canvas.save();
-
         trackDrawable.getPadding(tempRect);
+
         final int switchInnerLeft = switchLeft + tempRect.left;
         final int switchInnerTop = switchTop + tempRect.top;
         final int switchInnerRight = switchRight - tempRect.right;
         final int switchInnerBottom = switchBottom - tempRect.bottom;
-        canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
 
         // Relies on mTempRect, MUST be called first!
         final int thumbPos = getThumbOffset();
@@ -803,6 +797,18 @@
         int thumbLeft = switchInnerLeft - tempRect.left + thumbPos;
         int thumbRight = switchInnerLeft + thumbPos + mThumbWidth + tempRect.right;
         thumbDrawable.setBounds(thumbLeft, switchTop, thumbRight, switchBottom);
+
+        final Drawable background = getBackground();
+        if (background != null && background.supportsHotspots()) {
+            background.setHotspotBounds(thumbLeft, switchTop, thumbRight, switchBottom);
+        }
+
+        super.onDraw(canvas);
+
+        trackDrawable.draw(canvas);
+
+        final int saveCount = canvas.save();
+        canvas.clipRect(switchInnerLeft, switchTop, switchInnerRight, switchBottom);
         thumbDrawable.draw(canvas);
 
         final int drawableState[] = getDrawableState();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 5e4c143..b91111d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -652,6 +652,7 @@
         boolean allCaps = false;
         int shadowcolor = 0;
         float dx = 0, dy = 0, r = 0;
+        boolean elegant = false;
 
         final Resources.Theme theme = context.getTheme();
 
@@ -714,19 +715,23 @@
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowColor:
-                    shadowcolor = a.getInt(attr, 0);
+                    shadowcolor = appearance.getInt(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowDx:
-                    dx = a.getFloat(attr, 0);
+                    dx = appearance.getFloat(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowDy:
-                    dy = a.getFloat(attr, 0);
+                    dy = appearance.getFloat(attr, 0);
                     break;
 
                 case com.android.internal.R.styleable.TextAppearance_shadowRadius:
-                    r = a.getFloat(attr, 0);
+                    r = appearance.getFloat(attr, 0);
+                    break;
+
+                case com.android.internal.R.styleable.TextAppearance_elegantTextHeight:
+                    elegant = appearance.getBoolean(attr, false);
                     break;
                 }
             }
@@ -1065,6 +1070,10 @@
             case com.android.internal.R.styleable.TextView_textAllCaps:
                 allCaps = a.getBoolean(attr, false);
                 break;
+
+            case com.android.internal.R.styleable.TextView_elegantTextHeight:
+                elegant = a.getBoolean(attr, false);
+                break;
             }
         }
         a.recycle();
@@ -1245,6 +1254,7 @@
             setHighlightColor(textColorHighlight);
         }
         setRawTextSize(textSize);
+        setElegantTextHeight(elegant);
 
         if (allCaps) {
             setTransformationMethod(new AllCapsTransformationMethod(getContext()));
@@ -2468,6 +2478,11 @@
             setTransformationMethod(new AllCapsTransformationMethod(getContext()));
         }
 
+        if (appearance.hasValue(com.android.internal.R.styleable.TextAppearance_elegantTextHeight)) {
+            setElegantTextHeight(appearance.getBoolean(
+                com.android.internal.R.styleable.TextAppearance_elegantTextHeight, false));
+        }
+
         appearance.recycle();
     }
 
@@ -2615,6 +2630,17 @@
     }
 
     /**
+     * Set the TextView's elegant height metrics flag. This setting selects font
+     * variants that have not been compacted to fit Latin-based vertical
+     * metrics, and also increases top and bottom bounds to provide more space.
+     *
+     * @param elegant set the paint's elegant metrics flag.
+     */
+    public void setElegantTextHeight(boolean elegant) {
+        mTextPaint.setElegantTextHeight(elegant);
+    }
+
+    /**
      * Sets the text color for all the states (normal, selected,
      * focused) to be this color.
      *
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 7640749..4726da7 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -102,7 +102,7 @@
 
     private ScrollView mScrollView;
     
-    private int mIconId = -1;
+    private int mIconId = 0;
     
     private Drawable mIcon;
     
@@ -337,25 +337,39 @@
     }
 
     /**
-     * Set resId to 0 if you don't want an icon.
-     * @param resId the resourceId of the drawable to use as the icon or 0
-     * if you don't want an icon.
+     * Specifies the icon to display next to the alert title.
+     *
+     * @param resId the resource identifier of the drawable to use as the icon,
+     *            or 0 for no icon
      */
     public void setIcon(int resId) {
+        mIcon = null;
         mIconId = resId;
+
         if (mIconView != null) {
-            if (resId > 0) {
+            if (resId != 0) {
                 mIconView.setImageResource(mIconId);
-            } else if (resId == 0) {
+            } else {
                 mIconView.setVisibility(View.GONE);
             }
         }
     }
-    
+
+    /**
+     * Specifies the icon to display next to the alert title.
+     *
+     * @param icon the drawable to use as the icon or null for no icon
+     */
     public void setIcon(Drawable icon) {
         mIcon = icon;
-        if ((mIconView != null) && (mIcon != null)) {
-            mIconView.setImageDrawable(icon);
+        mIconId = 0;
+
+        if (mIconView != null) {
+            if (icon != null) {
+                mIconView.setImageDrawable(icon);
+            } else {
+                mIconView.setVisibility(View.GONE);
+            }
         }
     }
 
@@ -485,28 +499,24 @@
             View titleTemplate = mWindow.findViewById(R.id.title_template);
             titleTemplate.setVisibility(View.GONE);
         } else {
-            final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
-            
             mIconView = (ImageView) mWindow.findViewById(R.id.icon);
-            if (hasTextTitle) {
-                /* Display the title if a title is supplied, else hide it */
-                mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
 
+            final boolean hasTextTitle = !TextUtils.isEmpty(mTitle);
+            if (hasTextTitle) {
+                // Display the title if a title is supplied, else hide it.
+                mTitleView = (TextView) mWindow.findViewById(R.id.alertTitle);
                 mTitleView.setText(mTitle);
-                
-                /* Do this last so that if the user has supplied any
-                 * icons we use them instead of the default ones. If the
-                 * user has specified 0 then make it disappear.
-                 */
-                if (mIconId > 0) {
+
+                // Do this last so that if the user has supplied any icons we
+                // use them instead of the default ones. If the user has
+                // specified 0 then make it disappear.
+                if (mIconId != 0) {
                     mIconView.setImageResource(mIconId);
                 } else if (mIcon != null) {
                     mIconView.setImageDrawable(mIcon);
-                } else if (mIconId == 0) {
-                    
-                    /* Apply the padding from the icon to ensure the
-                     * title is aligned correctly.
-                     */
+                } else {
+                    // Apply the padding from the icon to ensure the title is
+                    // aligned correctly.
                     mTitleView.setPadding(mIconView.getPaddingLeft(),
                             mIconView.getPaddingTop(),
                             mIconView.getPaddingRight(),
@@ -514,9 +524,8 @@
                     mIconView.setVisibility(View.GONE);
                 }
             } else {
-                
                 // Hide the title template
-                View titleTemplate = mWindow.findViewById(R.id.title_template);
+                final View titleTemplate = mWindow.findViewById(R.id.title_template);
                 titleTemplate.setVisibility(View.GONE);
                 mIconView.setVisibility(View.GONE);
                 topPanel.setVisibility(View.GONE);
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 32f700d..1bb577b 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -19,6 +19,7 @@
 import com.android.internal.os.BatteryStatsImpl;
 
 import android.os.WorkSource;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 
 interface IBatteryStats {
@@ -30,6 +31,14 @@
     // Remaining methods are only used in Java.
     byte[] getStatistics();
 
+    // Return the computed amount of time remaining on battery, in milliseconds.
+    // Returns -1 if nothing could be computed.
+    long computeBatteryTimeRemaining();
+
+    // Return the computed amount of time remaining to fully charge, in milliseconds.
+    // Returns -1 if nothing could be computed.
+    long computeChargeTimeRemaining();
+
     void addIsolatedUid(int isolatedUid, int appUid);
     void removeIsolatedUid(int isolatedUid, int appUid);
 
@@ -55,7 +64,7 @@
     void noteScreenOff();
     void noteInputEvent();
     void noteUserActivity(int uid, int event);
-    void noteDataConnectionActive(int type, boolean active, long timestampNs);
+    void noteMobileRadioPowerState(int powerState, long timestampNs);
     void notePhoneOn();
     void notePhoneOff();
     void notePhoneSignalStrength(in SignalStrength signalStrength);
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
new file mode 100644
index 0000000..3219ddd
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.content.Intent;
+import android.os.Bundle;
+
+import com.android.internal.app.IVoiceInteractor;
+import android.service.voice.IVoiceInteractionService;
+import android.service.voice.IVoiceInteractionSession;
+
+interface IVoiceInteractionManagerService {
+    void startVoiceActivity(in Intent intent, String resolvedType, IVoiceInteractionService service,
+            in Bundle sessionArgs);
+    int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+            IVoiceInteractor interactor);
+}
diff --git a/core/java/com/android/internal/app/IVoiceInteractor.aidl b/core/java/com/android/internal/app/IVoiceInteractor.aidl
new file mode 100644
index 0000000..737906a
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceInteractor.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.os.Bundle;
+
+import com.android.internal.app.IVoiceInteractorCallback;
+import com.android.internal.app.IVoiceInteractorRequest;
+
+/**
+ * IPC interface for an application to perform calls through a VoiceInteractor.
+ */
+interface IVoiceInteractor {
+    IVoiceInteractorRequest startConfirmation(String callingPackage,
+            IVoiceInteractorCallback callback, String prompt, in Bundle extras);
+    IVoiceInteractorRequest startCommand(String callingPackage,
+            IVoiceInteractorCallback callback, String command, in Bundle extras);
+    boolean[] supportsCommands(String callingPackage, in String[] commands);
+}
diff --git a/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl b/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl
new file mode 100644
index 0000000..c6f93e1
--- /dev/null
+++ b/core/java/com/android/internal/app/IVoiceInteractorCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.os.Bundle;
+
+import com.android.internal.app.IVoiceInteractorRequest;
+
+/**
+ * IPC interface for an application to receive callbacks from the voice system.
+ */
+oneway interface IVoiceInteractorCallback {
+    void deliverConfirmationResult(IVoiceInteractorRequest request, boolean confirmed,
+            in Bundle result);
+    void deliverCommandResult(IVoiceInteractorRequest request, boolean complete, in Bundle result);
+    void deliverCancel(IVoiceInteractorRequest request);
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/core/java/com/android/internal/app/IVoiceInteractorRequest.aidl
similarity index 69%
copy from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
copy to core/java/com/android/internal/app/IVoiceInteractorRequest.aidl
index 0377123..ce2902d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/core/java/com/android/internal/app/IVoiceInteractorRequest.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 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,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.internal.app;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
+/**
+ * IPC interface identifying a request from an application calling through an IVoiceInteractor.
+ */
+interface IVoiceInteractorRequest {
+    void cancel();
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
new file mode 100644
index 0000000..2f74372
--- /dev/null
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.app;
+
+import android.app.Activity;
+import android.app.AppGlobals;
+import android.os.Bundle;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.IPackageManager;
+import android.content.pm.UserInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.app.ActivityManagerNative;
+import android.os.RemoteException;
+import android.util.Slog;
+import java.util.List;
+import java.util.Set;
+
+
+
+
+/*
+ * This is used in conjunction with DevicePolicyManager.setForwardingIntents to enable intents to be
+ * passed in and out of a managed profile.
+ */
+
+public class IntentForwarderActivity extends Activity  {
+
+    public static String TAG = "IntentForwarderActivity";
+
+    public static String FORWARD_INTENT_TO_USER_OWNER
+            = "com.android.internal.app.ForwardIntentToUserOwner";
+
+    public static String FORWARD_INTENT_TO_MANAGED_PROFILE
+            = "com.android.internal.app.ForwardIntentToManagedProfile";
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        Intent intentReceived = getIntent();
+
+        String className = intentReceived.getComponent().getClassName();
+        final UserHandle userDest;
+
+        if (className.equals(FORWARD_INTENT_TO_USER_OWNER)) {
+            userDest = UserHandle.OWNER;
+        } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
+            userDest = getManagedProfile();
+        } else {
+            Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
+            userDest = null;
+        }
+        if (userDest == null) { // This covers the case where there is no managed profile.
+            finish();
+            return;
+        }
+        Intent newIntent = new Intent(intentReceived);
+        newIntent.setComponent(null);
+        newIntent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
+                |Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
+        int callingUserId = getUserId();
+        IPackageManager ipm = AppGlobals.getPackageManager();
+        String resolvedType = newIntent.resolveTypeIfNeeded(getContentResolver());
+        boolean canForward = false;
+        try {
+            canForward = ipm.canForwardTo(newIntent, resolvedType, callingUserId,
+                    userDest.getIdentifier());
+        } catch (RemoteException e) {
+            Slog.e(TAG, "PackageManagerService is dead?");
+        }
+        if (canForward) {
+            startActivityAsUser(newIntent, userDest);
+        } else {
+            Slog.wtf(TAG, "the intent: " + newIntent + "cannot be forwarded from user "
+                    + callingUserId + " to user " + userDest.getIdentifier());
+        }
+        finish();
+    }
+
+    /**
+     * Returns the managed profile for this device or null if there is no managed
+     * profile.
+     *
+     * TODO: Remove the assumption that there is only one managed profile
+     * on the device.
+     */
+    private UserHandle getManagedProfile() {
+        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
+        List<UserInfo> relatedUsers = userManager.getProfiles(UserHandle.USER_OWNER);
+        for (UserInfo userInfo : relatedUsers) {
+            if (userInfo.isManagedProfile()) return new UserHandle(userInfo.id);
+        }
+        Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE
+                + " has been called, but there is no managed profile");
+        return null;
+    }
+}
diff --git a/core/java/com/android/internal/app/ToolbarActionBar.java b/core/java/com/android/internal/app/ToolbarActionBar.java
index 34156e5..afb6f7c 100644
--- a/core/java/com/android/internal/app/ToolbarActionBar.java
+++ b/core/java/com/android/internal/app/ToolbarActionBar.java
@@ -444,9 +444,4 @@
             mMenuVisibilityListeners.get(i).onMenuVisibilityChanged(isVisible);
         }
     }
-
-    @Override
-    public void captureSharedElements(Map<String, View> sharedElements) {
-        mToolbar.findSharedElements(sharedElements);
-    }
 }
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index c6afae0..131f828 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -170,6 +170,15 @@
         init(dialog.getWindow().getDecorView());
     }
 
+    /**
+     * Only for edit mode.
+     * @hide
+     */
+    public WindowDecorActionBar(View layout) {
+        assert layout.isInEditMode();
+        init(layout);
+    }
+
     private void init(View decor) {
         mOverlayLayout = (ActionBarOverlayLayout) decor.findViewById(
                 com.android.internal.R.id.action_bar_overlay_layout);
@@ -353,10 +362,6 @@
         setSubtitle(mContext.getString(resId));
     }
 
-    public void captureSharedElements(Map<String, View> sharedElements) {
-        mContainerView.findSharedElements(sharedElements);
-    }
-
     public void setSelectedNavigationItem(int position) {
         switch (mActionView.getNavigationMode()) {
         case NAVIGATION_MODE_TABS:
@@ -559,8 +564,8 @@
             return;
         }
 
-        final FragmentTransaction trans = mActivity.getFragmentManager().beginTransaction()
-                .disallowAddToBackStack();
+        final FragmentTransaction trans = mActionView.isInEditMode() ? null :
+                mActivity.getFragmentManager().beginTransaction().disallowAddToBackStack();
 
         if (mSelectedTab == tab) {
             if (mSelectedTab != null) {
@@ -578,7 +583,7 @@
             }
         }
 
-        if (!trans.isEmpty()) {
+        if (trans != null && !trans.isEmpty()) {
             trans.commit();
         }
     }
diff --git a/core/java/com/android/internal/backup/LocalTransport.java b/core/java/com/android/internal/backup/LocalTransport.java
index 1bfad05..446ef55 100644
--- a/core/java/com/android/internal/backup/LocalTransport.java
+++ b/core/java/com/android/internal/backup/LocalTransport.java
@@ -26,6 +26,9 @@
 import android.os.Environment;
 import android.os.ParcelFileDescriptor;
 import android.os.SELinux;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.util.Log;
 
 import com.android.org.bouncycastle.util.encoders.Base64;
@@ -37,10 +40,7 @@
 import java.util.ArrayList;
 import java.util.Collections;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
-import static libcore.io.OsConstants.*;
+import static android.system.OsConstants.*;
 
 /**
  * Backup transport for stashing stuff into a known location on disk, and
@@ -109,7 +109,7 @@
     public int performBackup(PackageInfo packageInfo, ParcelFileDescriptor data) {
         if (DEBUG) {
             try {
-            StructStat ss = Libcore.os.fstat(data.getFileDescriptor());
+            StructStat ss = Os.fstat(data.getFileDescriptor());
             Log.v(TAG, "performBackup() pkg=" + packageInfo.packageName
                     + " size=" + ss.st_size);
             } catch (ErrnoException e) {
@@ -152,7 +152,7 @@
                     changeSet.readEntityData(buf, 0, dataSize);
                     if (DEBUG) {
                         try {
-                            long cur = Libcore.os.lseek(data.getFileDescriptor(), 0, SEEK_CUR);
+                            long cur = Os.lseek(data.getFileDescriptor(), 0, SEEK_CUR);
                             Log.v(TAG, "  read entity data; new pos=" + cur);
                         }
                         catch (ErrnoException e) {
diff --git a/core/java/com/android/internal/content/NativeLibraryHelper.java b/core/java/com/android/internal/content/NativeLibraryHelper.java
index 6d65782..ba419f9 100644
--- a/core/java/com/android/internal/content/NativeLibraryHelper.java
+++ b/core/java/com/android/internal/content/NativeLibraryHelper.java
@@ -16,7 +16,7 @@
 
 package com.android.internal.content;
 
-import android.os.Build;
+import android.content.pm.PackageManager;
 import android.util.Slog;
 
 import java.io.File;
@@ -31,38 +31,76 @@
 
     private static final boolean DEBUG_NATIVE = false;
 
-    private static native long nativeSumNativeBinaries(String file, String cpuAbi, String cpuAbi2);
-
     /**
-     * Sums the size of native binaries in an APK.
+     * A handle to an opened APK. Used as input to the various NativeLibraryHelper
+     * methods. Allows us to scan and parse the APK exactly once instead of doing
+     * it multiple times.
      *
-     * @param apkFile APK file to scan for native libraries
-     * @return size of all native binary files in bytes
+     * @hide
      */
-    public static long sumNativeBinariesLI(File apkFile) {
-        final String cpuAbi = Build.CPU_ABI;
-        final String cpuAbi2 = Build.CPU_ABI2;
-        return nativeSumNativeBinaries(apkFile.getPath(), cpuAbi, cpuAbi2);
+    public static class ApkHandle {
+        final String apkPath;
+        final long apkHandle;
+
+        public ApkHandle(String path) {
+            apkPath = path;
+            apkHandle = nativeOpenApk(apkPath);
+        }
+
+        public ApkHandle(File apkFile) {
+            apkPath = apkFile.getPath();
+            apkHandle = nativeOpenApk(apkPath);
+        }
+
+        public void close() {
+            nativeClose(apkHandle);
+        }
     }
 
-    private native static int nativeCopyNativeBinaries(String filePath, String sharedLibraryPath,
-            String cpuAbi, String cpuAbi2);
+
+    private static native long nativeOpenApk(String path);
+    private static native void nativeClose(long handle);
+
+    private static native long nativeSumNativeBinaries(long handle, String cpuAbi);
+
+    /**
+     * Sums the size of native binaries in an APK for a given ABI.
+     *
+     * @return size of all native binary files in bytes
+     */
+    public static long sumNativeBinariesLI(ApkHandle handle, String abi) {
+        return nativeSumNativeBinaries(handle.apkHandle, abi);
+    }
+
+    private native static int nativeCopyNativeBinaries(long handle,
+            String sharedLibraryPath, String abiToCopy);
 
     /**
      * Copies native binaries to a shared library directory.
      *
-     * @param apkFile APK file to scan for native libraries
+     * @param handle APK file to scan for native libraries
      * @param sharedLibraryDir directory for libraries to be copied to
      * @return {@link PackageManager#INSTALL_SUCCEEDED} if successful or another
      *         error code from that class if not
      */
-    public static int copyNativeBinariesIfNeededLI(File apkFile, File sharedLibraryDir) {
-        final String cpuAbi = Build.CPU_ABI;
-        final String cpuAbi2 = Build.CPU_ABI2;
-        return nativeCopyNativeBinaries(apkFile.getPath(), sharedLibraryDir.getPath(), cpuAbi,
-                cpuAbi2);
+    public static int copyNativeBinariesIfNeededLI(ApkHandle handle, File sharedLibraryDir,
+            String abi) {
+        return nativeCopyNativeBinaries(handle.apkHandle, sharedLibraryDir.getPath(), abi);
     }
 
+    /**
+     * Checks if a given APK contains native code for any of the provided
+     * {@code supportedAbis}. Returns an index into {@code supportedAbis} if a matching
+     * ABI is found, {@link PackageManager#NO_NATIVE_LIBRARIES} if the
+     * APK doesn't contain any native code, and
+     * {@link PackageManager#INSTALL_FAILED_NO_MATCHING_ABIS} if none of the ABIs match.
+     */
+    public static int findSupportedAbi(ApkHandle handle, String[] supportedAbis) {
+        return nativeFindSupportedAbi(handle.apkHandle, supportedAbis);
+    }
+
+    private native static int nativeFindSupportedAbi(long handle, String[] supportedAbis);
+
     // Convenience method to call removeNativeBinariesFromDirLI(File)
     public static boolean removeNativeBinariesLI(String nativeLibraryPath) {
         return removeNativeBinariesFromDirLI(new File(nativeLibraryPath));
diff --git a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
index dcc0a4c..cba09d1 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodSubtypeSwitchingController.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.inputmethod;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
 
 import android.content.Context;
@@ -119,14 +120,14 @@
         }
     }
 
-    private static class InputMethodAndSubtypeCircularList {
+    private static class InputMethodAndSubtypeList {
         private final Context mContext;
         // Used to load label
         private final PackageManager mPm;
         private final String mSystemLocaleStr;
         private final InputMethodSettings mSettings;
 
-        public InputMethodAndSubtypeCircularList(Context context, InputMethodSettings settings) {
+        public InputMethodAndSubtypeList(Context context, InputMethodSettings settings) {
             mContext = context;
             mSettings = settings;
             mPm = context.getPackageManager();
@@ -152,38 +153,6 @@
                             }
                         });
 
-        public ImeSubtypeListItem getNextInputMethod(
-                boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
-            if (imi == null) {
-                return null;
-            }
-            final List<ImeSubtypeListItem> imList =
-                    getSortedInputMethodAndSubtypeList();
-            if (imList.size() <= 1) {
-                return null;
-            }
-            final int N = imList.size();
-            final int currentSubtypeId =
-                    subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
-                            subtype.hashCode()) : NOT_A_SUBTYPE_ID;
-            for (int i = 0; i < N; ++i) {
-                final ImeSubtypeListItem isli = imList.get(i);
-                if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
-                    if (!onlyCurrentIme) {
-                        return imList.get((i + 1) % N);
-                    }
-                    for (int j = 0; j < N - 1; ++j) {
-                        final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
-                        if (candidate.mImi.equals(imi)) {
-                            return candidate;
-                        }
-                    }
-                    return null;
-                }
-            }
-            return null;
-        }
-
         public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList() {
             return getSortedInputMethodAndSubtypeList(true, false, false);
         }
@@ -247,7 +216,38 @@
     private final ArrayDeque<SubtypeParams> mTypedSubtypeHistory = new ArrayDeque<SubtypeParams>();
     private final Object mLock = new Object();
     private final InputMethodSettings mSettings;
-    private InputMethodAndSubtypeCircularList mSubtypeList;
+    private InputMethodAndSubtypeList mSubtypeList;
+
+    @VisibleForTesting
+    public static ImeSubtypeListItem getNextInputMethodImpl(List<ImeSubtypeListItem> imList,
+            boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
+        if (imi == null) {
+            return null;
+        }
+        if (imList.size() <= 1) {
+            return null;
+        }
+        final int N = imList.size();
+        final int currentSubtypeId =
+                subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi,
+                        subtype.hashCode()) : NOT_A_SUBTYPE_ID;
+        for (int i = 0; i < N; ++i) {
+            final ImeSubtypeListItem isli = imList.get(i);
+            if (isli.mImi.equals(imi) && isli.mSubtypeId == currentSubtypeId) {
+                if (!onlyCurrentIme) {
+                    return imList.get((i + 1) % N);
+                }
+                for (int j = 0; j < N - 1; ++j) {
+                    final ImeSubtypeListItem candidate = imList.get((i + j + 1) % N);
+                    if (candidate.mImi.equals(imi)) {
+                        return candidate;
+                    }
+                }
+                return null;
+            }
+        }
+        return null;
+    }
 
     public InputMethodSubtypeSwitchingController(InputMethodSettings settings) {
         mSettings = settings;
@@ -278,14 +278,15 @@
 
     public void resetCircularListLocked(Context context) {
         synchronized(mLock) {
-            mSubtypeList = new InputMethodAndSubtypeCircularList(context, mSettings);
+            mSubtypeList = new InputMethodAndSubtypeList(context, mSettings);
         }
     }
 
     public ImeSubtypeListItem getNextInputMethod(
             boolean onlyCurrentIme, InputMethodInfo imi, InputMethodSubtype subtype) {
         synchronized(mLock) {
-            return mSubtypeList.getNextInputMethod(onlyCurrentIme, imi, subtype);
+            return getNextInputMethodImpl(mSubtypeList.getSortedInputMethodAndSubtypeList(),
+                    onlyCurrentIme, imi, subtype);
         }
     }
 
diff --git a/core/java/com/android/internal/notification/PeopleNotificationScorer.java b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
new file mode 100644
index 0000000..efb5f63
--- /dev/null
+++ b/core/java/com/android/internal/notification/PeopleNotificationScorer.java
@@ -0,0 +1,227 @@
+/*
+* Copyright (C) 2014 The Android Open Source Project
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+
+package com.android.internal.notification;
+
+import android.app.Notification;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.Contacts;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.LruCache;
+import android.util.Slog;
+
+/**
+ * This {@link NotificationScorer} attempts to validate people references.
+ * Also elevates the priority of real people.
+ */
+public class PeopleNotificationScorer implements NotificationScorer {
+    private static final String TAG = "PeopleNotificationScorer";
+    private static final boolean DBG = false;
+
+    private static final boolean ENABLE_PEOPLE_SCORER = true;
+    private static final String SETTING_ENABLE_PEOPLE_SCORER = "people_scorer_enabled";
+    private static final String[] LOOKUP_PROJECTION = { Contacts._ID };
+    private static final int MAX_PEOPLE = 10;
+    private static final int PEOPLE_CACHE_SIZE = 200;
+    // see NotificationManagerService
+    private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10;
+
+    protected boolean mEnabled;
+    private Context mContext;
+
+    // maps raw person handle to resolved person object
+    private LruCache<String, LookupResult> mPeopleCache;
+
+    private float findMaxContactScore(Bundle extras) {
+        if (extras == null) {
+            return 0f;
+        }
+
+        final String[] people = extras.getStringArray(Notification.EXTRA_PEOPLE);
+        if (people == null || people.length == 0) {
+            return 0f;
+        }
+
+        float rank = 0f;
+        for (int personIdx = 0; personIdx < people.length && personIdx < MAX_PEOPLE; personIdx++) {
+            final String handle = people[personIdx];
+            if (TextUtils.isEmpty(handle)) continue;
+
+            LookupResult lookupResult = mPeopleCache.get(handle);
+            if (lookupResult == null || lookupResult.isExpired()) {
+                final Uri uri = Uri.parse(handle);
+                if ("tel".equals(uri.getScheme())) {
+                    if (DBG) Slog.w(TAG, "checking telephone URI: " + handle);
+                    lookupResult = lookupPhoneContact(handle, uri.getSchemeSpecificPart());
+                } else if (handle.startsWith(Contacts.CONTENT_LOOKUP_URI.toString())) {
+                    if (DBG) Slog.w(TAG, "checking lookup URI: " + handle);
+                    lookupResult = resolveContactsUri(handle, uri);
+                } else {
+                    if (DBG) Slog.w(TAG, "unsupported URI " + handle);
+                }
+            } else {
+                if (DBG) Slog.w(TAG, "using cached lookupResult: " + lookupResult.mId);
+            }
+            if (lookupResult != null) {
+                rank = Math.max(rank, lookupResult.getRank());
+            }
+        }
+        return rank;
+    }
+
+    private LookupResult lookupPhoneContact(final String handle, final String number) {
+        LookupResult lookupResult = null;
+        Cursor c = null;
+        try {
+            Uri numberUri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI,
+                    Uri.encode(number));
+            c = mContext.getContentResolver().query(numberUri, LOOKUP_PROJECTION, null, null, null);
+            if (c != null && c.getCount() > 0) {
+                c.moveToFirst();
+                final int idIdx = c.getColumnIndex(Contacts._ID);
+                final int id = c.getInt(idIdx);
+                if (DBG) Slog.w(TAG, "is valid: " + id);
+                lookupResult = new LookupResult(id);
+            }
+        } catch(Throwable t) {
+            Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        if (lookupResult == null) {
+            lookupResult = new LookupResult(LookupResult.INVALID_ID);
+        }
+        mPeopleCache.put(handle, lookupResult);
+        return lookupResult;
+    }
+
+    private LookupResult resolveContactsUri(String handle, final Uri personUri) {
+        LookupResult lookupResult = null;
+        Cursor c = null;
+        try {
+            c = mContext.getContentResolver().query(personUri, LOOKUP_PROJECTION, null, null, null);
+            if (c != null && c.getCount() > 0) {
+                c.moveToFirst();
+                final int idIdx = c.getColumnIndex(Contacts._ID);
+                final int id = c.getInt(idIdx);
+                if (DBG) Slog.w(TAG, "is valid: " + id);
+                lookupResult = new LookupResult(id);
+            }
+        } catch(Throwable t) {
+            Slog.w(TAG, "Problem getting content resolver or performing contacts query.", t);
+        } finally {
+            if (c != null) {
+                c.close();
+            }
+        }
+        if (lookupResult == null) {
+            lookupResult = new LookupResult(LookupResult.INVALID_ID);
+        }
+        mPeopleCache.put(handle, lookupResult);
+        return lookupResult;
+    }
+
+    private final static int clamp(int x, int low, int high) {
+        return (x < low) ? low : ((x > high) ? high : x);
+    }
+
+    // TODO: rework this function before shipping
+    private static int priorityBumpMap(int incomingScore) {
+        //assumption is that scale runs from [-2*pm, 2*pm]
+        int pm = NOTIFICATION_PRIORITY_MULTIPLIER;
+        int theScore = incomingScore;
+        // enforce input in range
+        theScore = clamp(theScore, -2 * pm, 2 * pm);
+        if (theScore != incomingScore) return incomingScore;
+        // map -20 -> -20 and -10 -> 5 (when pm = 10)
+        if (theScore <= -pm) {
+            theScore += 1.5 * (theScore + 2 * pm);
+        } else {
+            // map 0 -> 10, 10 -> 15, 20 -> 20;
+            theScore += 0.5 * (2 * pm - theScore);
+        }
+        if (DBG) Slog.v(TAG, "priorityBumpMap: score before: " + incomingScore
+                + ", score after " + theScore + ".");
+        return theScore;
+    }
+
+    @Override
+    public void initialize(Context context) {
+        if (DBG) Slog.v(TAG, "Initializing  " + getClass().getSimpleName() + ".");
+        mContext = context;
+        mPeopleCache = new LruCache<String, LookupResult>(PEOPLE_CACHE_SIZE);
+        mEnabled = ENABLE_PEOPLE_SCORER && 1 == Settings.Global.getInt(
+                mContext.getContentResolver(), SETTING_ENABLE_PEOPLE_SCORER, 0);
+    }
+
+    @Override
+    public int getScore(Notification notification, int score) {
+        if (notification == null || !mEnabled) {
+            if (DBG) Slog.w(TAG, "empty notification? scorer disabled?");
+            return score;
+        }
+        float contactScore = findMaxContactScore(notification.extras);
+        if (contactScore > 0f) {
+            if (DBG) Slog.v(TAG, "Notification references a real contact. Promoted!");
+            score = priorityBumpMap(score);
+        } else {
+            if (DBG) Slog.v(TAG, "Notification lacks any valid contact reference. Not promoted!");
+        }
+        return score;
+    }
+
+    private static class LookupResult {
+        private static final long CONTACT_REFRESH_MILLIS = 60 * 60 * 1000;  // 1hr
+        public static final int INVALID_ID = -1;
+
+        private final long mExpireMillis;
+        private int mId;
+
+        public LookupResult(int id) {
+            mId = id;
+            mExpireMillis = System.currentTimeMillis() + CONTACT_REFRESH_MILLIS;
+        }
+
+        public boolean isExpired() {
+            return mExpireMillis < System.currentTimeMillis();
+        }
+
+        public boolean isInvalid() {
+            return mId == INVALID_ID || isExpired();
+        }
+
+        public float getRank() {
+            if (isInvalid()) {
+                return 0f;
+            } else {
+                return 1f;  // TODO: finer grained score
+            }
+        }
+
+        public LookupResult setId(int id) {
+            mId = id;
+            return this;
+        }
+    }
+}
+
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
index 1dd1f5e..7ff949e 100644
--- a/core/java/com/android/internal/os/BatteryStatsHelper.java
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -22,6 +22,8 @@
 import static android.os.BatteryStats.NETWORK_WIFI_TX_DATA;
 
 import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
 import android.hardware.Sensor;
 import android.hardware.SensorManager;
 import android.net.ConnectivityManager;
@@ -60,11 +62,14 @@
     private static final String TAG = BatteryStatsHelper.class.getSimpleName();
 
     private static BatteryStats sStatsXfer;
+    private static Intent sBatteryBroadcastXfer;
 
     final private Context mContext;
+    final private boolean mCollectBatteryBroadcast;
 
     private IBatteryStats mBatteryInfo;
     private BatteryStats mStats;
+    private Intent mBatteryBroadcast;
     private PowerProfile mPowerProfile;
 
     private final List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
@@ -85,6 +90,8 @@
     long mBatteryUptime;
     long mTypeBatteryRealtime;
     long mTypeBatteryUptime;
+    long mBatteryTimeRemaining;
+    long mChargeTimeRemaining;
 
     private long mStatsPeriod = 0;
     private double mMaxPower = 1;
@@ -102,7 +109,12 @@
     private long mAppWifiRunning;
 
     public BatteryStatsHelper(Context context) {
+        this(context, true);
+    }
+
+    public BatteryStatsHelper(Context context, boolean collectBatteryBroadcast) {
         mContext = context;
+        mCollectBatteryBroadcast = collectBatteryBroadcast;
     }
 
     /** Clears the current stats and forces recreating for future use. */
@@ -117,6 +129,13 @@
         return mStats;
     }
 
+    public Intent getBatteryBroadcast() {
+        if (mBatteryBroadcast == null && mCollectBatteryBroadcast) {
+            load();
+        }
+        return mBatteryBroadcast;
+    }
+
     public PowerProfile getPowerProfile() {
         return mPowerProfile;
     }
@@ -129,6 +148,7 @@
     public void create(Bundle icicle) {
         if (icicle != null) {
             mStats = sStatsXfer;
+            mBatteryBroadcast = sBatteryBroadcastXfer;
         }
         mBatteryInfo = IBatteryStats.Stub.asInterface(
                 ServiceManager.getService(BatteryStats.SERVICE_NAME));
@@ -137,6 +157,7 @@
 
     public void storeState() {
         sStatsXfer = mStats;
+        sBatteryBroadcastXfer = mBatteryBroadcast;
     }
 
     public static String makemAh(double power) {
@@ -190,6 +211,8 @@
         mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeUs);
         mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeUs, mStatsType);
         mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeUs, mStatsType);
+        mBatteryTimeRemaining = mStats.computeBatteryTimeRemaining(rawRealtimeUs);
+        mChargeTimeRemaining = mStats.computeChargeTimeRemaining(rawRealtimeUs);
 
         if (DEBUG) {
             Log.d(TAG, "Raw time: realtime=" + (rawRealtimeUs/1000) + " uptime="
@@ -787,6 +810,10 @@
         return mMaxDrainedPower;
     }
 
+    public long getBatteryTimeRemaining() { return mBatteryTimeRemaining; }
+
+    public long getChargeTimeRemaining() { return mChargeTimeRemaining; }
+
     private void load() {
         if (mBatteryInfo == null) {
             return;
@@ -803,5 +830,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException:", e);
         }
+        if (mCollectBatteryBroadcast) {
+            mBatteryBroadcast = mContext.registerReceiver(null,
+                    new IntentFilter(Intent.ACTION_BATTERY_CHANGED));
+        }
     }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 4c11fa9..f63fa8a 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -38,6 +38,7 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.WorkSource;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
@@ -87,7 +88,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 101 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 104 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -284,7 +285,7 @@
     int mBluetoothState = -1;
     final StopwatchTimer[] mBluetoothStateTimer = new StopwatchTimer[NUM_BLUETOOTH_STATES];
 
-    boolean mMobileRadioActive;
+    int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
     StopwatchTimer mMobileRadioActiveTimer;
     StopwatchTimer mMobileRadioActivePerAppTimer;
     LongSamplingCounter mMobileRadioActiveAdjustedTime;
@@ -306,7 +307,9 @@
      */
     int mDischargeStartLevel;
     int mDischargeUnplugLevel;
+    int mDischargePlugLevel;
     int mDischargeCurrentLevel;
+    int mCurrentBatteryLevel;
     int mLowDischargeAmountSinceCharge;
     int mHighDischargeAmountSinceCharge;
     int mDischargeScreenOnUnplugLevel;
@@ -316,6 +319,18 @@
     int mDischargeAmountScreenOff;
     int mDischargeAmountScreenOffSinceCharge;
 
+    static final int MAX_LEVEL_STEPS = 100;
+
+    int mLastDischargeStepLevel;
+    long mLastDischargeStepTime;
+    int mNumDischargeStepDurations;
+    final long[] mDischargeStepDurations = new long[MAX_LEVEL_STEPS];
+
+    int mLastChargeStepLevel;
+    long mLastChargeStepTime;
+    int mNumChargeStepDurations;
+    final long[] mChargeStepDurations = new long[MAX_LEVEL_STEPS];
+
     long mLastWriteTime = 0; // Milliseconds
 
     private int mBluetoothPingCount;
@@ -2736,40 +2751,41 @@
         }
     }
 
-    public void noteDataConnectionActive(int type, boolean active, long timestampNs) {
-        if (ConnectivityManager.isNetworkTypeMobile(type)) {
-            final long elapsedRealtime = SystemClock.elapsedRealtime();
-            final long uptime = SystemClock.uptimeMillis();
-            if (mMobileRadioActive != active) {
-                long realElapsedRealtimeMs;
-                if (active) {
+    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
+        final long elapsedRealtime = SystemClock.elapsedRealtime();
+        final long uptime = SystemClock.uptimeMillis();
+        if (mMobileRadioPowerState != powerState) {
+            long realElapsedRealtimeMs;
+            final boolean active =
+                    powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
+                            || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
+            if (active) {
+                realElapsedRealtimeMs = elapsedRealtime;
+                mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+            } else {
+                realElapsedRealtimeMs = timestampNs / (1000*1000);
+                long lastUpdateTimeMs = mMobileRadioActiveTimer.getLastUpdateTimeMs();
+                if (realElapsedRealtimeMs < lastUpdateTimeMs) {
+                    Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
+                            + " is before start time " + lastUpdateTimeMs);
                     realElapsedRealtimeMs = elapsedRealtime;
-                    mHistoryCur.states |= HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
-                } else {
-                    realElapsedRealtimeMs = timestampNs / (1000*1000);
-                    long lastUpdateTimeMs = mMobileRadioActiveTimer.getLastUpdateTimeMs();
-                    if (realElapsedRealtimeMs < lastUpdateTimeMs) {
-                        Slog.wtf(TAG, "Data connection inactive timestamp " + realElapsedRealtimeMs
-                                + " is before start time " + lastUpdateTimeMs);
-                        realElapsedRealtimeMs = elapsedRealtime;
-                    } else if (realElapsedRealtimeMs < elapsedRealtime) {
-                        mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
-                                - realElapsedRealtimeMs);
-                    }
-                    mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+                } else if (realElapsedRealtimeMs < elapsedRealtime) {
+                    mMobileRadioActiveAdjustedTime.addCountLocked(elapsedRealtime
+                            - realElapsedRealtimeMs);
                 }
-                if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
-                        + Integer.toHexString(mHistoryCur.states));
-                addHistoryRecordLocked(elapsedRealtime, uptime);
-                mMobileRadioActive = active;
-                if (active) {
-                    mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
-                    mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
-                } else {
-                    mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
-                    updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs);
-                    mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
-                }
+                mHistoryCur.states &= ~HistoryItem.STATE_MOBILE_RADIO_ACTIVE_FLAG;
+            }
+            if (DEBUG_HISTORY) Slog.v(TAG, "Mobile network active " + active + " to: "
+                    + Integer.toHexString(mHistoryCur.states));
+            addHistoryRecordLocked(elapsedRealtime, uptime);
+            mMobileRadioPowerState = powerState;
+            if (active) {
+                mMobileRadioActiveTimer.startRunningLocked(elapsedRealtime);
+                mMobileRadioActivePerAppTimer.startRunningLocked(elapsedRealtime);
+            } else {
+                mMobileRadioActiveTimer.stopRunningLocked(realElapsedRealtimeMs);
+                updateNetworkActivityLocked(NET_UPDATE_MOBILE, realElapsedRealtimeMs);
+                mMobileRadioActivePerAppTimer.stopRunningLocked(realElapsedRealtimeMs);
             }
         }
     }
@@ -5520,7 +5536,9 @@
         initTimes(uptime, realtime);
         mDischargeStartLevel = 0;
         mDischargeUnplugLevel = 0;
+        mDischargePlugLevel = -1;
         mDischargeCurrentLevel = 0;
+        mCurrentBatteryLevel = 0;
         initDischarge();
         clearHistoryLocked();
     }
@@ -5580,13 +5598,13 @@
             if (end) {
                 Slog.w(TAG, "New history ends before old history!");
             } else if (!out.same(mHistoryReadTmp)) {
-                long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
                 PrintWriter pw = new FastPrintWriter(new LogWriter(android.util.Log.WARN, TAG));
                 pw.println("Histories differ!");
                 pw.println("Old history:");
-                (new HistoryPrinter()).printNextItem(pw, out, now, false, true);
+                (new HistoryPrinter()).printNextItem(pw, out, 0, false, true);
                 pw.println("New history:");
-                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, now, false, true);
+                (new HistoryPrinter()).printNextItem(pw, mHistoryReadTmp, 0, false,
+                        true);
                 pw.flush();
             }
         }
@@ -5664,7 +5682,12 @@
             return false;
         }
 
+        final long lastRealtime = out.time;
+        final long lastWalltime = out.currentTime;
         readHistoryDelta(mHistoryBuffer, out);
+        if (out.cmd != HistoryItem.CMD_CURRENT_TIME && lastWalltime != 0) {
+            out.currentTime = lastWalltime + (out.time - lastRealtime);
+        }
         return true;
     }
 
@@ -5710,6 +5733,10 @@
         mDischargeAmountScreenOnSinceCharge = 0;
         mDischargeAmountScreenOff = 0;
         mDischargeAmountScreenOffSinceCharge = 0;
+        mLastDischargeStepTime = -1;
+        mNumDischargeStepDurations = 0;
+        mLastChargeStepTime = -1;
+        mNumChargeStepDurations = 0;
     }
 
     public void resetAllStatsCmdLocked() {
@@ -5721,7 +5748,8 @@
         mDischargeStartLevel = mHistoryCur.batteryLevel;
         pullPendingStateUpdatesLocked();
         addHistoryRecordLocked(mSecRealtime, mSecUptime);
-        mDischargeCurrentLevel = mDischargeUnplugLevel = mHistoryCur.batteryLevel;
+        mDischargeCurrentLevel = mDischargeUnplugLevel = mDischargePlugLevel
+                = mCurrentBatteryLevel = mHistoryCur.batteryLevel;
         mOnBatteryTimeBase.reset(uptime, realtime);
         mOnBatteryScreenOffTimeBase.reset(uptime, realtime);
         if ((mHistoryCur.states&HistoryItem.STATE_BATTERY_PLUGGED_FLAG) == 0) {
@@ -5873,7 +5901,10 @@
                 resetAllStatsLocked();
                 mDischargeStartLevel = level;
                 reset = true;
+                mNumDischargeStepDurations = 0;
             }
+            mLastDischargeStepLevel = level;
+            mLastDischargeStepTime = -1;
             pullPendingStateUpdatesLocked();
             mHistoryCur.batteryLevel = (byte)level;
             mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
@@ -5902,13 +5933,16 @@
             if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
                     + Integer.toHexString(mHistoryCur.states));
             addHistoryRecordLocked(mSecRealtime, mSecUptime);
-            mDischargeCurrentLevel = level;
+            mDischargeCurrentLevel = mDischargePlugLevel = level;
             if (level < mDischargeUnplugLevel) {
                 mLowDischargeAmountSinceCharge += mDischargeUnplugLevel-level-1;
                 mHighDischargeAmountSinceCharge += mDischargeUnplugLevel-level;
             }
             updateDischargeScreenLevelsLocked(mScreenOn, mScreenOn);
             updateTimeBasesLocked(false, !mScreenOn, uptime, realtime);
+            mNumChargeStepDurations = 0;
+            mLastChargeStepLevel = level;
+            mLastChargeStepTime = -1;
         }
         if (doWrite || (mLastWriteTime + (60 * 1000)) < mSecRealtime) {
             if (mFile != null) {
@@ -5932,6 +5966,24 @@
     // This should probably be exposed in the API, though it's not critical
     private static final int BATTERY_PLUGGED_NONE = 0;
 
+    private static int addLevelSteps(long[] steps, int stepCount, long lastStepTime,
+            int numStepLevels, long elapsedRealtime) {
+        if (lastStepTime >= 0 && numStepLevels > 0) {
+            long duration = elapsedRealtime - lastStepTime;
+            for (int i=0; i<numStepLevels; i++) {
+                System.arraycopy(steps, 0, steps, 1, steps.length-1);
+                long thisDuration = duration / (numStepLevels-i);
+                duration -= thisDuration;
+                steps[0] = thisDuration;
+            }
+            stepCount += numStepLevels;
+            if (stepCount > steps.length) {
+                stepCount = steps.length;
+            }
+        }
+        return stepCount;
+    }
+
     public void setBatteryState(int status, int health, int plugType, int level,
             int temp, int volt) {
         synchronized(this) {
@@ -5966,6 +6018,10 @@
                     startRecordingHistory(elapsedRealtime, uptime, true);
                 }
             }
+            mCurrentBatteryLevel = level;
+            if (mDischargePlugLevel < 0) {
+                mDischargePlugLevel = level;
+            }
             if (onBattery != mOnBattery) {
                 mHistoryCur.batteryLevel = (byte)level;
                 mHistoryCur.batteryStatus = (byte)status;
@@ -6005,6 +6061,23 @@
                 if (changed) {
                     addHistoryRecordLocked(elapsedRealtime, uptime);
                 }
+                if (onBattery) {
+                    if (mLastDischargeStepLevel != level) {
+                        mNumDischargeStepDurations = addLevelSteps(mDischargeStepDurations,
+                                mNumDischargeStepDurations, mLastDischargeStepTime,
+                                mLastDischargeStepLevel - level, elapsedRealtime);
+                        mLastDischargeStepLevel = level;
+                        mLastDischargeStepTime = elapsedRealtime;
+                    }
+                } else {
+                    if (mLastChargeStepLevel != level) {
+                        mNumChargeStepDurations = addLevelSteps(mChargeStepDurations,
+                                mNumChargeStepDurations, mLastChargeStepTime,
+                                level - mLastChargeStepLevel, elapsedRealtime);
+                        mLastChargeStepLevel = level;
+                        mLastChargeStepTime = elapsedRealtime;
+                    }
+                }
             }
             if (!onBattery && status == BatteryManager.BATTERY_STATUS_FULL) {
                 // We don't record history while we are plugged in and fully charged.
@@ -6219,6 +6292,117 @@
         return mOnBatteryScreenOffTimeBase.computeRealtime(curTime, which);
     }
 
+    private long computeTimePerLevel(long[] steps, int numSteps) {
+        // For now we'll do a simple average across all steps.
+        if (numSteps <= 0) {
+            return -1;
+        }
+        long total = 0;
+        for (int i=0; i<numSteps; i++) {
+            total += steps[i];
+        }
+        return total / numSteps;
+        /*
+        long[] buckets = new long[numSteps];
+        int numBuckets = 0;
+        int numToAverage = 4;
+        int i = 0;
+        while (i < numSteps) {
+            long totalTime = 0;
+            int num = 0;
+            for (int j=0; j<numToAverage && (i+j)<numSteps; j++) {
+                totalTime += steps[i+j];
+                num++;
+            }
+            buckets[numBuckets] = totalTime / num;
+            numBuckets++;
+            numToAverage *= 2;
+            i += num;
+        }
+        if (numBuckets < 1) {
+            return -1;
+        }
+        long averageTime = buckets[numBuckets-1];
+        for (i=numBuckets-2; i>=0; i--) {
+            averageTime = (averageTime + buckets[i]) / 2;
+        }
+        return averageTime;
+        */
+    }
+
+    @Override
+    public long computeBatteryTimeRemaining(long curTime) {
+        if (!mOnBattery) {
+            return -1;
+        }
+        /* Simple implementation just looks at the average discharge per level across the
+           entire sample period.
+        int discharge = (getLowDischargeAmountSinceCharge()+getHighDischargeAmountSinceCharge())/2;
+        if (discharge < 2) {
+            return -1;
+        }
+        long duration = computeBatteryRealtime(curTime, STATS_SINCE_CHARGED);
+        if (duration < 1000*1000) {
+            return -1;
+        }
+        long usPerLevel = duration/discharge;
+        return usPerLevel * mCurrentBatteryLevel;
+        */
+        if (mNumDischargeStepDurations < 1) {
+            return -1;
+        }
+        long msPerLevel = computeTimePerLevel(mDischargeStepDurations, mNumDischargeStepDurations);
+        if (msPerLevel <= 0) {
+            return -1;
+        }
+        return (msPerLevel * mCurrentBatteryLevel) * 1000;
+    }
+
+    public int getNumDischargeStepDurations() {
+        return mNumDischargeStepDurations;
+    }
+
+    public long[] getDischargeStepDurationsArray() {
+        return mDischargeStepDurations;
+    }
+
+    @Override
+    public long computeChargeTimeRemaining(long curTime) {
+        if (mOnBattery) {
+            // Not yet working.
+            return -1;
+        }
+        /* Broken
+        int curLevel = mCurrentBatteryLevel;
+        int plugLevel = mDischargePlugLevel;
+        if (plugLevel < 0 || curLevel < (plugLevel+1)) {
+            return -1;
+        }
+        long duration = computeBatteryRealtime(curTime, STATS_SINCE_UNPLUGGED);
+        if (duration < 1000*1000) {
+            return -1;
+        }
+        long usPerLevel = duration/(curLevel-plugLevel);
+        return usPerLevel * (100-curLevel);
+        */
+        if (mNumChargeStepDurations < 1) {
+            return -1;
+        }
+        long msPerLevel = computeTimePerLevel(mChargeStepDurations, mNumChargeStepDurations);
+        if (msPerLevel <= 0) {
+            return -1;
+        }
+        return (msPerLevel * (100-mCurrentBatteryLevel)) * 1000;
+    }
+
+    public int getNumChargeStepDurations() {
+        return mNumChargeStepDurations;
+    }
+
+    public long[] getChargeStepDurationsArray() {
+        return mChargeStepDurations;
+    }
+
     long getBatteryUptimeLocked() {
         return mOnBatteryTimeBase.getUptime(SystemClock.uptimeMillis() * 1000);
     }
@@ -6717,11 +6901,17 @@
         mOnBatteryTimeBase.readSummaryFromParcel(in);
         mOnBatteryScreenOffTimeBase.readSummaryFromParcel(in);
         mDischargeUnplugLevel = in.readInt();
+        mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
+        mCurrentBatteryLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
         mDischargeAmountScreenOnSinceCharge = in.readInt();
         mDischargeAmountScreenOffSinceCharge = in.readInt();
+        mNumDischargeStepDurations = in.readInt();
+        in.readLongArray(mDischargeStepDurations);
+        mNumChargeStepDurations = in.readInt();
+        in.readLongArray(mChargeStepDurations);
 
         mStartCount++;
 
@@ -6744,7 +6934,7 @@
             mNetworkByteActivityCounters[i].readSummaryFromParcelLocked(in);
             mNetworkPacketActivityCounters[i].readSummaryFromParcelLocked(in);
         }
-        mMobileRadioActive = false;
+        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
         mMobileRadioActiveTimer.readSummaryFromParcelLocked(in);
         mMobileRadioActivePerAppTimer.readSummaryFromParcelLocked(in);
         mMobileRadioActiveAdjustedTime.readSummaryFromParcelLocked(in);
@@ -6969,11 +7159,17 @@
         mOnBatteryTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         mOnBatteryScreenOffTimeBase.writeSummaryToParcel(out, NOW_SYS, NOWREAL_SYS);
         out.writeInt(mDischargeUnplugLevel);
+        out.writeInt(mDischargePlugLevel);
         out.writeInt(mDischargeCurrentLevel);
+        out.writeInt(mCurrentBatteryLevel);
         out.writeInt(getLowDischargeAmountSinceCharge());
         out.writeInt(getHighDischargeAmountSinceCharge());
         out.writeInt(getDischargeAmountScreenOnSinceCharge());
         out.writeInt(getDischargeAmountScreenOffSinceCharge());
+        out.writeInt(mNumDischargeStepDurations);
+        out.writeLongArray(mDischargeStepDurations);
+        out.writeInt(mNumChargeStepDurations);
+        out.writeLongArray(mChargeStepDurations);
 
         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL_SYS);
         for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
@@ -7257,7 +7453,7 @@
             mNetworkByteActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
             mNetworkPacketActivityCounters[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
         }
-        mMobileRadioActive = false;
+        mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
         mMobileRadioActiveTimer = new StopwatchTimer(null, -400, null, mOnBatteryTimeBase, in);
         mMobileRadioActivePerAppTimer = new StopwatchTimer(null, -401, null, mOnBatteryTimeBase,
                 in);
@@ -7279,13 +7475,19 @@
                     null, mOnBatteryTimeBase, in);
         }
         mDischargeUnplugLevel = in.readInt();
+        mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
+        mCurrentBatteryLevel = in.readInt();
         mLowDischargeAmountSinceCharge = in.readInt();
         mHighDischargeAmountSinceCharge = in.readInt();
         mDischargeAmountScreenOn = in.readInt();
         mDischargeAmountScreenOnSinceCharge = in.readInt();
         mDischargeAmountScreenOff = in.readInt();
         mDischargeAmountScreenOffSinceCharge = in.readInt();
+        mNumDischargeStepDurations = in.readInt();
+        in.readLongArray(mDischargeStepDurations);
+        mNumChargeStepDurations = in.readInt();
+        in.readLongArray(mChargeStepDurations);
         mLastWriteTime = in.readLong();
 
         mBluetoothPingCount = in.readInt();
@@ -7397,13 +7599,19 @@
             mBluetoothStateTimer[i].writeToParcel(out, uSecRealtime);
         }
         out.writeInt(mDischargeUnplugLevel);
+        out.writeInt(mDischargePlugLevel);
         out.writeInt(mDischargeCurrentLevel);
+        out.writeInt(mCurrentBatteryLevel);
         out.writeInt(mLowDischargeAmountSinceCharge);
         out.writeInt(mHighDischargeAmountSinceCharge);
         out.writeInt(mDischargeAmountScreenOn);
         out.writeInt(mDischargeAmountScreenOnSinceCharge);
         out.writeInt(mDischargeAmountScreenOff);
         out.writeInt(mDischargeAmountScreenOffSinceCharge);
+        out.writeInt(mNumDischargeStepDurations);
+        out.writeLongArray(mDischargeStepDurations);
+        out.writeInt(mNumChargeStepDurations);
+        out.writeLongArray(mChargeStepDurations);
         out.writeLong(mLastWriteTime);
 
         out.writeInt(getBluetoothPingCount());
@@ -7494,6 +7702,7 @@
                 pr.println("*** Data connection type #" + i + ":");
                 mPhoneDataConnectionsTimer[i].logState(pr, "  ");
             }
+            pr.println("*** mMobileRadioPowerState=" + mMobileRadioPowerState);
             pr.println("*** Mobile network active timer:");
             mMobileRadioActiveTimer.logState(pr, "  ");
             pr.println("*** Mobile network active adjusted timer:");
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index d9e3ef6..40834ba 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -85,7 +85,27 @@
     public void sendMessage(Message msg) {
         mH.sendMessage(msg);
     }
-    
+
+    public SomeArgs sendMessageAndWait(Message msg) {
+        if (Looper.myLooper() == mH.getLooper()) {
+            throw new IllegalStateException("Can't wait on same thread as looper");
+        }
+        SomeArgs args = (SomeArgs)msg.obj;
+        args.mWaitState = SomeArgs.WAIT_WAITING;
+        mH.sendMessage(msg);
+        synchronized (args) {
+            while (args.mWaitState == SomeArgs.WAIT_WAITING) {
+                try {
+                    args.wait();
+                } catch (InterruptedException e) {
+                    return null;
+                }
+            }
+        }
+        args.mWaitState = SomeArgs.WAIT_NONE;
+        return args;
+    }
+
     public Message obtainMessage(int what) {
         return mH.obtainMessage(what);
     }
@@ -136,6 +156,14 @@
         return mH.obtainMessage(what, arg1, 0, args);
     }
     
+    public Message obtainMessageIOOO(int what, int arg1, Object arg2, Object arg3, Object arg4) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = arg2;
+        args.arg2 = arg3;
+        args.arg3 = arg4;
+        return mH.obtainMessage(what, arg1, 0, args);
+    }
+
     public Message obtainMessageOO(int what, Object arg1, Object arg2) {
         SomeArgs args = SomeArgs.obtain();
         args.arg1 = arg1;
@@ -161,6 +189,17 @@
         return mH.obtainMessage(what, 0, 0, args);
     }
     
+    public Message obtainMessageOOOOO(int what, Object arg1, Object arg2,
+            Object arg3, Object arg4, Object arg5) {
+        SomeArgs args = SomeArgs.obtain();
+        args.arg1 = arg1;
+        args.arg2 = arg2;
+        args.arg3 = arg3;
+        args.arg4 = arg4;
+        args.arg5 = arg5;
+        return mH.obtainMessage(what, 0, 0, args);
+    }
+
     public Message obtainMessageIIII(int what, int arg1, int arg2,
             int arg3, int arg4) {
         SomeArgs args = SomeArgs.obtain();
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 5538dca..4a26b4b 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -55,6 +55,11 @@
     private static final native void nativeFinishInit();
     private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
 
+    private static int Clog_e(String tag, String msg, Throwable tr) {
+        return Log.println_native(Log.LOG_ID_CRASH, Log.ERROR, tag,
+                msg + '\n' + Log.getStackTraceString(tr));
+    }
+
     /**
      * Use this to log a message when a thread exits due to an uncaught
      * exception.  The framework catches these for the main threads, so
@@ -68,7 +73,7 @@
                 mCrashing = true;
 
                 if (mApplicationObject == null) {
-                    Slog.e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
+                    Clog_e(TAG, "*** FATAL EXCEPTION IN SYSTEM PROCESS: " + t.getName(), e);
                 } else {
                     StringBuilder message = new StringBuilder();
                     message.append("FATAL EXCEPTION: ").append(t.getName()).append("\n");
@@ -77,7 +82,7 @@
                         message.append("Process: ").append(processName).append(", ");
                     }
                     message.append("PID: ").append(Process.myPid());
-                    Slog.e(TAG, message.toString(), e);
+                    Clog_e(TAG, message.toString(), e);
                 }
 
                 // Bring up crash dialog, wait for it to be dismissed
@@ -85,9 +90,9 @@
                         mApplicationObject, new ApplicationErrorReport.CrashInfo(e));
             } catch (Throwable t2) {
                 try {
-                    Slog.e(TAG, "Error reporting crash", t2);
+                    Clog_e(TAG, "Error reporting crash", t2);
                 } catch (Throwable t3) {
-                    // Even Slog.e() fails!  Oh well.
+                    // Even Clog_e() fails!  Oh well.
                 }
             } finally {
                 // Try everything to make sure this process goes away.
diff --git a/core/java/com/android/internal/os/SomeArgs.java b/core/java/com/android/internal/os/SomeArgs.java
index 6fb72f1..7edf4cc 100644
--- a/core/java/com/android/internal/os/SomeArgs.java
+++ b/core/java/com/android/internal/os/SomeArgs.java
@@ -35,6 +35,11 @@
 
     private boolean mInPool;
 
+    static final int WAIT_NONE = 0;
+    static final int WAIT_WAITING = 1;
+    static final int WAIT_FINISHED = 2;
+    int mWaitState = WAIT_NONE;
+
     public Object arg1;
     public Object arg2;
     public Object arg3;
@@ -70,6 +75,9 @@
         if (mInPool) {
             throw new IllegalStateException("Already recycled.");
         }
+        if (mWaitState != WAIT_NONE) {
+            return;
+        }
         synchronized (sPoolLock) {
             clear();
             if (sPoolSize < MAX_POOL_SIZE) {
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index c5fa0a1..54c532a 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -18,8 +18,8 @@
 
 
 import dalvik.system.ZygoteHooks;
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
+import android.system.ErrnoException;
+import android.system.Os;
 
 /** @hide */
 public final class Zygote {
@@ -141,7 +141,7 @@
     public static void execShell(String command) {
         String[] args = { "/system/bin/sh", "-c", command };
         try {
-            Libcore.os.execv(args[0], args);
+            Os.execv(args[0], args);
         } catch (ErrnoException e) {
             throw new RuntimeException(e);
         }
diff --git a/core/java/com/android/internal/os/ZygoteConnection.java b/core/java/com/android/internal/os/ZygoteConnection.java
index 58a8e62..0c48368 100644
--- a/core/java/com/android/internal/os/ZygoteConnection.java
+++ b/core/java/com/android/internal/os/ZygoteConnection.java
@@ -21,6 +21,8 @@
 import android.os.Process;
 import android.os.SELinux;
 import android.os.SystemProperties;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Log;
 import dalvik.system.PathClassLoader;
 import java.io.BufferedReader;
@@ -34,9 +36,7 @@
 import java.io.PrintStream;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 /**
  * A connection that can make spawn requests.
@@ -186,7 +186,7 @@
             }
 
             if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {
-                FileDescriptor[] pipeFds = Libcore.os.pipe();
+                FileDescriptor[] pipeFds = Os.pipe();
                 childPipeFd = pipeFds[1];
                 serverPipeFd = pipeFds[0];
                 ZygoteInit.setCloseOnExec(serverPipeFd, true);
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index ef2908d..3ea749e 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -16,8 +16,8 @@
 
 package com.android.internal.os;
 
-import static libcore.io.OsConstants.S_IRWXG;
-import static libcore.io.OsConstants.S_IRWXO;
+import static android.system.OsConstants.S_IRWXG;
+import static android.system.OsConstants.S_IRWXO;
 
 import android.content.res.Resources;
 import android.content.res.TypedArray;
@@ -28,14 +28,15 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.OsConstants;
 import android.util.EventLog;
 import android.util.Log;
 
 import dalvik.system.VMRuntime;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
-import libcore.io.OsConstants;
 
 import java.io.BufferedReader;
 import java.io.FileDescriptor;
@@ -195,12 +196,12 @@
                 FileDescriptor fd = sServerSocket.getFileDescriptor();
                 sServerSocket.close();
                 if (fd != null) {
-                    Libcore.os.close(fd);
+                    Os.close(fd);
                 }
             }
         } catch (IOException ex) {
             Log.e(TAG, "Zygote:  error closing sockets", ex);
-        } catch (libcore.io.ErrnoException ex) {
+        } catch (ErrnoException ex) {
             Log.e(TAG, "Zygote:  error closing descriptor", ex);
         }
 
@@ -481,7 +482,7 @@
         closeServerSocket();
 
         // set umask to 0077 so new files and directories will default to owner-only permissions.
-        Libcore.os.umask(S_IRWXG | S_IRWXO);
+        Os.umask(S_IRWXG | S_IRWXO);
 
         if (parsedArgs.niceName != null) {
             Process.setArgV0(parsedArgs.niceName);
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 63ff5a0..b78c70f 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -25,12 +25,24 @@
 interface IKeyguardService {
     boolean isShowing();
     boolean isSecure();
-    boolean isShowingAndNotHidden();
+    boolean isShowingAndNotOccluded();
     boolean isInputRestricted();
     boolean isDismissable();
     oneway void verifyUnlock(IKeyguardExitCallback callback);
     oneway void keyguardDone(boolean authenticated, boolean wakeup);
-    oneway void setHidden(boolean isHidden);
+
+    /**
+     * Sets the Keyguard as occluded when a window dismisses the Keyguard with flag
+     * FLAG_SHOW_ON_LOCK_SCREEN.
+     *
+     * @param isOccluded Whether the Keyguard is occluded by another window.
+     * @return See IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_*. This is needed because
+     *         PhoneWindowManager needs to set these flags immediately and can't wait for the
+     *         Keyguard thread to pick it up. In the hidden case, PhoneWindowManager is solely
+     *         responsible to make sure that the flags are unset.
+     */
+    int setOccluded(boolean isOccluded);
+
     oneway void dismiss();
     oneway void onDreamingStarted();
     oneway void onDreamingStopped();
diff --git a/core/java/com/android/internal/policy/IKeyguardServiceConstants.java b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
new file mode 100644
index 0000000..b88174a
--- /dev/null
+++ b/core/java/com/android/internal/policy/IKeyguardServiceConstants.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.internal.policy;
+
+/**
+ * @hide
+ */
+public class IKeyguardServiceConstants {
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Don't change the keyguard window flags.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE = 0;
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Set the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS = 1;
+
+    /**
+     * Constant for {@link com.android.internal.policy.IKeyguardService#setHidden(boolean)}:
+     * Unset the keyguard window flags to FLAG_SHOW_WALLPAPER and PRIVATE_FLAG_KEYGUARD.
+     */
+    public static final int KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS = 2;
+}
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index dfdb9ae..6428e15 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -47,6 +47,8 @@
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
     void onNotificationClear(String pkg, String tag, int id, int userId);
+    void onNotificationVisibilityChanged(
+            in String[] newlyVisibleKeys, in String[] noLongerVisibleKeys);
     void setSystemUiVisibility(int vis, int mask);
     void setHardKeyboardEnabled(boolean enabled);
     void toggleRecentApps();
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index 02bd4ac..86c9fe3 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -57,10 +57,6 @@
     }
 
     @Override
-    public void dispatchScreenState(boolean on) {
-    }
-
-    @Override
     public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) {
     }
 
diff --git a/core/java/com/android/internal/view/menu/MenuBuilder.java b/core/java/com/android/internal/view/menu/MenuBuilder.java
index b776226..5d7d322 100644
--- a/core/java/com/android/internal/view/menu/MenuBuilder.java
+++ b/core/java/com/android/internal/view/menu/MenuBuilder.java
@@ -392,8 +392,8 @@
     private MenuItem addInternal(int group, int id, int categoryOrder, CharSequence title) {
         final int ordering = getOrdering(categoryOrder);
         
-        final MenuItemImpl item = new MenuItemImpl(this, group, id, categoryOrder,
-                ordering, title, mDefaultShowAsAction);
+        final MenuItemImpl item = createNewMenuItem(group, id, categoryOrder, ordering, title,
+                mDefaultShowAsAction);
 
         if (mCurrentMenuInfo != null) {
             // Pass along the current menu info
@@ -405,7 +405,14 @@
         
         return item;
     }
-    
+
+    // Layoutlib overrides this method to return its custom implementation of MenuItemImpl
+    private MenuItemImpl createNewMenuItem(int group, int id, int categoryOrder, int ordering,
+            CharSequence title, int defaultShowAsAction) {
+        return new MenuItemImpl(this, group, id, categoryOrder, ordering, title,
+                defaultShowAsAction);
+    }
+
     public MenuItem add(CharSequence title) {
         return addInternal(0, 0, 0, title);
     }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index 4504910..2882b54 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -788,13 +788,13 @@
      */
     public int getKeyguardStoredPasswordQuality() {
         int quality =
-                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         // If the user has chosen to use weak biometric sensor, then return the backup locking
         // method and treat biometric as a special case.
         if (quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK) {
             quality =
                 (int) getLong(PASSWORD_TYPE_ALTERNATE_KEY,
-                        DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         }
         return quality;
     }
@@ -804,7 +804,7 @@
      */
     public boolean usingBiometricWeak() {
         int quality =
-                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING);
+                (int) getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED);
         return quality == DevicePolicyManager.PASSWORD_QUALITY_BIOMETRIC_WEAK;
     }
 
@@ -943,11 +943,12 @@
      */
     public boolean isLockPatternEnabled() {
         final boolean backupEnabled =
-                getLong(PASSWORD_TYPE_ALTERNATE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
-                == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
+                getLong(PASSWORD_TYPE_ALTERNATE_KEY,
+                        DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
+                                == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
 
         return getBoolean(Settings.Secure.LOCK_PATTERN_ENABLED, false)
-                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_SOMETHING)
+                && (getLong(PASSWORD_TYPE_KEY, DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED)
                         == DevicePolicyManager.PASSWORD_QUALITY_SOMETHING ||
                         (usingBiometricWeak() && backupEnabled));
     }
diff --git a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
index 961e471..5f3c5f9 100644
--- a/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
+++ b/core/java/com/android/internal/widget/SizeAdaptiveLayout.java
@@ -107,8 +107,6 @@
         }
         if (background instanceof ColorDrawable) {
             mModestyPanel.setBackgroundDrawable(background);
-        } else {
-            mModestyPanel.setBackgroundColor(Color.BLACK);
         }
         SizeAdaptiveLayout.LayoutParams layout =
                 new SizeAdaptiveLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/core/java/com/android/server/SystemService.java b/core/java/com/android/server/SystemService.java
index e374563..bf36bb1 100644
--- a/core/java/com/android/server/SystemService.java
+++ b/core/java/com/android/server/SystemService.java
@@ -123,6 +123,38 @@
     public void onBootPhase(int phase) {}
 
     /**
+     * Called when a new user is starting, for system services to initialize any per-user
+     * state they maintain for running users.
+     * @param userHandle The identifier of the user.
+     */
+    public void onStartUser(int userHandle) {}
+
+    /**
+     * Called when switching to a different foreground user, for system services that have
+     * special behavior for whichever user is currently in the foreground.  This is called
+     * before any application processes are aware of the new user.
+     * @param userHandle The identifier of the user.
+     */
+    public void onSwitchUser(int userHandle) {}
+
+    /**
+     * Called when an existing user is stopping, for system services to finalize any per-user
+     * state they maintain for running users.  This is called prior to sending the SHUTDOWN
+     * broadcast to the user; it is a good place to stop making use of any resources of that
+     * user (such as binding to a service running in the user).
+     * @param userHandle The identifier of the user.
+     */
+    public void onStopUser(int userHandle) {}
+
+    /**
+     * Called when an existing user is stopping, for system services to finalize any per-user
+     * state they maintain for running users.  This is called after all application process
+     * teardown of the user is complete.
+     * @param userHandle The identifier of the user.
+     */
+    public void onCleanupUser(int userHandle) {}
+
+    /**
      * Publish the service so it is accessible to other services and apps.
      */
     protected final void publishBinderService(String name, IBinder service) {
diff --git a/core/java/com/android/server/SystemServiceManager.java b/core/java/com/android/server/SystemServiceManager.java
index eb8df0e..87a50a9 100644
--- a/core/java/com/android/server/SystemServiceManager.java
+++ b/core/java/com/android/server/SystemServiceManager.java
@@ -131,6 +131,58 @@
         }
     }
 
+    public void startUser(final int userHandle) {
+        final int serviceLen = mServices.size();
+        for (int i = 0; i < serviceLen; i++) {
+            final SystemService service = mServices.get(i);
+            try {
+                service.onStartUser(userHandle);
+            } catch (Exception ex) {
+                Slog.wtf(TAG, "Failure reporting start of user " + userHandle
+                        + " to service " + service.getClass().getName(), ex);
+            }
+        }
+    }
+
+    public void switchUser(final int userHandle) {
+        final int serviceLen = mServices.size();
+        for (int i = 0; i < serviceLen; i++) {
+            final SystemService service = mServices.get(i);
+            try {
+                service.onSwitchUser(userHandle);
+            } catch (Exception ex) {
+                Slog.wtf(TAG, "Failure reporting switch of user " + userHandle
+                        + " to service " + service.getClass().getName(), ex);
+            }
+        }
+    }
+
+    public void stopUser(final int userHandle) {
+        final int serviceLen = mServices.size();
+        for (int i = 0; i < serviceLen; i++) {
+            final SystemService service = mServices.get(i);
+            try {
+                service.onStopUser(userHandle);
+            } catch (Exception ex) {
+                Slog.wtf(TAG, "Failure reporting stop of user " + userHandle
+                        + " to service " + service.getClass().getName(), ex);
+            }
+        }
+    }
+
+    public void cleanupUser(final int userHandle) {
+        final int serviceLen = mServices.size();
+        for (int i = 0; i < serviceLen; i++) {
+            final SystemService service = mServices.get(i);
+            try {
+                service.onCleanupUser(userHandle);
+            } catch (Exception ex) {
+                Slog.wtf(TAG, "Failure reporting cleanup of user " + userHandle
+                        + " to service " + service.getClass().getName(), ex);
+            }
+        }
+    }
+
     /** Sets the safe mode flag for services to query. */
     public void setSafeMode(boolean safeMode) {
         mSafeMode = safeMode;
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 711f28a..ee59c8a 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -61,6 +61,7 @@
 	android_view_MotionEvent.cpp \
 	android_view_PointerIcon.cpp \
 	android_view_RenderNode.cpp \
+	android_view_RenderNodeAnimator.cpp \
 	android_view_VelocityTracker.cpp \
 	android_text_AndroidCharacter.cpp \
 	android_text_AndroidBidi.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index aa635c6..f964cd2 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -120,6 +120,7 @@
 extern int register_android_graphics_pdf_PdfDocument(JNIEnv* env);
 extern int register_android_view_DisplayEventReceiver(JNIEnv* env);
 extern int register_android_view_RenderNode(JNIEnv* env);
+extern int register_android_view_RenderNodeAnimator(JNIEnv* env);
 extern int register_android_view_GraphicBuffer(JNIEnv* env);
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_GLRenderer(JNIEnv* env);
@@ -1193,6 +1194,7 @@
     REG_JNI(register_android_graphics_Graphics),
     REG_JNI(register_android_view_DisplayEventReceiver),
     REG_JNI(register_android_view_RenderNode),
+    REG_JNI(register_android_view_RenderNodeAnimator),
     REG_JNI(register_android_view_GraphicBuffer),
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_GLRenderer),
diff --git a/core/jni/android/graphics/Canvas.cpp b/core/jni/android/graphics/Canvas.cpp
index 5148266..2adbf3a 100644
--- a/core/jni/android/graphics/Canvas.cpp
+++ b/core/jni/android/graphics/Canvas.cpp
@@ -509,12 +509,11 @@
     }
 
     static void drawRoundRect(JNIEnv* env, jobject, jlong canvasHandle,
-                              jobject jrect, jfloat rx, jfloat ry,
-                              jlong paintHandle) {
+            jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry,
+            jlong paintHandle) {
         SkCanvas* canvas = reinterpret_cast<SkCanvas*>(canvasHandle);
         SkPaint* paint = reinterpret_cast<SkPaint*>(paintHandle);
-        SkRect rect;
-        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
+        SkRect rect = SkRect::MakeLTRB(left, top, right, bottom);
         canvas->drawRoundRect(rect, rx, ry, *paint);
     }
 
@@ -1176,7 +1175,7 @@
     {"native_drawCircle","(JFFFJ)V", (void*) SkCanvasGlue::drawCircle},
     {"native_drawArc","(JLandroid/graphics/RectF;FFZJ)V",
         (void*) SkCanvasGlue::drawArc},
-    {"native_drawRoundRect","(JLandroid/graphics/RectF;FFJ)V",
+    {"native_drawRoundRect","(JFFFFFFJ)V",
         (void*) SkCanvasGlue::drawRoundRect},
     {"native_drawPath","(JJJ)V", (void*) SkCanvasGlue::drawPath},
     {"native_drawBitmap","(JJFFJIII)V",
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index f77a389..08a88d1 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -357,6 +357,24 @@
         obj->setPaintOptionsAndroid(paintOpts);
     }
 
+    static jboolean isElegantTextHeight(JNIEnv* env, jobject paint) {
+        NPE_CHECK_RETURN_ZERO(env, paint);
+        SkPaint* obj = GraphicsJNI::getNativePaint(env, paint);
+        SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
+        return paintOpts.getFontVariant() == SkPaintOptionsAndroid::kElegant_Variant;
+    }
+
+    static void setElegantTextHeight(JNIEnv* env, jobject paint, jboolean aa) {
+        NPE_CHECK_RETURN_VOID(env, paint);
+        SkPaint* obj = GraphicsJNI::getNativePaint(env, paint);
+        SkPaintOptionsAndroid::FontVariant variant =
+            aa ? SkPaintOptionsAndroid::kElegant_Variant :
+            SkPaintOptionsAndroid::kDefault_Variant;
+        SkPaintOptionsAndroid paintOpts = obj->getPaintOptionsAndroid();
+        paintOpts.setFontVariant(variant);
+        obj->setPaintOptionsAndroid(paintOpts);
+    }
+
     static jfloat getTextSize(JNIEnv* env, jobject paint) {
         NPE_CHECK_RETURN_ZERO(env, paint);
         return SkScalarToFloat(GraphicsJNI::getNativePaint(env, paint)->getTextSize());
@@ -401,10 +419,30 @@
         return SkScalarToFloat(metrics.fDescent);
     }
 
+    static SkScalar getMetricsInternal(SkPaint *paint, SkPaint::FontMetrics *metrics) {
+        const int kElegantTop = 2500;
+        const int kElegantBottom = -1000;
+        const int kElegantAscent = 1946;
+        const int kElegantDescent = -512;
+        const int kElegantLeading = 0;
+        SkScalar spacing = paint->getFontMetrics(metrics);
+        SkPaintOptionsAndroid paintOpts = paint->getPaintOptionsAndroid();
+        if (paintOpts.getFontVariant() == SkPaintOptionsAndroid::kElegant_Variant) {
+            SkScalar size = paint->getTextSize();
+            metrics->fTop = -size * kElegantTop / 2048;
+            metrics->fBottom = -size * kElegantBottom / 2048;
+            metrics->fAscent = -size * kElegantAscent / 2048;
+            metrics->fDescent = -size * kElegantDescent / 2048;
+            metrics->fLeading = size * kElegantLeading / 2048;
+            spacing = metrics->fDescent - metrics->fAscent + metrics->fLeading;
+        }
+        return spacing;
+    }
+
     static jfloat getFontMetrics(JNIEnv* env, jobject paint, jobject metricsObj) {
         NPE_CHECK_RETURN_ZERO(env, paint);
         SkPaint::FontMetrics metrics;
-        SkScalar             spacing = GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
+        SkScalar spacing = getMetricsInternal(GraphicsJNI::getNativePaint(env, paint), &metrics);
 
         if (metricsObj) {
             SkASSERT(env->IsInstanceOf(metricsObj, gFontMetrics_class));
@@ -421,7 +459,7 @@
         NPE_CHECK_RETURN_ZERO(env, paint);
         SkPaint::FontMetrics metrics;
 
-        GraphicsJNI::getNativePaint(env, paint)->getFontMetrics(&metrics);
+        getMetricsInternal(GraphicsJNI::getNativePaint(env, paint), &metrics);
         int ascent = SkScalarRoundToInt(metrics.fAscent);
         int descent = SkScalarRoundToInt(metrics.fDescent);
         int leading = SkScalarRoundToInt(metrics.fLeading);
@@ -894,6 +932,8 @@
     {"native_getTextAlign","(J)I", (void*) SkPaintGlue::getTextAlign},
     {"native_setTextAlign","(JI)V", (void*) SkPaintGlue::setTextAlign},
     {"native_setTextLocale","(JLjava/lang/String;)V", (void*) SkPaintGlue::setTextLocale},
+    {"isElegantTextHeight","()Z", (void*) SkPaintGlue::isElegantTextHeight},
+    {"setElegantTextHeight","(Z)V", (void*) SkPaintGlue::setElegantTextHeight},
     {"getTextSize","()F", (void*) SkPaintGlue::getTextSize},
     {"setTextSize","(F)V", (void*) SkPaintGlue::setTextSize},
     {"getTextScaleX","()F", (void*) SkPaintGlue::getTextScaleX},
diff --git a/core/jni/android/graphics/Path.cpp b/core/jni/android/graphics/Path.cpp
index 1ad1a8a..420a17f 100644
--- a/core/jni/android/graphics/Path.cpp
+++ b/core/jni/android/graphics/Path.cpp
@@ -163,42 +163,35 @@
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         obj->close();
     }
- 
-    static void addRect__RectFI(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect, jint dirHandle) {
-        SkRect rect;
-        SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
-        SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        GraphicsJNI::jrectf_to_rect(env, jrect, &rect);
-        obj->addRect(rect, dir);
-    }
- 
-    static void addRect__FFFFI(JNIEnv* env, jobject clazz, jlong objHandle, jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
+
+    static void addRect(JNIEnv* env, jobject clazz, jlong objHandle,
+            jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
         obj->addRect(left, top, right, bottom, dir);
     }
- 
-    static void addOval(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jint dirHandle) {
+
+    static void addOval(JNIEnv* env, jobject clazz, jlong objHandle,
+            jfloat left, jfloat top, jfloat right, jfloat bottom, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
-        SkRect oval_;
-        GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
-        obj->addOval(oval_, dir);
+        SkRect oval = SkRect::MakeLTRB(left, top, right, bottom);
+        obj->addOval(oval, dir);
     }
- 
+
     static void addCircle(JNIEnv* env, jobject clazz, jlong objHandle, jfloat x, jfloat y, jfloat radius, jint dirHandle) {
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         SkPath::Direction dir = static_cast<SkPath::Direction>(dirHandle);
         obj->addCircle(x, y, radius, dir);
     }
- 
+
     static void addArc(JNIEnv* env, jobject clazz, jlong objHandle, jobject oval, jfloat startAngle, jfloat sweepAngle) {
         SkRect oval_;
         SkPath* obj = reinterpret_cast<SkPath*>(objHandle);
         GraphicsJNI::jrectf_to_rect(env, oval, &oval_);
         obj->addArc(oval_, startAngle, sweepAngle);
     }
- 
+
     static void addRoundRectXY(JNIEnv* env, jobject clazz, jlong objHandle, jobject jrect,
             jfloat rx, jfloat ry, jint dirHandle) {
         SkRect rect;
@@ -496,9 +489,8 @@
     {"native_rCubicTo","(JFFFFFF)V", (void*) SkPathGlue::rCubicTo},
     {"native_arcTo","(JLandroid/graphics/RectF;FFZ)V", (void*) SkPathGlue::arcTo},
     {"native_close","(J)V", (void*) SkPathGlue::close},
-    {"native_addRect","(JLandroid/graphics/RectF;I)V", (void*) SkPathGlue::addRect__RectFI},
-    {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect__FFFFI},
-    {"native_addOval","(JLandroid/graphics/RectF;I)V", (void*) SkPathGlue::addOval},
+    {"native_addRect","(JFFFFI)V", (void*) SkPathGlue::addRect},
+    {"native_addOval","(JFFFFI)V", (void*) SkPathGlue::addOval},
     {"native_addCircle","(JFFFI)V", (void*) SkPathGlue::addCircle},
     {"native_addArc","(JLandroid/graphics/RectF;FF)V", (void*) SkPathGlue::addArc},
     {"native_addRoundRect","(JLandroid/graphics/RectF;FFI)V", (void*) SkPathGlue::addRoundRectXY},
diff --git a/core/jni/android/graphics/Shader.cpp b/core/jni/android/graphics/Shader.cpp
index c5e6053..b389d9e 100644
--- a/core/jni/android/graphics/Shader.cpp
+++ b/core/jni/android/graphics/Shader.cpp
@@ -105,7 +105,7 @@
 #ifdef USE_OPENGL_RENDERER
     SkiaShader* skiaShader = new SkiaBitmapShader(bitmap, shader,
             static_cast<SkShader::TileMode>(tileModeX), static_cast<SkShader::TileMode>(tileModeY),
-            NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            NULL, !shader->isOpaque());
     return reinterpret_cast<jlong>(skiaShader);
 #else
     return NULL;
@@ -205,7 +205,7 @@
 
     SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
             storedPositions, stopCount, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
-            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            !shader->isOpaque());
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     return reinterpret_cast<jlong>(skiaShader);
@@ -232,7 +232,7 @@
 
     SkiaShader* skiaShader = new SkiaLinearGradientShader(storedBounds, storedColors,
             storedPositions, 2, shader, static_cast<SkShader::TileMode>(tileMode), NULL,
-            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            !shader->isOpaque());
 
     return reinterpret_cast<jlong>(skiaShader);
 #else
@@ -330,7 +330,7 @@
 
     SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
             storedPositions, count, shader, (SkShader::TileMode) tileMode, NULL,
-            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            !shader->isOpaque());
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     return reinterpret_cast<jlong>(skiaShader);
@@ -353,7 +353,7 @@
 
     SkiaShader* skiaShader = new SkiaCircularGradientShader(x, y, radius, storedColors,
             storedPositions, 2, shader, (SkShader::TileMode) tileMode, NULL,
-            (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            !shader->isOpaque());
 
     return reinterpret_cast<jlong>(skiaShader);
 #else
@@ -422,7 +422,7 @@
     }
 
     SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, count,
-            shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            shader, NULL, !shader->isOpaque());
 
     env->ReleaseIntArrayElements(colorArray, const_cast<jint*>(colorValues), JNI_ABORT);
     return reinterpret_cast<jlong>(skiaShader);
@@ -444,7 +444,7 @@
     storedColors[1] = static_cast<uint32_t>(color1);
 
     SkiaShader* skiaShader = new SkiaSweepGradientShader(x, y, storedColors, storedPositions, 2,
-            shader, NULL, (shader->getFlags() & SkShader::kOpaqueAlpha_Flag) == 0);
+            shader, NULL, !shader->isOpaque());
 
     return reinterpret_cast<jlong>(skiaShader);
 #else
diff --git a/core/jni/android/graphics/YuvToJpegEncoder.cpp b/core/jni/android/graphics/YuvToJpegEncoder.cpp
index 799782d..6591d60 100644
--- a/core/jni/android/graphics/YuvToJpegEncoder.cpp
+++ b/core/jni/android/graphics/YuvToJpegEncoder.cpp
@@ -226,16 +226,17 @@
     jint* imgOffsets = env->GetIntArrayElements(offsets, NULL);
     jint* imgStrides = env->GetIntArrayElements(strides, NULL);
     YuvToJpegEncoder* encoder = YuvToJpegEncoder::create(format, imgStrides);
-    if (encoder == NULL) {
-        return JNI_FALSE;
+    jboolean result = JNI_FALSE;
+    if (encoder != NULL) {
+        encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality);
+        delete encoder;
+        result = JNI_TRUE;
     }
-    encoder->encode(strm, yuv, width, height, imgOffsets, jpegQuality);
 
-    delete encoder;
     env->ReleaseByteArrayElements(inYuv, yuv, 0);
     env->ReleaseIntArrayElements(offsets, imgOffsets, 0);
     env->ReleaseIntArrayElements(strides, imgStrides, 0);
-    return JNI_TRUE;
+    return result;
 }
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/core/jni/android_database_CursorWindow.cpp b/core/jni/android_database_CursorWindow.cpp
index 67f3879..af6cc72 100644
--- a/core/jni/android_database_CursorWindow.cpp
+++ b/core/jni/android_database_CursorWindow.cpp
@@ -17,6 +17,7 @@
 #undef LOG_TAG
 #define LOG_TAG "CursorWindow"
 
+#include <inttypes.h>
 #include <jni.h>
 #include <JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -225,7 +226,7 @@
     } else if (type == CursorWindow::FIELD_TYPE_INTEGER) {
         int64_t value = window->getFieldSlotValueLong(fieldSlot);
         char buf[32];
-        snprintf(buf, sizeof(buf), "%lld", value);
+        snprintf(buf, sizeof(buf), "%" PRId64, value);
         return env->NewStringUTF(buf);
     } else if (type == CursorWindow::FIELD_TYPE_FLOAT) {
         double value = window->getFieldSlotValueDouble(fieldSlot);
@@ -314,7 +315,7 @@
     } else if (type == CursorWindow::FIELD_TYPE_INTEGER) {
         int64_t value = window->getFieldSlotValueLong(fieldSlot);
         char buf[32];
-        snprintf(buf, sizeof(buf), "%lld", value);
+        snprintf(buf, sizeof(buf), "%" PRId64, value);
         fillCharArrayBufferUTF(env, bufferObj, buf, strlen(buf));
     } else if (type == CursorWindow::FIELD_TYPE_FLOAT) {
         double value = window->getFieldSlotValueDouble(fieldSlot);
diff --git a/core/jni/android_hardware_SensorManager.cpp b/core/jni/android_hardware_SensorManager.cpp
index 24e0b0a..fcf8f83e 100644
--- a/core/jni/android_hardware_SensorManager.cpp
+++ b/core/jni/android_hardware_SensorManager.cpp
@@ -49,6 +49,8 @@
     jfieldID    minDelay;
     jfieldID    fifoReservedEventCount;
     jfieldID    fifoMaxEventCount;
+    jfieldID    stringType;
+    jfieldID    requiredPermission;
 } gSensorOffsets;
 
 
@@ -73,6 +75,9 @@
     sensorOffsets.fifoReservedEventCount =
             _env->GetFieldID(sensorClass, "mFifoReservedEventCount",  "I");
     sensorOffsets.fifoMaxEventCount = _env->GetFieldID(sensorClass, "mFifoMaxEventCount",  "I");
+    sensorOffsets.stringType = _env->GetFieldID(sensorClass, "mStringType", "Ljava/lang/String;");
+    sensorOffsets.requiredPermission = _env->GetFieldID(sensorClass, "mRequiredPermission",
+                                                        "Ljava/lang/String;");
 }
 
 static jint
@@ -89,6 +94,8 @@
     const SensorOffsets& sensorOffsets(gSensorOffsets);
     jstring name = env->NewStringUTF(list->getName().string());
     jstring vendor = env->NewStringUTF(list->getVendor().string());
+    jstring stringType = env->NewStringUTF(list->getStringType().string());
+    jstring requiredPermission = env->NewStringUTF(list->getRequiredPermission().string());
     env->SetObjectField(sensor, sensorOffsets.name,      name);
     env->SetObjectField(sensor, sensorOffsets.vendor,    vendor);
     env->SetIntField(sensor, sensorOffsets.version,      list->getVersion());
@@ -100,7 +107,11 @@
     env->SetIntField(sensor, sensorOffsets.minDelay,     list->getMinDelay());
     env->SetIntField(sensor, sensorOffsets.fifoReservedEventCount,
                      list->getFifoReservedEventCount());
-    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount, list->getFifoMaxEventCount());
+    env->SetIntField(sensor, sensorOffsets.fifoMaxEventCount,
+                     list->getFifoMaxEventCount());
+    env->SetObjectField(sensor, sensorOffsets.stringType, stringType);
+    env->SetObjectField(sensor, sensorOffsets.requiredPermission,
+                        requiredPermission);
     next++;
     return size_t(next) < count ? next : 0;
 }
@@ -149,7 +160,6 @@
         ASensorEvent buffer[16];
         while ((n = q->read(buffer, 16)) > 0) {
             for (int i=0 ; i<n ; i++) {
-
                 if (buffer[i].type == SENSOR_TYPE_STEP_COUNTER) {
                     // step-counter returns a uint64, but the java API only deals with floats
                     float value = float(buffer[i].u64.step_counter);
@@ -172,17 +182,17 @@
                                         buffer[i].vector.status,
                                         buffer[i].timestamp);
                 }
-
                 if (env->ExceptionCheck()) {
+                    mSensorQueue->sendAck(buffer, n);
                     ALOGE("Exception dispatching input event.");
                     return 1;
                 }
             }
+            mSensorQueue->sendAck(buffer, n);
         }
         if (n<0 && n != -EAGAIN) {
             // FIXME: error receiving events, what to do in this case?
         }
-
         return 1;
     }
 };
diff --git a/core/jni/android_net_TrafficStats.cpp b/core/jni/android_net_TrafficStats.cpp
index f904b62..031637f 100644
--- a/core/jni/android_net_TrafficStats.cpp
+++ b/core/jni/android_net_TrafficStats.cpp
@@ -19,6 +19,7 @@
 #include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 
@@ -85,9 +86,9 @@
     uint64_t rxBytes, rxPackets, txBytes, txPackets, tcpRxPackets, tcpTxPackets;
 
     while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-        int matched = sscanf(buffer, "%31s %llu %llu %llu %llu "
-                "%*u %llu %*u %*u %*u %*u "
-                "%*u %llu %*u %*u %*u %*u", cur_iface, &rxBytes,
+        int matched = sscanf(buffer, "%31s %" SCNu64 " %" SCNu64 " %" SCNu64
+                " %" SCNu64 " " "%*u %" SCNu64 " %*u %*u %*u %*u "
+                "%*u %" SCNu64 " %*u %*u %*u %*u", cur_iface, &rxBytes,
                 &rxPackets, &txBytes, &txPackets, &tcpRxPackets, &tcpTxPackets);
         if (matched >= 5) {
             if (matched == 7) {
@@ -129,9 +130,11 @@
     uint64_t tag, rxBytes, rxPackets, txBytes, txPackets;
 
     while (fgets(buffer, sizeof(buffer), fp) != NULL) {
-        if (sscanf(buffer, "%d %31s 0x%llx %u %u %llu %llu %llu %llu", &idx,
-                iface, &tag, &cur_uid, &set, &rxBytes, &rxPackets, &txBytes,
-                &txPackets) == 9) {
+        if (sscanf(buffer,
+                "%" SCNu32 " %31s 0x%" SCNx64 " %u %u %" SCNu64 " %" SCNu64
+                " %" SCNu64 " %" SCNu64 "",
+                &idx, iface, &tag, &cur_uid, &set, &rxBytes, &rxPackets,
+                &txBytes, &txPackets) == 9) {
             if (uid == cur_uid && tag == 0L) {
                 stats->rxBytes += rxBytes;
                 stats->rxPackets += rxPackets;
diff --git a/core/jni/android_os_Debug.cpp b/core/jni/android_os_Debug.cpp
index d4873d6..86207f0 100644
--- a/core/jni/android_os_Debug.cpp
+++ b/core/jni/android_os_Debug.cpp
@@ -24,6 +24,7 @@
 
 #include <cutils/log.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -824,9 +825,9 @@
                 break;
             } else {
 #ifdef __LP64__
-                fprintf(fp, " %016x", backtrace[bt]);
+                fprintf(fp, " %016" PRIxPTR, backtrace[bt]);
 #else
-                fprintf(fp, " %08x", backtrace[bt]);
+                fprintf(fp, " %08" PRIxPTR, backtrace[bt]);
 #endif
             }
         }
diff --git a/core/jni/android_util_Binder.cpp b/core/jni/android_util_Binder.cpp
index 475e926..662af89 100644
--- a/core/jni/android_util_Binder.cpp
+++ b/core/jni/android_util_Binder.cpp
@@ -23,6 +23,7 @@
 #include "JNIHelp.h"
 
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -334,7 +335,7 @@
         if (b == NULL) {
             b = new JavaBBinder(env, obj);
             mBinder = b;
-            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%d\n",
+            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
                  b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
         }
 
@@ -697,9 +698,9 @@
                     "Not allowed to write file descriptors here");
             break;
         default:
-            ALOGE("Unknown binder error code. 0x%x", err);
+            ALOGE("Unknown binder error code. 0x%" PRIx32, err);
             String8 msg;
-            msg.appendFormat("Unknown binder error code. 0x%x", err);
+            msg.appendFormat("Unknown binder error code. 0x%" PRIx32, err);
             // RemoteException is a checked exception, only throw from certain methods.
             jniThrowException(env, canThrowRemoteException
                     ? "android/os/RemoteException" : "java/lang/RuntimeException", msg.string());
@@ -733,7 +734,7 @@
     if (uid > 0 && uid < 999) {
         // In Android currently there are no uids in this range.
         char buf[128];
-        sprintf(buf, "Restoring bad calling ident: 0x%Lx", token);
+        sprintf(buf, "Restoring bad calling ident: 0x%" PRIx64, token);
         jniThrowException(env, "java/lang/IllegalStateException", buf);
         return;
     }
@@ -965,8 +966,8 @@
     jint len = strlen(str);
     int space_needed = 1 + sizeof(len) + len;
     if (end - *pos < space_needed) {
-        ALOGW("not enough space for string. remain=%d; needed=%d",
-             (end - *pos), space_needed);
+        ALOGW("not enough space for string. remain=%" PRIdPTR "; needed=%d",
+             end - *pos, space_needed);
         return false;
     }
     **pos = EVENT_TYPE_STRING;
@@ -981,8 +982,8 @@
 static bool push_eventlog_int(char** pos, const char* end, jint val) {
     int space_needed = 1 + sizeof(val);
     if (end - *pos < space_needed) {
-        ALOGW("not enough space for int.  remain=%d; needed=%d",
-             (end - *pos), space_needed);
+        ALOGW("not enough space for int.  remain=%" PRIdPTR "; needed=%d",
+             end - *pos, space_needed);
         return false;
     }
     **pos = EVENT_TYPE_INT;
@@ -1068,7 +1069,7 @@
         return JNI_FALSE;
     }
 
-    ALOGV("Java code calling transact on %p in Java object %p with code %d\n",
+    ALOGV("Java code calling transact on %p in Java object %p with code %" PRId32 "\n",
             target, obj, code);
 
 #if ENABLE_BINDER_SAMPLE
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index a4efed7..01f4d3a 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -30,15 +30,16 @@
 #include "android_util_Binder.h"
 #include "JNIHelp.h"
 
-#include <sys/errno.h>
-#include <sys/resource.h>
-#include <sys/types.h>
-#include <sys/stat.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <inttypes.h>
 #include <pwd.h>
 #include <signal.h>
+#include <sys/errno.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <sys/types.h>
 #include <unistd.h>
 
 #define POLICY_DEBUG 0
@@ -159,7 +160,7 @@
 
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int tid, jint grp)
 {
-    ALOGV("%s tid=%d grp=%d", __func__, tid, grp);
+    ALOGV("%s tid=%d grp=%" PRId32, __func__, tid, grp);
     SchedPolicy sp = (SchedPolicy) grp;
     int res = set_sched_policy(tid, sp);
     if (res != NO_ERROR) {
@@ -169,7 +170,7 @@
 
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
-    ALOGV("%s pid=%d grp=%d", __func__, pid, grp);
+    ALOGV("%s pid=%d grp=%" PRId32, __func__, pid, grp);
     DIR *d;
     FILE *fp;
     char proc_path[255];
@@ -322,7 +323,7 @@
         }
     }
 
-    //ALOGI("Setting priority of %d: %d, getpriority returns %d\n",
+    //ALOGI("Setting priority of %" PRId32 ": %" PRId32 ", getpriority returns %d\n",
     //     pid, pri, getpriority(PRIO_PROCESS, pid));
 }
 
@@ -340,7 +341,7 @@
     if (errno != 0) {
         signalExceptionForPriorityError(env, errno);
     }
-    //ALOGI("Returning priority of %d: %d\n", pid, pri);
+    //ALOGI("Returning priority of %" PRId32 ": %" PRId32 "\n", pid, pri);
     return pri;
 }
 
@@ -362,7 +363,7 @@
 
     int fd = open(text, O_WRONLY);
     if (fd >= 0) {
-        sprintf(text, "%d", pid);
+        sprintf(text, "%" PRId32, pid);
         write(fd, text, strlen(text));
         close(fd);
     }
@@ -403,7 +404,7 @@
 
 static int pid_compare(const void* v1, const void* v2)
 {
-    //ALOGI("Compare %d vs %d\n", *((const jint*)v1), *((const jint*)v2));
+    //ALOGI("Compare %" PRId32 " vs %" PRId32 "\n", *((const jint*)v1), *((const jint*)v2));
     return *((const jint*)v1) - *((const jint*)v2);
 }
 
@@ -517,7 +518,7 @@
         return;
     }
 
-    //ALOGI("Clearing %d sizes", count);
+    //ALOGI("Clearing %" PRId32 " sizes", count);
     for (i=0; i<count; i++) {
         sizesArray[i] = 0;
     }
@@ -556,7 +557,7 @@
                     }
                     char* end;
                     sizesArray[i] = strtoll(num, &end, 10);
-                    //ALOGI("Field %s = %d", field.string(), sizesArray[i]);
+                    //ALOGI("Field %s = %" PRId64, field.string(), sizesArray[i]);
                     foundCount++;
                     break;
                 }
@@ -758,7 +759,7 @@
             }
         }
 
-        //ALOGI("Field %d: %d-%d dest=%d mode=0x%x\n", i, start, end, di, mode);
+        //ALOGI("Field %" PRId32 ": %" PRId32 "-%" PRId32 " dest=%" PRId32 " mode=0x%" PRIx32 "\n", i, start, end, di, mode);
 
         if ((mode&(PROC_OUT_FLOAT|PROC_OUT_LONG|PROC_OUT_STRING)) != 0) {
             char c = buffer[end];
@@ -857,7 +858,7 @@
 void android_os_Process_sendSignal(JNIEnv* env, jobject clazz, jint pid, jint sig)
 {
     if (pid > 0) {
-        ALOGI("Sending signal. PID: %d SIG: %d", pid, sig);
+        ALOGI("Sending signal. PID: %" PRId32 " SIG: %" PRId32, pid, sig);
         kill(pid, sig);
     }
 }
@@ -887,7 +888,7 @@
 {
     char filename[64];
 
-    snprintf(filename, sizeof(filename), "/proc/%d/smaps", pid);
+    snprintf(filename, sizeof(filename), "/proc/%" PRId32 "/smaps", pid);
 
     FILE * file = fopen(filename, "r");
     if (!file) {
@@ -899,7 +900,7 @@
     jlong pss = 0;
     while (fgets(line, sizeof(line), file)) {
         jlong v;
-        if (sscanf(line, "Pss: %lld kB", &v) == 1) {
+        if (sscanf(line, "Pss: %" SCNd64 " kB", &v) == 1) {
             pss += v;
         }
     }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index e72aff9..ef5ebd0 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -287,7 +287,7 @@
         jlong rendererPtr, jlong paintPtr, jint saveFlags) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
     SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr);
-    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
     return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom,
             paint, saveFlags);
 }
@@ -302,7 +302,7 @@
 static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jint alpha, jint saveFlags) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
     return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom,
             alpha, saveFlags);
 }
@@ -356,7 +356,7 @@
 static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jobject rect) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    const android::uirenderer::Rect& bounds(renderer->getClipBounds());
+    const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds());
 
     env->CallVoidMethod(rect, gRectClassInfo.set,
             int(bounds.left), int(bounds.top), int(bounds.right), int(bounds.bottom));
@@ -870,8 +870,7 @@
     return reinterpret_cast<jlong>(renderer->finishRecording());
 }
 
-static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env,
-        jobject clazz) {
+static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jobject clazz) {
     return reinterpret_cast<jlong>(new DisplayListRenderer);
 }
 
@@ -893,18 +892,6 @@
 // Layers
 // ----------------------------------------------------------------------------
 
-static void android_view_GLES20Canvas_interrupt(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    renderer->interrupt();
-}
-
-static void android_view_GLES20Canvas_resume(JNIEnv* env, jobject clazz,
-        jlong rendererPtr) {
-    OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
-    renderer->resume();
-}
-
 static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
         jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) {
     OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr);
@@ -1093,9 +1080,6 @@
 
     { "nCreateDisplayListRenderer", "()J",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
 
-    { "nInterrupt",              "(J)V",       (void*) android_view_GLES20Canvas_interrupt },
-    { "nResume",                 "(J)V",       (void*) android_view_GLES20Canvas_resume },
-
     { "nDrawLayer",              "(JJFF)V",    (void*) android_view_GLES20Canvas_drawLayer },
     { "nCopyLayer",              "(JJ)Z",      (void*) android_view_GLES20Canvas_copyLayer },
     { "nClearLayerUpdates",      "(J)V",       (void*) android_view_GLES20Canvas_clearLayerUpdates },
diff --git a/core/jni/android_view_GLRenderer.cpp b/core/jni/android_view_GLRenderer.cpp
index 180c625..d0269a3 100644
--- a/core/jni/android_view_GLRenderer.cpp
+++ b/core/jni/android_view_GLRenderer.cpp
@@ -142,19 +142,12 @@
     LayerRenderer::destroyLayer(layer);
 }
 
-static void android_view_GLRenderer_setDisplayListData(JNIEnv* env, jobject clazz,
-        jlong displayListPtr, jlong newDataPtr) {
-    using namespace android::uirenderer;
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
-    displayList->setData(newData);
-}
-
-static void android_view_GLRenderer_updateRenderNodeProperties(JNIEnv* env, jobject clazz,
+static void android_view_GLRenderer_prepareTree(JNIEnv* env, jobject clazz,
         jlong renderNodePtr) {
     using namespace android::uirenderer;
     RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
-    renderNode->updateProperties();
+    TreeInfo ignoredInfo;
+    renderNode->prepareTree(ignoredInfo);
 }
 
 static void android_view_GLRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
@@ -195,8 +188,7 @@
 
     { "getSystemTime",         "()J",   (void*) android_view_GLRenderer_getSystemTime },
     { "nDestroyLayer",         "(J)V",  (void*) android_view_GLRenderer_destroyLayer },
-    { "nSetDisplayListData",  "(JJ)V", (void*) android_view_GLRenderer_setDisplayListData },
-    { "nUpdateRenderNodeProperties", "(J)V", (void*) android_view_GLRenderer_updateRenderNodeProperties },
+    { "nPrepareTree", "(J)V", (void*) android_view_GLRenderer_prepareTree },
     { "nInvokeFunctor",        "(JZ)V", (void*) android_view_GLRenderer_invokeFunctor },
 #endif
 
diff --git a/core/jni/android_view_HardwareLayer.cpp b/core/jni/android_view_HardwareLayer.cpp
index 4bf5f78..b2f17de 100644
--- a/core/jni/android_view_HardwareLayer.cpp
+++ b/core/jni/android_view_HardwareLayer.cpp
@@ -127,7 +127,8 @@
 static jboolean android_view_HardwareLayer_flushChanges(JNIEnv* env, jobject clazz,
         jlong layerUpdaterPtr) {
     DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerUpdaterPtr);
-    return layer->apply();
+    TreeInfo ignoredInfo;
+    return layer->apply(ignoredInfo);
 }
 
 static jlong android_view_HardwareLayer_getLayer(JNIEnv* env, jobject clazz,
diff --git a/core/jni/android_view_KeyEvent.cpp b/core/jni/android_view_KeyEvent.cpp
index c83541d..7ae21a7 100644
--- a/core/jni/android_view_KeyEvent.cpp
+++ b/core/jni/android_view_KeyEvent.cpp
@@ -22,6 +22,7 @@
 #include <android_runtime/Log.h>
 #include <utils/Log.h>
 #include <input/Input.h>
+#include <ScopedUtfChars.h>
 #include "android_view_KeyEvent.h"
 
 namespace android {
@@ -102,20 +103,25 @@
     return OK;
 }
 
-static jboolean native_isSystemKey(JNIEnv* env, jobject clazz, jint keyCode) {
-    return KeyEvent::isSystemKey(keyCode);
+static jstring android_view_KeyEvent_nativeKeyCodeToString(JNIEnv* env, jobject clazz,
+        jint keyCode) {
+    return env->NewStringUTF(KeyEvent::getLabel(keyCode));
 }
 
-static jboolean native_hasDefaultAction(JNIEnv* env, jobject clazz, jint keyCode) {
-    return KeyEvent::hasDefaultAction(keyCode);
+static jint android_view_KeyEvent_nativeKeyCodeFromString(JNIEnv* env, jobject clazz,
+        jstring label) {
+    ScopedUtfChars keyLabel(env, label);
+    return KeyEvent::getKeyCodeFromLabel(keyLabel.c_str());
 }
 
 
 // ----------------------------------------------------------------------------
 
 static const JNINativeMethod g_methods[] = {
-    { "native_isSystemKey", "(I)Z", (void*)native_isSystemKey },
-    { "native_hasDefaultAction", "(I)Z", (void*)native_hasDefaultAction },
+    { "nativeKeyCodeToString", "(I)Ljava/lang/String;",
+        (void*)android_view_KeyEvent_nativeKeyCodeToString},
+    { "nativeKeyCodeFromString", "(Ljava/lang/String;)I",
+        (void*)android_view_KeyEvent_nativeKeyCodeFromString},
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/core/jni/android_view_MotionEvent.cpp b/core/jni/android_view_MotionEvent.cpp
index 76e145b..6ae02e0 100644
--- a/core/jni/android_view_MotionEvent.cpp
+++ b/core/jni/android_view_MotionEvent.cpp
@@ -23,6 +23,7 @@
 #include <android_runtime/Log.h>
 #include <utils/Log.h>
 #include <input/Input.h>
+#include <ScopedUtfChars.h>
 #include "android_os_Parcel.h"
 #include "android_view_MotionEvent.h"
 #include "android_util_Binder.h"
@@ -724,6 +725,17 @@
     }
 }
 
+static jstring android_view_MotionEvent_nativeAxisToString(JNIEnv* env, jclass clazz,
+        jint axis) {
+    return env->NewStringUTF(MotionEvent::getLabel(static_cast<int32_t>(axis)));
+}
+
+static jint android_view_MotionEvent_nativeAxisFromString(JNIEnv* env, jclass clazz,
+        jstring label) {
+    ScopedUtfChars axisLabel(env, label);
+    return static_cast<jint>(MotionEvent::getAxisFromLabel(axisLabel.c_str()));
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gMotionEventMethods[] = {
@@ -840,6 +852,10 @@
     { "nativeWriteToParcel",
             "(JLandroid/os/Parcel;)V",
             (void*)android_view_MotionEvent_nativeWriteToParcel },
+    { "nativeAxisToString", "(I)Ljava/lang/String;",
+            (void*)android_view_MotionEvent_nativeAxisToString },
+    { "nativeAxisFromString", "(Ljava/lang/String;)I",
+            (void*)android_view_MotionEvent_nativeAxisFromString },
 };
 
 #define FIND_CLASS(var, className) \
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index cf95657..4715c26 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -23,6 +23,7 @@
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
 
+#include <Animator.h>
 #include <DisplayListRenderer.h>
 #include <RenderNode.h>
 
@@ -41,32 +42,34 @@
 // DisplayList view properties
 // ----------------------------------------------------------------------------
 
-static void android_view_RenderNode_setDisplayListName(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jstring name) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+static void android_view_RenderNode_output(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->output();
+}
+
+static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz, jstring name) {
+    RenderNode* renderNode = new RenderNode();
+    renderNode->incStrong(0);
     if (name != NULL) {
         const char* textArray = env->GetStringUTFChars(name, NULL);
-        displayList->setName(textArray);
+        renderNode->setName(textArray);
         env->ReleaseStringUTFChars(name, textArray);
     }
+    return reinterpret_cast<jlong>(renderNode);
 }
 
-static void android_view_RenderNode_output(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->output();
+static void android_view_RenderNode_destroyRenderNode(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->decStrong(0);
 }
 
-static jlong android_view_RenderNode_create(JNIEnv* env, jobject clazz) {
-    RenderNode* displayList = new RenderNode();
-    displayList->incStrong(0);
-    return reinterpret_cast<jlong>(displayList);
-}
-
-static void android_view_RenderNode_destroyDisplayList(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->decStrong(0);
+static void android_view_RenderNode_setDisplayListData(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr, jlong newDataPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
+    renderNode->setStagingDisplayList(newData);
 }
 
 // ----------------------------------------------------------------------------
@@ -74,201 +77,207 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_RenderNode_setCaching(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean caching) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setCaching(caching);
+        jobject clazz, jlong renderNodePtr, jboolean caching) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setCaching(caching);
 }
 
 static void android_view_RenderNode_setStaticMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong matrixPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+        jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    displayList->mutateStagingProperties().setStaticMatrix(matrix);
+    renderNode->mutateStagingProperties().setStaticMatrix(matrix);
 }
 
 static void android_view_RenderNode_setAnimationMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong matrixPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+        jobject clazz, jlong renderNodePtr, jlong matrixPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr);
-    displayList->mutateStagingProperties().setAnimationMatrix(matrix);
+    renderNode->mutateStagingProperties().setAnimationMatrix(matrix);
 }
 
 static void android_view_RenderNode_setClipToBounds(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean clipToBounds) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setClipToBounds(clipToBounds);
+        jobject clazz, jlong renderNodePtr, jboolean clipToBounds) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setClipToBounds(clipToBounds);
 }
 
 static void android_view_RenderNode_setProjectBackwards(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean shouldProject) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setProjectBackwards(shouldProject);
+        jobject clazz, jlong renderNodePtr, jboolean shouldProject) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setProjectBackwards(shouldProject);
 }
 
 static void android_view_RenderNode_setProjectionReceiver(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean shouldRecieve) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
+        jobject clazz, jlong renderNodePtr, jboolean shouldRecieve) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setProjectionReceiver(shouldRecieve);
 }
 
 static void android_view_RenderNode_setOutlineRoundRect(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jint left, jint top,
+        jobject clazz, jlong renderNodePtr, jint left, jint top,
         jint right, jint bottom, jfloat radius) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
-    displayList->mutateStagingProperties().updateClipPath();
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().mutableOutline().setRoundRect(left, top, right, bottom, radius);
+    renderNode->mutateStagingProperties().updateClipPath();
 }
 
 static void android_view_RenderNode_setOutlineConvexPath(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong outlinePathPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+        jobject clazz, jlong renderNodePtr, jlong outlinePathPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkPath* outlinePath = reinterpret_cast<SkPath*>(outlinePathPtr);
-    displayList->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
-    displayList->mutateStagingProperties().updateClipPath();
+    renderNode->mutateStagingProperties().mutableOutline().setConvexPath(outlinePath);
+    renderNode->mutateStagingProperties().updateClipPath();
 }
 
 static void android_view_RenderNode_setOutlineEmpty(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().mutableOutline().setEmpty();
-    displayList->mutateStagingProperties().updateClipPath();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().mutableOutline().setEmpty();
+    renderNode->mutateStagingProperties().updateClipPath();
 }
 
 static void android_view_RenderNode_setClipToOutline(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean clipToOutline) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
-    displayList->mutateStagingProperties().updateClipPath();
+        jobject clazz, jlong renderNodePtr, jboolean clipToOutline) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().mutableOutline().setShouldClip(clipToOutline);
+    renderNode->mutateStagingProperties().updateClipPath();
 }
 
 static void android_view_RenderNode_setRevealClip(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean shouldClip, jboolean inverseClip,
+        jobject clazz, jlong renderNodePtr, jboolean shouldClip, jboolean inverseClip,
         jfloat x, jfloat y, jfloat radius) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().mutableRevealClip().set(
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().mutableRevealClip().set(
             shouldClip, inverseClip, x, y, radius);
-    displayList->mutateStagingProperties().updateClipPath();
+    renderNode->mutateStagingProperties().updateClipPath();
 }
 
 static void android_view_RenderNode_setAlpha(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float alpha) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setAlpha(alpha);
+        jobject clazz, jlong renderNodePtr, float alpha) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setAlpha(alpha);
 }
 
 static void android_view_RenderNode_setHasOverlappingRendering(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, bool hasOverlappingRendering) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
+        jobject clazz, jlong renderNodePtr, bool hasOverlappingRendering) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setHasOverlappingRendering(hasOverlappingRendering);
+}
+
+static void android_view_RenderNode_setElevation(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr, float elevation) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setElevation(elevation);
 }
 
 static void android_view_RenderNode_setTranslationX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float tx) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setTranslationX(tx);
+        jobject clazz, jlong renderNodePtr, float tx) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setTranslationX(tx);
 }
 
 static void android_view_RenderNode_setTranslationY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float ty) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setTranslationY(ty);
+        jobject clazz, jlong renderNodePtr, float ty) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setTranslationY(ty);
 }
 
 static void android_view_RenderNode_setTranslationZ(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float tz) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setTranslationZ(tz);
+        jobject clazz, jlong renderNodePtr, float tz) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setTranslationZ(tz);
 }
 
 static void android_view_RenderNode_setRotation(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float rotation) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setRotation(rotation);
+        jobject clazz, jlong renderNodePtr, float rotation) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setRotation(rotation);
 }
 
 static void android_view_RenderNode_setRotationX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float rx) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setRotationX(rx);
+        jobject clazz, jlong renderNodePtr, float rx) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setRotationX(rx);
 }
 
 static void android_view_RenderNode_setRotationY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float ry) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setRotationY(ry);
+        jobject clazz, jlong renderNodePtr, float ry) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setRotationY(ry);
 }
 
 static void android_view_RenderNode_setScaleX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float sx) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setScaleX(sx);
+        jobject clazz, jlong renderNodePtr, float sx) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setScaleX(sx);
 }
 
 static void android_view_RenderNode_setScaleY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float sy) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setScaleY(sy);
+        jobject clazz, jlong renderNodePtr, float sy) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setScaleY(sy);
 }
 
 static void android_view_RenderNode_setPivotX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float px) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setPivotX(px);
+        jobject clazz, jlong renderNodePtr, float px) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setPivotX(px);
 }
 
 static void android_view_RenderNode_setPivotY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float py) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setPivotY(py);
+        jobject clazz, jlong renderNodePtr, float py) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setPivotY(py);
 }
 
 static void android_view_RenderNode_setCameraDistance(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float distance) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setCameraDistance(distance);
+        jobject clazz, jlong renderNodePtr, float distance) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setCameraDistance(distance);
 }
 
 static void android_view_RenderNode_setLeft(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, int left) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setLeft(left);
+        jobject clazz, jlong renderNodePtr, int left) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setLeft(left);
 }
 
 static void android_view_RenderNode_setTop(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, int top) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setTop(top);
+        jobject clazz, jlong renderNodePtr, int top) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setTop(top);
 }
 
 static void android_view_RenderNode_setRight(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, int right) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setRight(right);
+        jobject clazz, jlong renderNodePtr, int right) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setRight(right);
 }
 
 static void android_view_RenderNode_setBottom(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, int bottom) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setBottom(bottom);
+        jobject clazz, jlong renderNodePtr, int bottom) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setBottom(bottom);
 }
 
 static void android_view_RenderNode_setLeftTopRightBottom(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, int left, int top,
+        jobject clazz, jlong renderNodePtr, int left, int top,
         int right, int bottom) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().setLeftTopRightBottom(left, top, right, bottom);
 }
 
 static void android_view_RenderNode_offsetLeftAndRight(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float offset) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().offsetLeftRight(offset);
+        jobject clazz, jlong renderNodePtr, float offset) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().offsetLeftRight(offset);
 }
 
 static void android_view_RenderNode_offsetTopAndBottom(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, float offset) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().offsetTopBottom(offset);
+        jobject clazz, jlong renderNodePtr, float offset) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().offsetTopBottom(offset);
 }
 
 // ----------------------------------------------------------------------------
@@ -276,105 +285,112 @@
 // ----------------------------------------------------------------------------
 
 static jboolean android_view_RenderNode_hasOverlappingRendering(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().hasOverlappingRendering();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().hasOverlappingRendering();
 }
 
 static jfloat android_view_RenderNode_getAlpha(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getAlpha();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getAlpha();
 }
 
 static jfloat android_view_RenderNode_getLeft(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getLeft();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getLeft();
 }
 
 static jfloat android_view_RenderNode_getTop(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getTop();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getTop();
 }
 
 static jfloat android_view_RenderNode_getRight(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getRight();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getRight();
 }
 
 static jfloat android_view_RenderNode_getBottom(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getBottom();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getBottom();
 }
 
 static jfloat android_view_RenderNode_getCameraDistance(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getCameraDistance();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getCameraDistance();
 }
 
 static jfloat android_view_RenderNode_getScaleX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getScaleX();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getScaleX();
 }
 
 static jfloat android_view_RenderNode_getScaleY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getScaleY();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getScaleY();
+}
+
+static jfloat android_view_RenderNode_getElevation(JNIEnv* env,
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getElevation();
 }
 
 static jfloat android_view_RenderNode_getTranslationX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getTranslationX();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getTranslationX();
 }
 
 static jfloat android_view_RenderNode_getTranslationY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getTranslationY();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getTranslationY();
 }
 
 static jfloat android_view_RenderNode_getTranslationZ(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getTranslationZ();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getTranslationZ();
 }
 
 static jfloat android_view_RenderNode_getRotation(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getRotation();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getRotation();
 }
 
 static jfloat android_view_RenderNode_getRotationX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getRotationX();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getRotationX();
 }
 
 static jfloat android_view_RenderNode_getRotationY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getRotationY();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().getRotationY();
 }
 
 static jboolean android_view_RenderNode_isPivotExplicitlySet(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().isPivotExplicitlySet();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    return renderNode->stagingProperties().isPivotExplicitlySet();
 }
 
 static jboolean android_view_RenderNode_hasIdentityMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    return displayList->stagingProperties().getMatrixFlags() == 0;
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().updateMatrix();
+    return !renderNode->stagingProperties().hasTransformMatrix();
 }
 
 // ----------------------------------------------------------------------------
@@ -382,17 +398,14 @@
 // ----------------------------------------------------------------------------
 
 static void android_view_RenderNode_getTransformMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
+        jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
 
-    displayList->mutateStagingProperties().updateMatrix();
-    const SkMatrix* transformMatrix = displayList->stagingProperties().getTransformMatrix();
+    renderNode->mutateStagingProperties().updateMatrix();
+    const SkMatrix* transformMatrix = renderNode->stagingProperties().getTransformMatrix();
 
-    if (displayList->stagingProperties().getMatrixFlags() == TRANSLATION) {
-        outMatrix->setTranslate(displayList->stagingProperties().getTranslationX(),
-                displayList->stagingProperties().getTranslationY());
-    } else if (transformMatrix) {
+    if (transformMatrix) {
         *outMatrix = *transformMatrix;
     } else {
         outMatrix->setIdentity();
@@ -400,9 +413,9 @@
 }
 
 static void android_view_RenderNode_getInverseTransformMatrix(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jlong outMatrixPtr) {
+        jobject clazz, jlong renderNodePtr, jlong outMatrixPtr) {
     // load transform matrix
-    android_view_RenderNode_getTransformMatrix(env, clazz, displayListPtr, outMatrixPtr);
+    android_view_RenderNode_getTransformMatrix(env, clazz, renderNodePtr, outMatrixPtr);
     SkMatrix* outMatrix = reinterpret_cast<SkMatrix*>(outMatrixPtr);
 
     // return it inverted
@@ -413,19 +426,38 @@
 }
 
 static jfloat android_view_RenderNode_getPivotX(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().updateMatrix();
-    return displayList->stagingProperties().getPivotX();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().updateMatrix();
+    return renderNode->stagingProperties().getPivotX();
 }
 
 static jfloat android_view_RenderNode_getPivotY(JNIEnv* env,
-        jobject clazz, jlong displayListPtr) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->mutateStagingProperties().updateMatrix();
-    return displayList->stagingProperties().getPivotY();
+        jobject clazz, jlong renderNodePtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    renderNode->mutateStagingProperties().updateMatrix();
+    return renderNode->stagingProperties().getPivotY();
 }
 
+// ----------------------------------------------------------------------------
+// RenderProperties - Animations
+// ----------------------------------------------------------------------------
+
+static void android_view_RenderNode_addAnimator(JNIEnv* env, jobject clazz,
+        jlong renderNodePtr, jlong animatorPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
+    renderNode->addAnimator(animator);
+}
+
+static void android_view_RenderNode_removeAnimator(JNIEnv* env, jobject clazz,
+        jlong renderNodePtr, jlong animatorPtr) {
+    RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr);
+    RenderPropertyAnimator* animator = reinterpret_cast<RenderPropertyAnimator*>(animatorPtr);
+    renderNode->removeAnimator(animator);
+}
+
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -436,10 +468,9 @@
 
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
-    { "nCreate",               "()J",    (void*) android_view_RenderNode_create },
-    { "nDestroyDisplayList",   "(J)V",   (void*) android_view_RenderNode_destroyDisplayList },
-    { "nSetDisplayListName",   "(JLjava/lang/String;)V",
-            (void*) android_view_RenderNode_setDisplayListName },
+    { "nCreate",               "(Ljava/lang/String;)J",    (void*) android_view_RenderNode_create },
+    { "nDestroyRenderNode",   "(J)V",   (void*) android_view_RenderNode_destroyRenderNode },
+    { "nSetDisplayListData",   "(JJ)V", (void*) android_view_RenderNode_setDisplayListData },
     { "nOutput",               "(J)V",  (void*) android_view_RenderNode_output },
 
     { "nSetCaching",           "(JZ)V",  (void*) android_view_RenderNode_setCaching },
@@ -458,6 +489,7 @@
     { "nSetAlpha",             "(JF)V",  (void*) android_view_RenderNode_setAlpha },
     { "nSetHasOverlappingRendering", "(JZ)V",
             (void*) android_view_RenderNode_setHasOverlappingRendering },
+    { "nSetElevation",         "(JF)V",  (void*) android_view_RenderNode_setElevation },
     { "nSetTranslationX",      "(JF)V",  (void*) android_view_RenderNode_setTranslationX },
     { "nSetTranslationY",      "(JF)V",  (void*) android_view_RenderNode_setTranslationY },
     { "nSetTranslationZ",      "(JF)V",  (void*) android_view_RenderNode_setTranslationZ },
@@ -486,6 +518,7 @@
     { "nGetCameraDistance",       "(J)F",  (void*) android_view_RenderNode_getCameraDistance },
     { "nGetScaleX",               "(J)F",  (void*) android_view_RenderNode_getScaleX },
     { "nGetScaleY",               "(J)F",  (void*) android_view_RenderNode_getScaleY },
+    { "nGetElevation",            "(J)F",  (void*) android_view_RenderNode_getElevation },
     { "nGetTranslationX",         "(J)F",  (void*) android_view_RenderNode_getTranslationX },
     { "nGetTranslationY",         "(J)F",  (void*) android_view_RenderNode_getTranslationY },
     { "nGetTranslationZ",         "(J)F",  (void*) android_view_RenderNode_getTranslationZ },
@@ -500,6 +533,9 @@
 
     { "nGetPivotX",                "(J)F",  (void*) android_view_RenderNode_getPivotX },
     { "nGetPivotY",                "(J)F",  (void*) android_view_RenderNode_getPivotY },
+
+    { "nAddAnimator",              "(JJ)V", (void*) android_view_RenderNode_addAnimator },
+    { "nRemoveAnimator",           "(JJ)V", (void*) android_view_RenderNode_removeAnimator },
 #endif
 };
 
diff --git a/core/jni/android_view_RenderNodeAnimator.cpp b/core/jni/android_view_RenderNodeAnimator.cpp
new file mode 100644
index 0000000..b92c992
--- /dev/null
+++ b/core/jni/android_view_RenderNodeAnimator.cpp
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#define LOG_TAG "OpenGLRenderer"
+
+#include "android_view_RenderNodeAnimator.h"
+
+#include "jni.h"
+#include "GraphicsJNI.h"
+#include <nativehelper/JNIHelp.h>
+#include <android_runtime/AndroidRuntime.h>
+
+#include <Animator.h>
+#include <Interpolator.h>
+#include <RenderProperties.h>
+
+namespace android {
+
+using namespace uirenderer;
+
+static struct {
+    jclass clazz;
+
+    jmethodID callOnFinished;
+} gRenderNodeAnimatorClassInfo;
+
+#ifdef USE_OPENGL_RENDERER
+
+static JNIEnv* getEnv(JavaVM* vm) {
+    JNIEnv* env;
+    if (vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6) != JNI_OK) {
+        return 0;
+    }
+    return env;
+}
+
+RenderNodeAnimator::RenderNodeAnimator(JNIEnv* env, jobject weakThis,
+                RenderProperty property, DeltaValueType deltaType, float delta)
+        : RenderPropertyAnimator(property, deltaType, delta) {
+    mWeakThis = env->NewGlobalRef(weakThis);
+    env->GetJavaVM(&mJvm);
+}
+
+RenderNodeAnimator::~RenderNodeAnimator() {
+    JNIEnv* env = getEnv(mJvm);
+    env->DeleteGlobalRef(mWeakThis);
+    mWeakThis = NULL;
+}
+
+void RenderNodeAnimator::callOnFinished() {
+    JNIEnv* env = getEnv(mJvm);
+    env->CallStaticVoidMethod(
+            gRenderNodeAnimatorClassInfo.clazz,
+            gRenderNodeAnimatorClassInfo.callOnFinished,
+            mWeakThis);
+}
+
+static jlong createAnimator(JNIEnv* env, jobject clazz, jobject weakThis,
+        jint property, jint deltaType, jfloat deltaValue) {
+    LOG_ALWAYS_FATAL_IF(property < 0 || property > RenderNodeAnimator::ALPHA,
+            "Invalid property %d", property);
+    LOG_ALWAYS_FATAL_IF(deltaType != RenderPropertyAnimator::DELTA
+            && deltaType != RenderPropertyAnimator::ABSOLUTE,
+            "Invalid delta type %d", deltaType);
+
+    RenderNodeAnimator* animator = new RenderNodeAnimator(env, weakThis,
+            static_cast<RenderPropertyAnimator::RenderProperty>(property),
+            static_cast<RenderPropertyAnimator::DeltaValueType>(deltaType),
+            deltaValue);
+    animator->incStrong(0);
+    return reinterpret_cast<jlong>( animator );
+}
+
+static void setDuration(JNIEnv* env, jobject clazz, jlong animatorPtr, jint duration) {
+    LOG_ALWAYS_FATAL_IF(duration < 0, "Duration cannot be negative");
+    RenderNodeAnimator* animator = reinterpret_cast<RenderNodeAnimator*>(animatorPtr);
+    animator->setDuration(duration);
+}
+
+static void unref(JNIEnv* env, jobject clazz, jlong objPtr) {
+    VirtualLightRefBase* obj = reinterpret_cast<VirtualLightRefBase*>(objPtr);
+    obj->decStrong(0);
+}
+
+#endif
+
+// ----------------------------------------------------------------------------
+// JNI Glue
+// ----------------------------------------------------------------------------
+
+const char* const kClassPathName = "android/view/RenderNodeAnimator";
+
+static JNINativeMethod gMethods[] = {
+#ifdef USE_OPENGL_RENDERER
+    { "nCreateAnimator", "(Ljava/lang/ref/WeakReference;IIF)J", (void*) createAnimator },
+    { "nSetDuration", "(JI)V", (void*) setDuration },
+    { "nUnref", "(J)V", (void*) unref },
+#endif
+};
+
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className);
+
+#define GET_STATIC_METHOD_ID(var, clazz, methodName, methodDescriptor) \
+        var = env->GetStaticMethodID(clazz, methodName, methodDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find method " methodName);
+
+int register_android_view_RenderNodeAnimator(JNIEnv* env) {
+    FIND_CLASS(gRenderNodeAnimatorClassInfo.clazz, kClassPathName);
+    gRenderNodeAnimatorClassInfo.clazz = jclass(env->NewGlobalRef(gRenderNodeAnimatorClassInfo.clazz));
+
+    GET_STATIC_METHOD_ID(gRenderNodeAnimatorClassInfo.callOnFinished, gRenderNodeAnimatorClassInfo.clazz,
+            "callOnFinished", "(Ljava/lang/ref/WeakReference;)V");
+
+    return AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods));
+}
+
+
+} // namespace android
diff --git a/core/jni/android_view_RenderNodeAnimator.h b/core/jni/android_view_RenderNodeAnimator.h
new file mode 100644
index 0000000..760ca91
--- /dev/null
+++ b/core/jni/android_view_RenderNodeAnimator.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2012 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"
+
+#ifdef USE_OPENGL_RENDERER
+
+#include <Animator.h>
+
+namespace android {
+
+class RenderNodeAnimator : public uirenderer::RenderPropertyAnimator {
+public:
+    RenderNodeAnimator(JNIEnv* env, jobject callbackObject,
+            RenderProperty property, DeltaValueType deltaType, float delta);
+    virtual ~RenderNodeAnimator();
+
+    void callOnFinished();
+
+private:
+    JavaVM* mJvm;
+    jobject mWeakThis;
+};
+
+}
+
+#endif
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index 159ffb2..c293c7a 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -34,6 +34,7 @@
 #include <gui/SurfaceComposerClient.h>
 
 #include <ui/DisplayInfo.h>
+#include <ui/FrameStats.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -64,6 +65,16 @@
     delete ((ScreenshotClient*) context);
 }
 
+static struct {
+    nsecs_t UNDEFINED_TIME_NANO;
+    jmethodID init;
+} gWindowContentFrameStatsClassInfo;
+
+static struct {
+    nsecs_t UNDEFINED_TIME_NANO;
+    jmethodID init;
+} gWindowAnimationFrameStatsClassInfo;
+
 // ----------------------------------------------------------------------------
 
 static jlong nativeCreate(JNIEnv* env, jclass clazz, jobject sessionObj,
@@ -371,6 +382,151 @@
     SurfaceComposerClient::unblankDisplay(token);
 }
 
+static jboolean nativeClearContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->clearLayerFrameStats();
+
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+
+    // The other end is not ready, just report we failed.
+    if (err == NO_INIT) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+static jboolean nativeGetContentFrameStats(JNIEnv* env, jclass clazz, jlong nativeObject,
+    jobject outStats) {
+    FrameStats stats;
+
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->getLayerFrameStats(&stats);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+
+    // The other end is not ready, fine just return empty stats.
+    if (err == NO_INIT) {
+        return JNI_FALSE;
+    }
+
+    jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+    size_t frameCount = stats.desiredPresentTimesNano.size();
+
+    jlongArray postedTimesNanoDst = env->NewLongArray(frameCount);
+    if (postedTimesNanoDst == NULL) {
+        return JNI_FALSE;
+    }
+
+    jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+    if (presentedTimesNanoDst == NULL) {
+        return JNI_FALSE;
+    }
+
+    jlongArray readyTimesNanoDst = env->NewLongArray(frameCount);
+    if (readyTimesNanoDst == NULL) {
+        return JNI_FALSE;
+    }
+
+    nsecs_t postedTimesNanoSrc[frameCount];
+    nsecs_t presentedTimesNanoSrc[frameCount];
+    nsecs_t readyTimesNanoSrc[frameCount];
+
+    for (size_t i = 0; i < frameCount; i++) {
+        nsecs_t postedTimeNano = stats.desiredPresentTimesNano[i];
+        if (postedTimeNano == INT64_MAX) {
+            postedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+        }
+        postedTimesNanoSrc[i] = postedTimeNano;
+
+        nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
+        if (presentedTimeNano == INT64_MAX) {
+            presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+        }
+        presentedTimesNanoSrc[i] = presentedTimeNano;
+
+        nsecs_t readyTimeNano = stats.frameReadyTimesNano[i];
+        if (readyTimeNano == INT64_MAX) {
+            readyTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+        }
+        readyTimesNanoSrc[i] = readyTimeNano;
+    }
+
+    env->SetLongArrayRegion(postedTimesNanoDst, 0, frameCount, postedTimesNanoSrc);
+    env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+    env->SetLongArrayRegion(readyTimesNanoDst, 0, frameCount, readyTimesNanoSrc);
+
+    env->CallVoidMethod(outStats, gWindowContentFrameStatsClassInfo.init, refreshPeriodNano,
+            postedTimesNanoDst, presentedTimesNanoDst, readyTimesNanoDst);
+
+    if (env->ExceptionCheck()) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+static jboolean nativeClearAnimationFrameStats(JNIEnv* env, jclass clazz) {
+    status_t err = SurfaceComposerClient::clearAnimationFrameStats();
+
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+
+    // The other end is not ready, just report we failed.
+    if (err == NO_INIT) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
+static jboolean nativeGetAnimationFrameStats(JNIEnv* env, jclass clazz, jobject outStats) {
+    FrameStats stats;
+
+    status_t err = SurfaceComposerClient::getAnimationFrameStats(&stats);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+
+    // The other end is not ready, fine just return empty stats.
+    if (err == NO_INIT) {
+        return JNI_FALSE;
+    }
+
+    jlong refreshPeriodNano = static_cast<jlong>(stats.refreshPeriodNano);
+    size_t frameCount = stats.desiredPresentTimesNano.size();
+
+    jlongArray presentedTimesNanoDst = env->NewLongArray(frameCount);
+    if (presentedTimesNanoDst == NULL) {
+        return JNI_FALSE;
+    }
+
+    nsecs_t presentedTimesNanoSrc[frameCount];
+
+    for (size_t i = 0; i < frameCount; i++) {
+        nsecs_t presentedTimeNano = stats.actualPresentTimesNano[i];
+        if (presentedTimeNano == INT64_MAX) {
+            presentedTimeNano = gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO;
+        }
+        presentedTimesNanoSrc[i] = presentedTimeNano;
+    }
+
+    env->SetLongArrayRegion(presentedTimesNanoDst, 0, frameCount, presentedTimesNanoSrc);
+
+    env->CallVoidMethod(outStats, gWindowAnimationFrameStatsClassInfo.init, refreshPeriodNano,
+            presentedTimesNanoDst);
+
+    if (env->ExceptionCheck()) {
+        return JNI_FALSE;
+    }
+
+    return JNI_TRUE;
+}
+
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod sSurfaceControlMethods[] = {
@@ -426,6 +582,14 @@
             (void*)nativeBlankDisplay },
     {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
             (void*)nativeUnblankDisplay },
+    {"nativeClearContentFrameStats", "(J)Z",
+            (void*)nativeClearContentFrameStats },
+    {"nativeGetContentFrameStats", "(JLandroid/view/WindowContentFrameStats;)Z",
+            (void*)nativeGetContentFrameStats },
+    {"nativeClearAnimationFrameStats", "()Z",
+            (void*)nativeClearAnimationFrameStats },
+    {"nativeGetAnimationFrameStats", "(Landroid/view/WindowAnimationFrameStats;)Z",
+            (void*)nativeGetAnimationFrameStats },
 };
 
 int register_android_view_SurfaceControl(JNIEnv* env)
@@ -441,6 +605,19 @@
     gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
     gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
     gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+
+    jclass frameStatsClazz = env->FindClass("android/view/FrameStats");
+    jfieldID undefined_time_nano_field =  env->GetStaticFieldID(frameStatsClazz, "UNDEFINED_TIME_NANO", "J");
+    nsecs_t undefined_time_nano = env->GetStaticLongField(frameStatsClazz, undefined_time_nano_field);
+
+    jclass contFrameStatsClazz = env->FindClass("android/view/WindowContentFrameStats");
+    gWindowContentFrameStatsClassInfo.init =  env->GetMethodID(contFrameStatsClazz, "init", "(J[J[J[J)V");
+    gWindowContentFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
+    jclass animFrameStatsClazz = env->FindClass("android/view/WindowAnimationFrameStats");
+    gWindowAnimationFrameStatsClassInfo.init =  env->GetMethodID(animFrameStatsClazz, "init", "(J[J)V");
+    gWindowAnimationFrameStatsClassInfo.UNDEFINED_TIME_NANO = undefined_time_nano;
+
     return err;
 }
 
diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp
index 20a61bf..58fc1e1 100644
--- a/core/jni/android_view_ThreadedRenderer.cpp
+++ b/core/jni/android_view_ThreadedRenderer.cpp
@@ -16,6 +16,8 @@
 
 #define LOG_TAG "ThreadedRenderer"
 
+#include <algorithm>
+
 #include "jni.h"
 #include <nativehelper/JNIHelp.h>
 #include <android_runtime/AndroidRuntime.h>
@@ -24,6 +26,8 @@
 #include <android_runtime/android_view_Surface.h>
 #include <system/window.h>
 
+#include "android_view_RenderNodeAnimator.h"
+#include <RenderNode.h>
 #include <renderthread/RenderProxy.h>
 #include <renderthread/RenderTask.h>
 #include <renderthread/RenderThread.h>
@@ -63,15 +67,75 @@
     jobject mRunnable;
 };
 
+class InvokeAnimationListeners : public MessageHandler {
+public:
+    InvokeAnimationListeners(std::vector< sp<RenderNodeAnimator> >& animators) {
+        mAnimators.swap(animators);
+    }
+
+    static void callOnFinished(const sp<RenderNodeAnimator>& animator) {
+        animator->callOnFinished();
+    }
+
+    virtual void handleMessage(const Message& message) {
+        std::for_each(mAnimators.begin(), mAnimators.end(), callOnFinished);
+        mAnimators.clear();
+    }
+
+private:
+    std::vector< sp<RenderNodeAnimator> > mAnimators;
+};
+
+class RootRenderNode : public RenderNode, public AnimationListener {
+public:
+    RootRenderNode() : RenderNode() {
+        mLooper = Looper::getForThread();
+        LOG_ALWAYS_FATAL_IF(!mLooper.get(),
+                "Must create RootRenderNode on a thread with a looper!");
+    }
+
+    virtual ~RootRenderNode() {}
+
+    void onAnimationFinished(const sp<RenderPropertyAnimator>& animator) {
+        mFinishedAnimators.push_back(
+                reinterpret_cast<RenderNodeAnimator*>(animator.get()));
+    }
+
+    virtual void prepareTree(TreeInfo& info) {
+        info.animationListener = this;
+        RenderNode::prepareTree(info);
+        info.animationListener = NULL;
+
+        // post all the finished stuff
+        if (mFinishedAnimators.size()) {
+            sp<InvokeAnimationListeners> message
+                    = new InvokeAnimationListeners(mFinishedAnimators);
+            mLooper->sendMessage(message, 0);
+        }
+    }
+
+private:
+    sp<Looper> mLooper;
+    std::vector< sp<RenderNodeAnimator> > mFinishedAnimators;
+};
+
 static void android_view_ThreadedRenderer_postToRenderThread(JNIEnv* env, jobject clazz,
         jobject jrunnable) {
     RenderTask* task = new JavaTask(env, jrunnable);
     RenderThread::getInstance().queue(task);
 }
 
+static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) {
+    RootRenderNode* node = new RootRenderNode();
+    node->incStrong(0);
+    node->setName("RootRenderNode");
+    return reinterpret_cast<jlong>(node);
+}
+
 static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject clazz,
-        jboolean translucent) {
-    return (jlong) new RenderProxy(translucent);
+        jboolean translucent, jlong rootRenderNodePtr) {
+    RenderNode* rootRenderNode = reinterpret_cast<RenderNode*>(rootRenderNodePtr);
+    return (jlong) new RenderProxy(translucent, rootRenderNode);
 }
 
 static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz,
@@ -113,40 +177,17 @@
     proxy->setup(width, height);
 }
 
-static void android_view_ThreadedRenderer_setDisplayListData(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong displayListPtr, jlong newDataPtr) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    DisplayListData* newData = reinterpret_cast<DisplayListData*>(newDataPtr);
-    proxy->setDisplayListData(displayList, newData);
-}
-
-static void android_view_ThreadedRenderer_drawDisplayList(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong displayListPtr, jint dirtyLeft, jint dirtyTop,
+static void android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
+        jlong proxyPtr, jint dirtyLeft, jint dirtyTop,
         jint dirtyRight, jint dirtyBottom) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    proxy->drawDisplayList(displayList, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
+    proxy->syncAndDrawFrame(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
 }
 
-static void android_view_ThreadedRenderer_destroyCanvas(JNIEnv* env, jobject clazz,
+static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, jobject clazz,
         jlong proxyPtr) {
     RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    proxy->destroyCanvas();
-}
-
-static void android_view_ThreadedRenderer_attachFunctor(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong functorPtr) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    proxy->attachFunctor(functor);
-}
-
-static void android_view_ThreadedRenderer_detachFunctor(JNIEnv* env, jobject clazz,
-        jlong proxyPtr, jlong functorPtr) {
-    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
-    Functor* functor = reinterpret_cast<Functor*>(functorPtr);
-    proxy->detachFunctor(functor);
+    proxy->destroyCanvasAndSurface();
 }
 
 static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz,
@@ -209,17 +250,15 @@
 static JNINativeMethod gMethods[] = {
 #ifdef USE_OPENGL_RENDERER
     { "postToRenderThread", "(Ljava/lang/Runnable;)V",   (void*) android_view_ThreadedRenderer_postToRenderThread },
-    { "nCreateProxy", "(Z)J", (void*) android_view_ThreadedRenderer_createProxy },
+    { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode },
+    { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy },
     { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy },
     { "nInitialize", "(JLandroid/view/Surface;)Z", (void*) android_view_ThreadedRenderer_initialize },
     { "nUpdateSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_updateSurface },
     { "nPauseSurface", "(JLandroid/view/Surface;)V", (void*) android_view_ThreadedRenderer_pauseSurface },
     { "nSetup", "(JII)V", (void*) android_view_ThreadedRenderer_setup },
-    { "nSetDisplayListData", "(JJJ)V", (void*) android_view_ThreadedRenderer_setDisplayListData },
-    { "nDrawDisplayList", "(JJIIII)V", (void*) android_view_ThreadedRenderer_drawDisplayList },
-    { "nDestroyCanvas", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvas },
-    { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor },
-    { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor },
+    { "nSyncAndDrawFrame", "(JIIII)V", (void*) android_view_ThreadedRenderer_syncAndDrawFrame },
+    { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface },
     { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor },
     { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext },
     { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer },
diff --git a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
index a860918..230658f 100644
--- a/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
+++ b/core/jni/com_android_internal_content_NativeLibraryHelper.cpp
@@ -19,11 +19,12 @@
 
 #include <android_runtime/AndroidRuntime.h>
 
-#include <utils/Log.h>
-#include <androidfw/ZipFileRO.h>
-#include <androidfw/ZipUtils.h>
 #include <ScopedUtfChars.h>
 #include <UniquePtr.h>
+#include <androidfw/ZipFileRO.h>
+#include <androidfw/ZipUtils.h>
+#include <utils/Log.h>
+#include <utils/Vector.h>
 
 #include <zlib.h>
 
@@ -54,17 +55,19 @@
 namespace android {
 
 // These match PackageManager.java install codes
-typedef enum {
+enum install_status_t {
     INSTALL_SUCCEEDED = 1,
     INSTALL_FAILED_INVALID_APK = -2,
     INSTALL_FAILED_INSUFFICIENT_STORAGE = -4,
     INSTALL_FAILED_CONTAINER_ERROR = -18,
     INSTALL_FAILED_INTERNAL_ERROR = -110,
-} install_status_t;
+    INSTALL_FAILED_NO_MATCHING_ABIS = -113,
+    NO_NATIVE_LIBRARIES = -114
+};
 
 typedef install_status_t (*iterFunc)(JNIEnv*, void*, ZipFileRO*, ZipEntryRO, const char*);
 
-// Equivalent to isFilenameSafe
+// Equivalent to android.os.FileUtils.isFilenameSafe
 static bool
 isFilenameSafe(const char* filename)
 {
@@ -268,126 +271,252 @@
     return INSTALL_SUCCEEDED;
 }
 
-static install_status_t
-iterateOverNativeFiles(JNIEnv *env, jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2,
-        iterFunc callFunc, void* callArg) {
-    ScopedUtfChars filePath(env, javaFilePath);
-    ScopedUtfChars cpuAbi(env, javaCpuAbi);
-    ScopedUtfChars cpuAbi2(env, javaCpuAbi2);
-
-    UniquePtr<ZipFileRO> zipFile(ZipFileRO::open(filePath.c_str()));
-    if (zipFile.get() == NULL) {
-        ALOGI("Couldn't open APK %s\n", filePath.c_str());
-        return INSTALL_FAILED_INVALID_APK;
+/*
+ * An iterator over all shared libraries in a zip file. An entry is
+ * considered to be a shared library if all of the conditions below are
+ * satisfied :
+ *
+ * - The entry is under the lib/ directory.
+ * - The entry name ends with ".so" and the entry name starts with "lib",
+ *   an exception is made for entries whose name is "gdbserver".
+ * - The entry filename is "safe" (as determined by isFilenameSafe).
+ *
+ */
+class NativeLibrariesIterator {
+private:
+    NativeLibrariesIterator(ZipFileRO* zipFile, void* cookie)
+        : mZipFile(zipFile), mCookie(cookie), mLastSlash(NULL) {
+        fileName[0] = '\0';
     }
 
+public:
+    static NativeLibrariesIterator* create(ZipFileRO* zipFile) {
+        void* cookie = NULL;
+        if (!zipFile->startIteration(&cookie)) {
+            return NULL;
+        }
+
+        return new NativeLibrariesIterator(zipFile, cookie);
+    }
+
+    ZipEntryRO next() {
+        ZipEntryRO next = NULL;
+        while ((next = mZipFile->nextEntry(mCookie)) != NULL) {
+            // Make sure this entry has a filename.
+            if (mZipFile->getEntryFileName(next, fileName, sizeof(fileName))) {
+                continue;
+            }
+
+            // Make sure we're in the lib directory of the ZIP.
+            if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
+                continue;
+            }
+
+            // Make sure the filename is at least to the minimum library name size.
+            const size_t fileNameLen = strlen(fileName);
+            static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
+            if (fileNameLen < minLength) {
+                continue;
+            }
+
+            const char* lastSlash = strrchr(fileName, '/');
+            ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
+
+            // Exception: If we find the gdbserver binary, return it.
+            if (!strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
+                break;
+            }
+
+            // Make sure the filename starts with lib and ends with ".so".
+            if (strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
+                || strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)) {
+                continue;
+            }
+
+            // Make sure the filename is safe.
+            if (!isFilenameSafe(lastSlash + 1)) {
+                continue;
+            }
+
+            mLastSlash = lastSlash;
+            break;
+        }
+
+        return next;
+    }
+
+    inline const char* currentEntry() const {
+        return fileName;
+    }
+
+    inline const char* lastSlash() const {
+        return mLastSlash;
+    }
+
+    virtual ~NativeLibrariesIterator() {
+        mZipFile->endIteration(mCookie);
+    }
+private:
+
     char fileName[PATH_MAX];
-    bool hasPrimaryAbi = false;
+    ZipFileRO* const mZipFile;
+    void* mCookie;
+    const char* mLastSlash;
+};
 
-    void* cookie = NULL;
-    if (!zipFile->startIteration(&cookie)) {
-        ALOGI("Couldn't iterate over APK%s\n", filePath.c_str());
+static install_status_t
+iterateOverNativeFiles(JNIEnv *env, jlong apkHandle, jstring javaCpuAbi,
+                       iterFunc callFunc, void* callArg) {
+    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+    if (zipFile == NULL) {
         return INSTALL_FAILED_INVALID_APK;
     }
 
+    UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
+    if (it.get() == NULL) {
+        return INSTALL_FAILED_INVALID_APK;
+    }
+
+    const ScopedUtfChars cpuAbi(env, javaCpuAbi);
+    if (cpuAbi.c_str() == NULL) {
+        // This would've thrown, so this return code isn't observable by
+        // Java.
+        return INSTALL_FAILED_INVALID_APK;
+    }
     ZipEntryRO entry = NULL;
-    while ((entry = zipFile->nextEntry(cookie)) != NULL) {
-        // Make sure this entry has a filename.
-        if (zipFile->getEntryFileName(entry, fileName, sizeof(fileName))) {
-            continue;
-        }
-
-        // Make sure we're in the lib directory of the ZIP.
-        if (strncmp(fileName, APK_LIB, APK_LIB_LEN)) {
-            continue;
-        }
-
-        // Make sure the filename is at least to the minimum library name size.
-        const size_t fileNameLen = strlen(fileName);
-        static const size_t minLength = APK_LIB_LEN + 2 + LIB_PREFIX_LEN + 1 + LIB_SUFFIX_LEN;
-        if (fileNameLen < minLength) {
-            continue;
-        }
-
-        const char* lastSlash = strrchr(fileName, '/');
-        ALOG_ASSERT(lastSlash != NULL, "last slash was null somehow for %s\n", fileName);
+    while ((entry = it->next()) != NULL) {
+        const char* fileName = it->currentEntry();
+        const char* lastSlash = it->lastSlash();
 
         // Check to make sure the CPU ABI of this file is one we support.
         const char* cpuAbiOffset = fileName + APK_LIB_LEN;
         const size_t cpuAbiRegionSize = lastSlash - cpuAbiOffset;
 
-        ALOGV("Comparing ABIs %s and %s versus %s\n", cpuAbi.c_str(), cpuAbi2.c_str(), cpuAbiOffset);
-        if (cpuAbi.size() == cpuAbiRegionSize
-                && *(cpuAbiOffset + cpuAbi.size()) == '/'
-                && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
-            ALOGV("Using primary ABI %s\n", cpuAbi.c_str());
-            hasPrimaryAbi = true;
-        } else if (cpuAbi2.size() == cpuAbiRegionSize
-                && *(cpuAbiOffset + cpuAbi2.size()) == '/'
-                && !strncmp(cpuAbiOffset, cpuAbi2.c_str(), cpuAbiRegionSize)) {
-
-            /*
-             * If this library matches both the primary and secondary ABIs,
-             * only use the primary ABI.
-             */
-            if (hasPrimaryAbi) {
-                ALOGV("Already saw primary ABI, skipping secondary ABI %s\n", cpuAbi2.c_str());
-                continue;
-            } else {
-                ALOGV("Using secondary ABI %s\n", cpuAbi2.c_str());
-            }
-        } else {
-            ALOGV("abi didn't match anything: %s (end at %zd)\n", cpuAbiOffset, cpuAbiRegionSize);
-            continue;
-        }
-
-        // If this is a .so file, check to see if we need to copy it.
-        if ((!strncmp(fileName + fileNameLen - LIB_SUFFIX_LEN, LIB_SUFFIX, LIB_SUFFIX_LEN)
-                    && !strncmp(lastSlash, LIB_PREFIX, LIB_PREFIX_LEN)
-                    && isFilenameSafe(lastSlash + 1))
-                || !strncmp(lastSlash + 1, GDBSERVER, GDBSERVER_LEN)) {
-
-            install_status_t ret = callFunc(env, callArg, zipFile.get(), entry, lastSlash + 1);
+        if (cpuAbi.size() == cpuAbiRegionSize && !strncmp(cpuAbiOffset, cpuAbi.c_str(), cpuAbiRegionSize)) {
+            install_status_t ret = callFunc(env, callArg, zipFile, entry, lastSlash + 1);
 
             if (ret != INSTALL_SUCCEEDED) {
                 ALOGV("Failure for entry %s", lastSlash + 1);
-                zipFile->endIteration(cookie);
                 return ret;
             }
         }
     }
 
-    zipFile->endIteration(cookie);
-
     return INSTALL_SUCCEEDED;
 }
 
+
+static int findSupportedAbi(JNIEnv *env, jlong apkHandle, jobjectArray supportedAbisArray) {
+    const int numAbis = env->GetArrayLength(supportedAbisArray);
+    Vector<ScopedUtfChars*> supportedAbis;
+
+    for (int i = 0; i < numAbis; ++i) {
+        supportedAbis.add(new ScopedUtfChars(env,
+            (jstring) env->GetObjectArrayElement(supportedAbisArray, i)));
+    }
+
+    ZipFileRO* zipFile = reinterpret_cast<ZipFileRO*>(apkHandle);
+    if (zipFile == NULL) {
+        return INSTALL_FAILED_INVALID_APK;
+    }
+
+    UniquePtr<NativeLibrariesIterator> it(NativeLibrariesIterator::create(zipFile));
+    if (it.get() == NULL) {
+        return INSTALL_FAILED_INVALID_APK;
+    }
+
+    ZipEntryRO entry = NULL;
+    char fileName[PATH_MAX];
+    int status = NO_NATIVE_LIBRARIES;
+    while ((entry = it->next()) != NULL) {
+        // We're currently in the lib/ directory of the APK, so it does have some native
+        // code. We should return INSTALL_FAILED_NO_MATCHING_ABIS if none of the
+        // libraries match.
+        if (status == NO_NATIVE_LIBRARIES) {
+            status = INSTALL_FAILED_NO_MATCHING_ABIS;
+        }
+
+        const char* fileName = it->currentEntry();
+        const char* lastSlash = it->lastSlash();
+
+        // Check to see if this CPU ABI matches what we are looking for.
+        const char* abiOffset = fileName + APK_LIB_LEN;
+        const size_t abiSize = lastSlash - abiOffset;
+        for (int i = 0; i < numAbis; i++) {
+            const ScopedUtfChars* abi = supportedAbis[i];
+            if (abi->size() == abiSize && !strncmp(abiOffset, abi->c_str(), abiSize)) {
+                // The entry that comes in first (i.e. with a lower index) has the higher priority.
+                if (((i < status) && (status >= 0)) || (status < 0) ) {
+                    status = i;
+                }
+            }
+        }
+    }
+
+    for (int i = 0; i < numAbis; ++i) {
+        delete supportedAbis[i];
+    }
+
+    return status;
+}
+
 static jint
 com_android_internal_content_NativeLibraryHelper_copyNativeBinaries(JNIEnv *env, jclass clazz,
-        jstring javaFilePath, jstring javaNativeLibPath, jstring javaCpuAbi, jstring javaCpuAbi2)
+        jlong apkHandle, jstring javaNativeLibPath, jstring javaCpuAbi)
 {
-    return (jint) iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2,
+    return (jint) iterateOverNativeFiles(env, apkHandle, javaCpuAbi,
             copyFileIfChanged, &javaNativeLibPath);
 }
 
 static jlong
 com_android_internal_content_NativeLibraryHelper_sumNativeBinaries(JNIEnv *env, jclass clazz,
-        jstring javaFilePath, jstring javaCpuAbi, jstring javaCpuAbi2)
+        jlong apkHandle, jstring javaCpuAbi)
 {
     size_t totalSize = 0;
 
-    iterateOverNativeFiles(env, javaFilePath, javaCpuAbi, javaCpuAbi2, sumFiles, &totalSize);
+    iterateOverNativeFiles(env, apkHandle, javaCpuAbi, sumFiles, &totalSize);
 
     return totalSize;
 }
 
+static jint
+com_android_internal_content_NativeLibraryHelper_findSupportedAbi(JNIEnv *env, jclass clazz,
+        jlong apkHandle, jobjectArray javaCpuAbisToSearch)
+{
+    return (jint) findSupportedAbi(env, apkHandle, javaCpuAbisToSearch);
+}
+
+static jlong
+com_android_internal_content_NativeLibraryHelper_openApk(JNIEnv *env, jclass, jstring apkPath)
+{
+    ScopedUtfChars filePath(env, apkPath);
+    ZipFileRO* zipFile = ZipFileRO::open(filePath.c_str());
+
+    return reinterpret_cast<jlong>(zipFile);
+}
+
+static void
+com_android_internal_content_NativeLibraryHelper_close(JNIEnv *env, jclass, jlong apkHandle)
+{
+    delete reinterpret_cast<ZipFileRO*>(apkHandle);
+}
+
 static JNINativeMethod gMethods[] = {
+    {"nativeOpenApk",
+            "(Ljava/lang/String;)J",
+            (void *)com_android_internal_content_NativeLibraryHelper_openApk},
+    {"nativeClose",
+            "(J)V",
+            (void *)com_android_internal_content_NativeLibraryHelper_close},
     {"nativeCopyNativeBinaries",
-            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
+            "(JLjava/lang/String;Ljava/lang/String;)I",
             (void *)com_android_internal_content_NativeLibraryHelper_copyNativeBinaries},
     {"nativeSumNativeBinaries",
-            "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
+            "(JLjava/lang/String;)J",
             (void *)com_android_internal_content_NativeLibraryHelper_sumNativeBinaries},
+    {"nativeFindSupportedAbi",
+            "(J[Ljava/lang/String;)I",
+            (void *)com_android_internal_content_NativeLibraryHelper_findSupportedAbi},
 };
 
 
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index a61fa87..c58bf04 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -92,14 +92,10 @@
     if (WIFEXITED(status)) {
       if (WEXITSTATUS(status)) {
         ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
-      } else if (false) {
-        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
       }
     } else if (WIFSIGNALED(status)) {
       if (WTERMSIG(status) != SIGKILL) {
-        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
-      } else if (false) {
-        ALOGI("Process %d exited cleanly (%d)", pid, WTERMSIG(status));
+        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
       }
 #ifdef WCOREDUMP
       if (WCOREDUMP(status)) {
@@ -117,8 +113,10 @@
     }
   }
 
-  if (pid < 0) {
-    ALOGW("Zygote SIGCHLD error in waitpid: %d", errno);
+  // Note that we shouldn't consider ECHILD an error because
+  // the secondary zygote might have no children left to wait for.
+  if (pid < 0 && errno != ECHILD) {
+    ALOGW("Zygote SIGCHLD error in waitpid: %s", strerror(errno));
   }
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 0f772f1..3d3e86f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -234,10 +234,12 @@
     <protected-broadcast android:name="android.net.conn.NETWORK_CONDITIONS_MEASURED" />
     <protected-broadcast
             android:name="android.net.ConnectivityService.action.PKT_CNT_SAMPLE_INTERVAL_ELAPSED" />
+    <protected-broadcast android:name="android.net.scoring.SCORE_NETWORKS" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_AVAILABLE" />
     <protected-broadcast android:name="android.intent.action.EXTERNAL_APPLICATIONS_UNAVAILABLE" />
     <protected-broadcast android:name="android.intent.action.AIRPLANE_MODE" />
     <protected-broadcast android:name="android.intent.action.ADVANCED_SETTINGS" />
+    <protected-broadcast android:name="android.intent.action.APPLICATION_RESTRICTIONS_CHANGED" />
     <protected-broadcast android:name="android.intent.action.BUGREPORT_FINISHED" />
 
     <protected-broadcast android:name="android.intent.action.ACTION_IDLE_MAINTENANCE_START" />
@@ -483,6 +485,13 @@
         android:label="@string/permlab_writeProfile"
         android:description="@string/permdesc_writeProfile" />
 
+    <!-- Allows an application to access data from sensors that the user uses to
+         measure what is happening inside his/her body, such as heart rate. -->
+    <permission android:name="android.permission.BODY_SENSORS"
+        android:permissionGroup="android.permission-group.PERSONAL_INFO"
+        android:label="@string/permlab_bodySensors"
+        android:description="@string/permdesc_bodySensors" />
+
     <!-- =============================================================== -->
     <!-- Permissions for accessing the device calendar                   -->
     <!-- =============================================================== -->
@@ -755,6 +764,13 @@
         android:description="@string/permdesc_changeWimaxState"
         android:label="@string/permlab_changeWimaxState" />
 
+    <!-- Allows applications to act as network scorers. @hide -->
+    <permission android:name="android.permission.SCORE_NETWORKS"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="normal"
+        android:description="@string/permdesc_scoreNetworks"
+        android:label="@string/permlab_scoreNetworks" />
+
     <!-- ======================================= -->
     <!-- Permissions for short range, peripheral networks -->
     <!-- ======================================= -->
@@ -1921,6 +1937,18 @@
         android:description="@string/permdesc_filter_events"
         android:protectionLevel="signature" />
 
+    <!-- @hide Allows an application to retrieve the window token from the accessibility manager. -->
+    <permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN"
+        android:label="@string/permlab_retrieveWindowToken"
+        android:description="@string/permdesc_retrieveWindowToken"
+        android:protectionLevel="signature" />
+
+    <!-- @hide Allows an application to collect frame statistics -->
+    <permission android:name="android.permission.FRAME_STATS"
+         android:label="@string/permlab_frameStats"
+         android:description="@string/permdesc_frameStats"
+         android:protectionLevel="signature" />
+
     <!-- @hide Allows an application to temporary enable accessibility on the device. -->
     <permission android:name="android.permission.TEMPORARY_ENABLE_ACCESSIBILITY"
         android:label="@string/permlab_temporary_enable_accessibility"
@@ -2028,6 +2056,13 @@
         android:description="@string/permdesc_bindWallpaper"
         android:protectionLevel="signature|system" />
 
+    <!-- Must be required by a {@link android.service.voice.VoiceInteractionService},
+         to ensure that only the system can bind to it. -->
+    <permission android:name="android.permission.BIND_VOICE_INTERACTION"
+        android:label="@string/permlab_bindVoiceInteraction"
+        android:description="@string/permdesc_bindVoiceInteraction"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by a {@link com.android.media.remotedisplay.RemoteDisplayProvider},
          to ensure that only the system can bind to it.
          @hide -->
@@ -2043,6 +2078,14 @@
         android:description="@string/permdesc_bindTvInput"
         android:protectionLevel="signature|system" />
 
+    <!-- Must be required by a {@link android.media.routeprovider.RouteProviderService}
+         to ensure that only the system can interact with it.
+         -->
+    <permission android:name="android.permission.BIND_ROUTE_PROVIDER"
+        android:label="@string/permlab_bindRouteProvider"
+        android:description="@string/permdesc_bindRouteProvider"
+        android:protectionLevel="signature" />
+
     <!-- Must be required by device administration receiver, to ensure that only the
          system can interact with it. -->
     <permission android:name="android.permission.BIND_DEVICE_ADMIN"
@@ -2271,6 +2314,13 @@
         android:description="@string/permdesc_broadcastWapPush"
         android:protectionLevel="signature" />
 
+    <!-- Allows an application to broadcast a SCORE_NETWORKS request.
+         <p>Not for use by third-party applications. @hide -->
+    <permission android:name="android.permission.BROADCAST_SCORE_NETWORKS"
+        android:label="@string/permlab_broadcastScoreNetworks"
+        android:description="@string/permdesc_broadcastScoreNetworks"
+        android:protectionLevel="signature|system" />
+
     <!-- Not for use by third-party applications. -->
     <permission android:name="android.permission.MASTER_CLEAR"
         android:label="@string/permlab_masterClear"
@@ -2577,6 +2627,15 @@
         android:description="@string/permdesc_bindNotificationListenerService"
         android:protectionLevel="signature" />
 
+    <!-- Must be required by an {@link
+         android.service.notification.ConditionProviderService},
+         to ensure that only the system can bind to it.
+         @hide -->
+    <permission android:name="android.permission.BIND_CONDITION_PROVIDER_SERVICE"
+        android:label="@string/permlab_bindConditionProviderService"
+        android:description="@string/permdesc_bindConditionProviderService"
+        android:protectionLevel="signature" />
+
     <!-- Allows an application to call into a carrier setup flow. It is up to the
          carrier setup application to enforce that this permission is required
          @hide This is not a third-party API (intended for OEMs and system apps). -->
@@ -2622,6 +2681,26 @@
                 <category android:name="android.intent.category.DEFAULT" />
             </intent-filter>
         </activity>
+        <activity android:name="com.android.internal.app.IntentForwarderActivity"
+                android:finishOnCloseSystemDialogs="true"
+                android:theme="@style/Theme.NoDisplay"
+                android:excludeFromRecents="true"
+                android:label="@string/user_owner_label"
+                android:exported="true"
+                >
+        </activity>
+        <activity-alias android:name="com.android.internal.app.ForwardIntentToUserOwner"
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/personal_icon"
+                android:exported="true"
+                android:label="@string/user_owner_label">
+        </activity-alias>
+        <activity-alias android:name="com.android.internal.app.ForwardIntentToManagedProfile"
+                android:targetActivity="com.android.internal.app.IntentForwarderActivity"
+                android:icon="@drawable/work_icon"
+                android:exported="true"
+                android:label="@string/managed_profile_label">
+        </activity-alias>
         <activity android:name="com.android.internal.app.HeavyWeightSwitcherActivity"
                 android:theme="@style/Theme.Holo.Dialog"
                 android:label="@string/heavy_weight_switcher_title"
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/color/primary_text_quantum_dark.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/color/primary_text_quantum_dark.xml
index 15d0890..1fcd0e3 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/color/primary_text_quantum_dark.xml
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_quantum_dark"/>
+    <item android:color="@color/primary_text_default_quantum_dark"/>
+</selector>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/color/primary_text_quantum_light.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/color/primary_text_quantum_light.xml
index 15d0890..1ec1634 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/color/primary_text_quantum_light.xml
@@ -1,20 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 The Android Open Source Project
+<!-- 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.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:alpha="0.5" android:color="@color/primary_text_default_quantum_light"/>
+    <item android:color="@color/primary_text_default_quantum_light"/>
+</selector>
diff --git a/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..3813563
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..47263ea
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..aa23c59
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..cac32b5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_settings.png b/core/res/res/drawable-hdpi/ic_settings.png
new file mode 100644
index 0000000..cfa539f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..25b8935
--- /dev/null
+++ b/core/res/res/drawable-hdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/personal_icon.png b/core/res/res/drawable-hdpi/personal_icon.png
new file mode 100644
index 0000000..8d96b5e
--- /dev/null
+++ b/core/res/res/drawable-hdpi/personal_icon.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..32ddf7a
--- /dev/null
+++ b/core/res/res/drawable-hdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..598b98c
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..df2fdb8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..79fe7c5
--- /dev/null
+++ b/core/res/res/drawable-hdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..7bcebcd
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..eb1d945
--- /dev/null
+++ b/core/res/res/drawable-hdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/work_icon.png b/core/res/res/drawable-hdpi/work_icon.png
new file mode 100644
index 0000000..e90866b
--- /dev/null
+++ b/core/res/res/drawable-hdpi/work_icon.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..d43e4d1
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..42ac8ca
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..b5f6176
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..9137fea
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_settings.png b/core/res/res/drawable-mdpi/ic_settings.png
new file mode 100644
index 0000000..e6237eb
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..3f1eee3
--- /dev/null
+++ b/core/res/res/drawable-mdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..db9e172
--- /dev/null
+++ b/core/res/res/drawable-mdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..506a186
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..e54d32e
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..fb0e926
--- /dev/null
+++ b/core/res/res/drawable-mdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..ef4ebc0
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..9ddbcf5
--- /dev/null
+++ b/core/res/res/drawable-mdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..ddacb59
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c10a1b7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..bd80981
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..513ee8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_settings.png b/core/res/res/drawable-xhdpi/ic_settings.png
new file mode 100644
index 0000000..208089d
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..c1c23d04
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..805cb29
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..38b8e8b
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..c1ca323
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..d6002a7
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..1a2546f
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..500ec33
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
new file mode 100644
index 0000000..21ed9144
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_clear_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
new file mode 100644
index 0000000..fc1b8b4
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_commit_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
new file mode 100644
index 0000000..8e1ab5b
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_go_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
new file mode 100644
index 0000000..81b13aa
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_settings.png b/core/res/res/drawable-xxhdpi/ic_settings.png
new file mode 100644
index 0000000..452942e
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_settings.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
new file mode 100644
index 0000000..d95f1d0
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/ic_voice_search_api_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png
new file mode 100644
index 0000000..c3791fc
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/scrubber_track_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
new file mode 100644
index 0000000..93469a2
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_left_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
new file mode 100644
index 0000000..5753d89
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_middle_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
new file mode 100644
index 0000000..b3493e7
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/text_select_handle_right_qntm_alpha.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
new file mode 100644
index 0000000..cd5b00f
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_activated_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
new file mode 100644
index 0000000..5ee867c
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/textfield_search_default_qntm_alpha.9.png
Binary files differ
diff --git a/core/res/res/drawable/btn_check_quantum_anim.xml b/core/res/res/drawable/btn_check_quantum_anim.xml
new file mode 100644
index 0000000..0600522
--- /dev/null
+++ b/core/res/res/drawable/btn_check_quantum_anim.xml
@@ -0,0 +1,79 @@
+<!-- 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:trigger="state_checked"
+    android:versionCode="1" >
+
+    <size
+        android:height="32dp"
+        android:width="32dp" />
+
+    <viewport
+        android:viewportHeight="320"
+        android:viewportWidth="320" />
+
+    <group>
+        <path
+            android:name="box1"
+            android:pathData="M 240,80 L 240,240 L 80,240 L 80,80 L 240,80 L 240,80 z"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="20"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box2"
+            android:pathData="M 160,200 L 160,240 L 120,240 L 120,200 L 160,200 L 160,200 z"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="10"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box3"
+            android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+            android:rotation="35"
+            android:pivotX="140"
+            android:pivotY="220"
+            android:fill="?attr/colorControlNormal"
+            android:stroke="?attr/colorControlNormal"
+            android:strokeWidth="5"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="box4"
+            android:pathData="M 160,216.5 L 143.5,240 L 120,223.5 L 136.5,200 L 160,216.5 L 160,216.5 z"
+            android:fill="?attr/colorControlActivated"
+            android:stroke="?attr/colorControlActivated"
+            android:strokeLineCap="round"
+            android:strokeLineJoin="round" />
+    </group>
+    <group>
+        <path
+            android:name="check"
+            android:pathData="M 232.1,80.6 L 248.5,92.1 L 145.2,239.5 L 71.5,187.8 L 83,171.5 L 140.3,211.7 z"
+            android:fill="?attr/colorControlActivated" />
+    </group>
+
+    <animation
+        android:durations="300,100,0,300"
+        android:sequence="box1,box2,box3,box4,check" />
+
+</vector>
diff --git a/core/res/res/drawable/btn_color_quantum.xml b/core/res/res/drawable/btn_color_quantum.xml
index e923003..2da9226 100644
--- a/core/res/res/drawable/btn_color_quantum.xml
+++ b/core/res/res/drawable/btn_color_quantum.xml
@@ -19,7 +19,8 @@
     <selector>
         <item android:state_enabled="false">
             <nine-patch android:src="@drawable/btn_qntm_alpha"
-                android:tint="?attr/colorButtonNormal" />
+                android:tint="?attr/colorButtonNormal"
+                android:alpha="?attr/disabledAlpha" />
         </item>
         <item>
             <nine-patch android:src="@drawable/btn_qntm_alpha"
diff --git a/core/res/res/drawable/btn_default_quantum.xml b/core/res/res/drawable/btn_default_quantum.xml
index 2919621..c6a3a33 100644
--- a/core/res/res/drawable/btn_default_quantum.xml
+++ b/core/res/res/drawable/btn_default_quantum.xml
@@ -17,7 +17,18 @@
 <touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
     android:tint="?attr/colorButtonPressed">
     <item>
-        <nine-patch android:src="@drawable/btn_qntm_alpha"
-            android:tint="?attr/colorButtonNormal" />
+        <selector>
+            <item android:state_enabled="false">
+                <nine-patch
+                    android:src="@drawable/btn_qntm_alpha"
+                    android:tint="?attr/colorButtonNormal"
+                    android:alpha="?attr/disabledAlpha" />
+            </item>
+            <item>
+                <nine-patch
+                    android:src="@drawable/btn_qntm_alpha"
+                    android:tint="?attr/colorButtonNormal" />
+            </item>
+        </selector>
     </item>
 </touch-feedback>
diff --git a/core/res/res/drawable/btn_radio_quantum.xml b/core/res/res/drawable/btn_radio_quantum.xml
index 152e3d3..0f9ebce 100644
--- a/core/res/res/drawable/btn_radio_quantum.xml
+++ b/core/res/res/drawable/btn_radio_quantum.xml
@@ -15,18 +15,20 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_checked="true" android:state_enabled="true" android:state_pressed="true">
-        <bitmap android:src="@drawable/btn_radio_on_pressed_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
+    <item android:state_enabled="false" android:state_checked="true">
+        <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
     </item>
     <item android:state_checked="true">
         <bitmap android:src="@drawable/btn_radio_on_qntm_alpha"
             android:tint="?attr/colorControlActivated" />
     </item>
-    <item android:state_enabled="true" android:state_pressed="true">
-        <bitmap android:src="@drawable/btn_radio_off_pressed_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
     <item>
         <bitmap android:src="@drawable/btn_radio_off_qntm_alpha"
             android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/dialog_background_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/dialog_background_quantum.xml
index 15d0890..7e5b003 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/dialog_background_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,13 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+
+    <corners
+        android:radius="2dp" />
+    <solid
+        android:color="?attr/colorBackground" />
+
+</shape>
diff --git a/core/res/res/drawable/edit_text_quantum.xml b/core/res/res/drawable/edit_text_quantum.xml
index d1f9831..c42c7b7 100644
--- a/core/res/res/drawable/edit_text_quantum.xml
+++ b/core/res/res/drawable/edit_text_quantum.xml
@@ -14,29 +14,26 @@
      limitations under the License.
 -->
 
-<selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_window_focused="false" android:state_enabled="true">
-        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
-    </item>
-    <item android:state_window_focused="false" android:state_enabled="false">
-        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
-    </item>
-    <item android:state_enabled="true" android:state_focused="true">
-        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
-    <item android:state_enabled="true" android:state_activated="true">
-        <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
-    <item android:state_enabled="true">
-        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
-    </item>
+<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="?attr/colorControlActivated">
     <item>
-        <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
+        <selector>
+            <item android:state_window_focused="false">
+                <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+            <item android:state_enabled="false">
+                <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+            <item android:state_focused="false" android:state_activated="false">
+                <nine-patch android:src="@drawable/textfield_default_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+            <item>
+                <nine-patch android:src="@drawable/textfield_activated_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+        </selector>
     </item>
-</selector>
+</touch-feedback>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/ic_clear_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/ic_clear_quantum.xml
index 15d0890..02f0929 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/ic_clear_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_clear_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/ic_commit_search_api_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/ic_commit_search_api_quantum.xml
index 15d0890..02d08b9 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/ic_commit_search_api_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_commit_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/ic_go_search_api_quantum.xml
similarity index 64%
rename from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
rename to core/res/res/drawable/ic_go_search_api_quantum.xml
index 15d0890..b5b5cfb 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/ic_go_search_api_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_go_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/ic_search_api_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/ic_search_api_quantum.xml
index 15d0890..2bbc294 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/ic_search_api_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/ic_voice_search_api_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/ic_voice_search_api_quantum.xml
index 15d0890..ddb14ef 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/ic_voice_search_api_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_voice_search_api_qntm_alpha"
+    android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/list_selector_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/list_selector_quantum.xml
index 15d0890..c007117 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/list_selector_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<touch-feedback xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="?attr/colorButtonPressed">
+    <item android:id="@id/mask">
+        <color android:color="@color/white" />
+    </item>
+</touch-feedback>
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_bg_dim.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_background.xml
rename to core/res/res/drawable/notification_bg_dim.xml
index 7b508a9..ec20368 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_bg_dim.xml
@@ -15,7 +15,9 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffffffff" />
-    <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="#ff444444"
+    >
+    <item android:drawable="@drawable/notification_bg_normal" />
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_bg.xml b/core/res/res/drawable/notification_quantum_bg.xml
index 608115e..300a565 100644
--- a/core/res/res/drawable/notification_quantum_bg.xml
+++ b/core/res/res/drawable/notification_quantum_bg.xml
@@ -16,6 +16,16 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"  android:drawable="@drawable/notification_quantum_press" />
-    <item android:state_pressed="false" android:drawable="@drawable/notification_quantum_background" />
+    <item android:state_pressed="true">
+        <shape>
+            <solid android:color="#ffd0d0d0" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+    <item>
+        <shape>
+            <solid android:color="#fffafafa" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
 </selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/notification_quantum_background.xml b/core/res/res/drawable/notification_quantum_bg_dim.xml
similarity index 65%
copy from core/res/res/drawable/notification_quantum_background.xml
copy to core/res/res/drawable/notification_quantum_bg_dim.xml
index 7b508a9..ab0e049 100644
--- a/core/res/res/drawable/notification_quantum_background.xml
+++ b/core/res/res/drawable/notification_quantum_bg_dim.xml
@@ -15,7 +15,15 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffffffff" />
-    <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
-</shape>
\ No newline at end of file
+<touch-feedback
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:tint="#ffffffff"
+    android:tintMode="src_over"
+    >
+    <item>
+        <shape>
+            <solid android:color="#d4ffffff" />
+            <corners android:radius="@dimen/notification_quantum_rounded_rect_radius" />
+        </shape>
+    </item>
+</touch-feedback>
\ No newline at end of file
diff --git a/core/res/res/drawable/scrubber_control_selector_quantum.xml b/core/res/res/drawable/scrubber_control_selector_quantum.xml
index e31c2c1..ef3af0c 100644
--- a/core/res/res/drawable/scrubber_control_selector_quantum.xml
+++ b/core/res/res/drawable/scrubber_control_selector_quantum.xml
@@ -15,12 +15,12 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_enabled="true" android:state_pressed="true">
-        <bitmap android:src="@drawable/scrubber_control_on_pressed_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/scrubber_control_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
     </item>
     <item>
         <bitmap android:src="@drawable/scrubber_control_on_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
+            android:tint="?attr/colorControlActivated" />
     </item>
 </selector>
diff --git a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
index 7b124ac..d172b05 100644
--- a/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
+++ b/core/res/res/drawable/scrubber_progress_horizontal_quantum.xml
@@ -15,12 +15,24 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true">
-        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
+    <item android:state_enabled="false">
+        <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
     </item>
     <item>
-        <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
-            android:tint="?attr/colorControlNormal" />
+        <layer-list>
+            <item android:id="@id/background">
+                <bitmap android:src="@drawable/scrubber_track_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+            <item android:id="@id/secondaryProgress">
+                <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+                    android:tint="?attr/colorControlNormal" />
+            </item>
+            <item android:id="@id/progress">
+                <bitmap android:src="@drawable/scrubber_primary_qntm_alpha"
+                    android:tint="?attr/colorControlActivated" />
+            </item>
+        </layer-list>
     </item>
 </selector>
diff --git a/core/res/res/drawable/switch_inner_quantum.xml b/core/res/res/drawable/switch_inner_quantum.xml
index 915377e..856895e 100644
--- a/core/res/res/drawable/switch_inner_quantum.xml
+++ b/core/res/res/drawable/switch_inner_quantum.xml
@@ -15,18 +15,20 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_checked="true" android:state_pressed="true">
+    <item android:state_enabled="false" android:state_checked="true">
         <nine-patch android:src="@drawable/switch_on_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
+    </item>
+    <item android:state_enabled="false">
+        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
+            android:tint="?attr/colorControlNormal"
+            android:alpha="?attr/disabledAlpha" />
     </item>
     <item android:state_checked="true">
         <nine-patch android:src="@drawable/switch_on_qntm_alpha"
             android:tint="?attr/colorControlActivated" />
     </item>
-    <item android:state_pressed="true">
-        <nine-patch android:src="@drawable/switch_off_qntm_alpha"
-            android:tint="?attr/colorControlActivated" />
-    </item>
     <item>
         <nine-patch android:src="@drawable/switch_off_qntm_alpha"
             android:tint="?attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/text_select_handle_left_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/text_select_handle_left_quantum.xml
index 15d0890..a0ad7cf 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/text_select_handle_left_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_left_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/text_select_handle_middle_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/text_select_handle_middle_quantum.xml
index 15d0890..bff0b66 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/text_select_handle_middle_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_middle_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/drawable/text_select_handle_right_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/drawable/text_select_handle_right_quantum.xml
index 15d0890..413661f 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/drawable/text_select_handle_right_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/text_select_handle_right_qntm_alpha"
+    android:tint="?attr/colorControlActivated" />
diff --git a/core/res/res/drawable/textfield_search_quantum.xml b/core/res/res/drawable/textfield_search_quantum.xml
new file mode 100644
index 0000000..877de46
--- /dev/null
+++ b/core/res/res/drawable/textfield_search_quantum.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_window_focused="false" android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_window_focused="false" android:state_enabled="false">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item android:state_enabled="true" android:state_focused="true">
+        <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:state_enabled="true" android:state_activated="true">
+        <nine-patch android:src="@drawable/textfield_search_activated_qntm_alpha"
+            android:tint="?attr/colorControlActivated" />
+    </item>
+    <item android:state_enabled="true">
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+    <item>
+        <nine-patch android:src="@drawable/textfield_search_default_qntm_alpha"
+            android:tint="?attr/colorControlNormal" />
+    </item>
+</selector>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_linear_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/fast_out_linear_in.xml
index 4999f55..19f95a6 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_linear_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="1"
+    android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/fast_out_slow_in.xml
similarity index 77%
rename from core/res/res/drawable/notification_quantum_press.xml
rename to core/res/res/interpolator/fast_out_slow_in.xml
index 4999f55..2d68dbb 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/fast_out_slow_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0.4"
+    android:controlY1="0"
+    android:controlX2="0.2"
+    android:controlY2="1"/>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/core/res/res/interpolator/linear_out_slow_in.xml
similarity index 77%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to core/res/res/interpolator/linear_out_slow_in.xml
index 4999f55..83fc223 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/core/res/res/interpolator/linear_out_slow_in.xml
@@ -15,7 +15,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<pathInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
+    android:controlX1="0"
+    android:controlY1="0"
+    android:controlX2="0.2"
+    android:controlY2="1"/>
diff --git a/core/res/res/layout/action_bar_home_quantum.xml b/core/res/res/layout/action_bar_home_quantum.xml
new file mode 100644
index 0000000..9213458
--- /dev/null
+++ b/core/res/res/layout/action_bar_home_quantum.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 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.
+-->
+
+<view xmlns:android="http://schemas.android.com/apk/res/android"
+    class="com.android.internal.widget.ActionBarView$HomeView"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_vertical|start">
+    <ImageView android:id="@android:id/up"
+        android:src="?android:attr/homeAsUpIndicator"
+        android:layout_gravity="center_vertical|start"
+        android:visibility="gone"
+        android:layout_width="48dp"
+        android:layout_height="48dp"
+        android:scaleType="centerInside" />
+    <ImageView android:id="@android:id/home"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginEnd="8dip"
+        android:layout_marginTop="@android:dimen/action_bar_icon_vertical_padding"
+        android:layout_marginBottom="@android:dimen/action_bar_icon_vertical_padding"
+        android:adjustViewBounds="true"
+        android:scaleType="fitCenter" />
+</view>
diff --git a/core/res/res/layout/alert_dialog_quantum.xml b/core/res/res/layout/alert_dialog_quantum.xml
index 98b68797..80e34cb 100644
--- a/core/res/res/layout/alert_dialog_quantum.xml
+++ b/core/res/res/layout/alert_dialog_quantum.xml
@@ -20,7 +20,10 @@
     android:id="@+id/parentPanel"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:background="@drawable/dialog_background_quantum"
+    android:translationZ="@dimen/floating_window_z"
+    android:layout_margin="@dimen/floating_window_margin">
 
     <LinearLayout android:id="@+id/topPanel"
         android:layout_width="match_parent"
@@ -91,32 +94,32 @@
             style="?android:attr/buttonBarStyle"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:orientation="horizontal"
-            android:layoutDirection="locale"
-            android:measureWithLargestChild="true">
+            android:layoutDirection="locale">
             <Button android:id="@+id/button3"
+                style="?android:attr/buttonBarButtonStyle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="start"
                 android:layout_marginRight="8dip"
                 android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarButtonStyle" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
+            <View
+                android:layout_width="0dp"
+                android:layout_height="@dimen/alert_dialog_button_bar_height"
+                android:layout_weight="1"
+                android:visibility="invisible" />
             <Button android:id="@+id/button2"
+                style="?android:attr/buttonBarButtonStyle"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="end"
-                android:layout_marginRight="8dip"
                 android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarButtonStyle" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
             <Button android:id="@+id/button1"
+                style="?android:attr/buttonBarButtonStyle"
+                android:layout_marginLeft="8dip"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_gravity="end"
                 android:maxLines="2"
-                android:minHeight="@dimen/alert_dialog_button_bar_height"
-                style="?android:attr/buttonBarButtonStyle" />
+                android:minHeight="@dimen/alert_dialog_button_bar_height" />
         </LinearLayout>
      </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/notification_template_quantum_base.xml b/core/res/res/layout/notification_template_quantum_base.xml
index 8863cfa..8f3019d 100644
--- a/core/res/res/layout/notification_template_quantum_base.xml
+++ b/core/res/res/layout/notification_template_quantum_base.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="64dp"
diff --git a/core/res/res/layout/notification_template_quantum_big_base.xml b/core/res/res/layout/notification_template_quantum_big_base.xml
index 63935bb..45e69b1 100644
--- a/core/res/res/layout/notification_template_quantum_big_base.xml
+++ b/core/res/res/layout/notification_template_quantum_big_base.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_big_picture.xml b/core/res/res/layout/notification_template_quantum_big_picture.xml
index e49c3bd..f68e414 100644
--- a/core/res/res/layout/notification_template_quantum_big_picture.xml
+++ b/core/res/res/layout/notification_template_quantum_big_picture.xml
@@ -17,7 +17,6 @@
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/core/res/res/layout/notification_template_quantum_big_text.xml b/core/res/res/layout/notification_template_quantum_big_text.xml
index 516b0c4..f7769d7 100644
--- a/core/res/res/layout/notification_template_quantum_big_text.xml
+++ b/core/res/res/layout/notification_template_quantum_big_text.xml
@@ -16,7 +16,6 @@
   -->
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
-    android:background="@android:drawable/notification_quantum_bg"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
diff --git a/core/res/res/layout/notification_template_quantum_inbox.xml b/core/res/res/layout/notification_template_quantum_inbox.xml
index c6192be..04974c4 100644
--- a/core/res/res/layout/notification_template_quantum_inbox.xml
+++ b/core/res/res/layout/notification_template_quantum_inbox.xml
@@ -18,7 +18,6 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:internal="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/status_bar_latest_event_content"
-    android:background="@android:drawable/notification_quantum_bg"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     internal:layout_minHeight="65dp"
diff --git a/core/res/res/layout/preference_category_quantum.xml b/core/res/res/layout/preference_category_quantum.xml
new file mode 100644
index 0000000..032e09d
--- /dev/null
+++ b/core/res/res/layout/preference_category_quantum.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Layout used for PreferenceCategory in a PreferenceActivity. -->
+<TextView xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+android:id/title"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginBottom="16dip"
+    android:textAppearance="@style/TextAppearance.Quantum.Body2"
+    android:textColor="?android:attr/textColorSecondary"
+    android:textStyle="bold"
+    android:paddingStart="?attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?attr/listPreferredItemPaddingEnd"
+    android:paddingTop="16dip" />
diff --git a/core/res/res/layout/preference_child_quantum.xml b/core/res/res/layout/preference_child_quantum.xml
new file mode 100644
index 0000000..690d64a
--- /dev/null
+++ b/core/res/res/layout/preference_child_quantum.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Layout for a visually child-like Preference in a PreferenceActivity. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:layout_marginStart="?attr/listPreferredItemPaddingStart"
+    android:minHeight="?android:attr/listPreferredItemHeight"
+    android:gravity="center_vertical"
+    android:paddingStart="?attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?attr/listPreferredItemPaddingEnd">
+
+    <LinearLayout
+        android:id="@+android:id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="left|center_vertical"
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="8dip" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dip"
+        android:paddingBottom="16dip">
+
+        <TextView android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem" />
+
+        <TextView android:id="@+android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="right|center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/preference_information_quantum.xml b/core/res/res/layout/preference_information_quantum.xml
new file mode 100644
index 0000000..f21640f
--- /dev/null
+++ b/core/res/res/layout/preference_information_quantum.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Layout for a Preference in a PreferenceActivity. The
+     Preference is able to place a specific widget for its particular
+     type in the "widget_frame" layout. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?attr/listPreferredItemPaddingEnd">
+
+    <LinearLayout
+        android:id="@+android:id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="left|center_vertical"
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginEnd="8dip" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dip"
+        android:paddingBottom="16dip">
+
+        <TextView android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem" />
+
+        <TextView android:id="@+android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="right|center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/preference_quantum.xml b/core/res/res/layout/preference_quantum.xml
new file mode 100644
index 0000000..a4fe73d
--- /dev/null
+++ b/core/res/res/layout/preference_quantum.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<!-- Layout for a Preference in a PreferenceActivity. The
+     Preference is able to place a specific widget for its particular
+     type in the "widget_frame" layout. -->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:minHeight="?android:attr/listPreferredItemHeightSmall"
+    android:gravity="center_vertical"
+    android:paddingStart="?attr/listPreferredItemPaddingStart"
+    android:paddingEnd="?attr/listPreferredItemPaddingEnd"
+    android:background="?android:attr/activatedBackgroundIndicator">
+
+    <LinearLayout
+        android:id="@+android:id/icon_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="left|center_vertical"
+        android:orientation="horizontal">
+        <ImageView
+            android:id="@+android:id/icon"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:scaleType="centerInside"
+            android:layout_marginEnd="8dip" />
+    </LinearLayout>
+
+    <RelativeLayout
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_weight="1"
+        android:paddingTop="16dip"
+        android:paddingBottom="16dip">
+
+        <TextView android:id="@+android:id/title"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:singleLine="true"
+            android:textAppearance="?android:attr/textAppearanceListItem"
+            android:ellipsize="marquee" />
+
+        <TextView android:id="@+android:id/summary"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_below="@android:id/title"
+            android:layout_alignStart="@android:id/title"
+            android:textAppearance="?android:attr/textAppearanceListItemSecondary"
+            android:textColor="?android:attr/textColorSecondary"
+            android:maxLines="10" />
+
+    </RelativeLayout>
+
+    <!-- Preference should place its actual preference widget here. -->
+    <LinearLayout android:id="@+android:id/widget_frame"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:minWidth="58dip"
+        android:gravity="right|center_vertical"
+        android:orientation="vertical" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/preference_widget_checkbox.xml b/core/res/res/layout/preference_widget_checkbox.xml
index 33a43f4..bfd7f0a 100644
--- a/core/res/res/layout/preference_widget_checkbox.xml
+++ b/core/res/res/layout/preference_widget_checkbox.xml
@@ -20,6 +20,5 @@
     android:id="@+android:id/checkbox" 
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_gravity="center"
     android:focusable="false"
     android:clickable="false" />
diff --git a/core/res/res/layout/preference_widget_switch.xml b/core/res/res/layout/preference_widget_switch.xml
index 83ef097..534c7ec 100644
--- a/core/res/res/layout/preference_widget_switch.xml
+++ b/core/res/res/layout/preference_widget_switch.xml
@@ -20,6 +20,5 @@
     android:id="@+android:id/switchWidget"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
-    android:layout_gravity="center"
     android:padding="16dip"
     android:focusable="false" />
diff --git a/core/res/res/layout/simple_list_item_1.xml b/core/res/res/layout/simple_list_item_1.xml
index 4249d10..43a5635 100644
--- a/core/res/res/layout/simple_list_item_1.xml
+++ b/core/res/res/layout/simple_list_item_1.xml
@@ -22,5 +22,4 @@
     android:gravity="center_vertical"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-/>
+    android:minHeight="?android:attr/listPreferredItemHeightSmall" />
diff --git a/core/res/res/layout/simple_list_item_2.xml b/core/res/res/layout/simple_list_item_2.xml
index 63c542b..b47a346 100644
--- a/core/res/res/layout/simple_list_item_2.xml
+++ b/core/res/res/layout/simple_list_item_2.xml
@@ -20,22 +20,19 @@
     android:minHeight="?android:attr/listPreferredItemHeight"
     android:mode="twoLine"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
->
-    
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
+
 	<TextView android:id="@android:id/text1"
-		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-    android:layout_marginTop="8dip"
-		android:textAppearance="?android:attr/textAppearanceListItem"
-	/>
-		
+    	android:layout_width="match_parent"
+    	android:layout_height="wrap_content"
+      android:layout_marginTop="8dip"
+    	android:textAppearance="?android:attr/textAppearanceListItem" />
+
 	<TextView android:id="@android:id/text2"
-		android:layout_width="match_parent"
-		android:layout_height="wrap_content"
-		android:layout_below="@android:id/text1"
-    android:layout_alignStart="@android:id/text1"
-		android:textAppearance="?android:attr/textAppearanceSmall"
-	/>
+    	android:layout_width="match_parent"
+    	android:layout_height="wrap_content"
+    	android:layout_below="@android:id/text1"
+      android:layout_alignStart="@android:id/text1"
+    	android:textAppearance="?android:attr/textAppearanceListItemSecondary" />
 
 </TwoLineListItem>
diff --git a/core/res/res/layout/simple_list_item_2_single_choice.xml b/core/res/res/layout/simple_list_item_2_single_choice.xml
index 5629567..940c6b8 100644
--- a/core/res/res/layout/simple_list_item_2_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_2_single_choice.xml
@@ -21,32 +21,36 @@
     android:gravity="center_vertical"
     android:paddingStart="16dip"
     android:paddingEnd="12dip"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall">
+    android:minHeight="?attr/listPreferredItemHeightSmall"
+    android:background="@color/transparent">
+
     <LinearLayout
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:orientation="vertical"
         android:gravity="center_vertical">
+
         <TextView android:id="@android:id/text1"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceMedium"
-            android:textColor="?android:attr/textColorAlertDialogListItem"
+            android:textAppearance="?attr/textAppearanceListItem"
+            android:textColor="?attr/textColorAlertDialogListItem"
             android:gravity="center_vertical|start"
             android:singleLine="true"
-            android:ellipsize="marquee"
-        />
+            android:ellipsize="marquee" />
+        
         <TextView android:id="@android:id/text2"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="?android:attr/textAppearanceSmall"
-            android:textColor="?android:attr/textColorAlertDialogListItem"
+            android:textAppearance="?attr/textAppearanceListItemSecondary"
+            android:textColor="?attr/textColorAlertDialogListItem"
             android:gravity="center_vertical|start"
             android:singleLine="true"
-            android:ellipsize="marquee"
-        />
+            android:ellipsize="marquee" />
+        
     </LinearLayout>
+
     <RadioButton
         android:id="@+id/radio"
         android:layout_width="35dip"
@@ -54,6 +58,6 @@
         android:paddingEnd="12dip"
         android:gravity="center_vertical"
         android:focusable="false"
-        android:clickable="false"
-    />
+        android:clickable="false" />
+
 </LinearLayout>
diff --git a/core/res/res/layout/simple_list_item_activated_1.xml b/core/res/res/layout/simple_list_item_activated_1.xml
index 41155e4..9b778d7 100644
--- a/core/res/res/layout/simple_list_item_activated_1.xml
+++ b/core/res/res/layout/simple_list_item_activated_1.xml
@@ -23,5 +23,4 @@
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
     android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
     android:background="?android:attr/activatedBackgroundIndicator"
-    android:minHeight="?android:attr/listPreferredItemHeightSmall"
-/>
+    android:minHeight="?android:attr/listPreferredItemHeightSmall" />
diff --git a/core/res/res/layout/simple_list_item_activated_2.xml b/core/res/res/layout/simple_list_item_activated_2.xml
index 725697d..5036813 100644
--- a/core/res/res/layout/simple_list_item_activated_2.xml
+++ b/core/res/res/layout/simple_list_item_activated_2.xml
@@ -21,23 +21,20 @@
     android:layout_height="wrap_content"
     android:background="?android:attr/activatedBackgroundIndicator"
     android:minHeight="?android:attr/listPreferredItemHeight"
-    android:mode="twoLine"
->
+    android:mode="twoLine">
 
     <TextView android:id="@android:id/text1"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginStart="?android:attr/listPreferredItemPaddingStart"
         android:layout_marginTop="6dip"
-        android:textAppearance="?android:attr/textAppearanceListItem"
-    />
+        android:textAppearance="?android:attr/textAppearanceListItem" />
 
     <TextView android:id="@android:id/text2"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_below="@android:id/text1"
         android:layout_alignStart="@android:id/text1"
-        android:textAppearance="?android:attr/textAppearanceSmall"
-    />
+        android:textAppearance="?android:attr/textAppearanceListItemSecondary" />
 
 </TwoLineListItem>
diff --git a/core/res/res/layout/simple_list_item_checked.xml b/core/res/res/layout/simple_list_item_checked.xml
index 0c497d6..4673e27 100644
--- a/core/res/res/layout/simple_list_item_checked.xml
+++ b/core/res/res/layout/simple_list_item_checked.xml
@@ -22,5 +22,4 @@
     android:gravity="center_vertical"
     android:checkMark="?android:attr/textCheckMark"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-/>
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/core/res/res/layout/simple_list_item_multiple_choice.xml b/core/res/res/layout/simple_list_item_multiple_choice.xml
index 076d8c6..440b6fd 100644
--- a/core/res/res/layout/simple_list_item_multiple_choice.xml
+++ b/core/res/res/layout/simple_list_item_multiple_choice.xml
@@ -22,5 +22,4 @@
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorMultiple"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-/>
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/core/res/res/layout/simple_list_item_single_choice.xml b/core/res/res/layout/simple_list_item_single_choice.xml
index 4c1af09..02cb7f7 100644
--- a/core/res/res/layout/simple_list_item_single_choice.xml
+++ b/core/res/res/layout/simple_list_item_single_choice.xml
@@ -22,5 +22,4 @@
     android:gravity="center_vertical"
     android:checkMark="?android:attr/listChoiceIndicatorSingle"
     android:paddingStart="?android:attr/listPreferredItemPaddingStart"
-    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
-/>
+    android:paddingEnd="?android:attr/listPreferredItemPaddingEnd" />
diff --git a/core/res/res/layout/volume_adjust.xml b/core/res/res/layout/volume_adjust.xml
index c16a12c..3ad1f23 100644
--- a/core/res/res/layout/volume_adjust.xml
+++ b/core/res/res/layout/volume_adjust.xml
@@ -14,47 +14,38 @@
      limitations under the License.
 -->
 
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="480dp"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/visible_panel"
+    android:orientation="horizontal"
+    android:layout_width="300dp"
     android:layout_height="wrap_content">
+
     <LinearLayout
-        android:id="@+id/visible_panel"
-        android:layout_width="match_parent"
+        android:id="@+id/slider_group"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
-        android:background="@android:drawable/dialog_full_holo_dark"
-        android:orientation="horizontal"
-        >
-
-        <LinearLayout
-            android:id="@+id/slider_group"
-            android:layout_width="0dp"
-            android:layout_height="wrap_content"
-            android:layout_weight="1"
-            android:orientation="vertical"
-            >
-            <!-- Sliders go here -->
-        </LinearLayout>
-
-        <ImageView
-            android:id="@+id/expand_button_divider"
-            android:src="?attr/dividerVertical"
-            android:layout_width="wrap_content"
-            android:layout_height="32dip"
-            android:scaleType="fitXY"
-            android:layout_gravity="top"
-            android:layout_marginTop="16dip"
-            android:layout_marginBottom="16dip"
-            />
-
-        <ImageView
-            android:id="@+id/expand_button"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_gravity="top"
-            android:padding="16dip"
-            android:background="?attr/selectableItemBackground"
-            android:src="@drawable/ic_sysbar_quicksettings"
-            />
-
+        android:layout_weight="1"
+        android:orientation="vertical">
+        <!-- Sliders go here -->
     </LinearLayout>
-</FrameLayout>
\ No newline at end of file
+
+    <ImageView
+        android:id="@+id/expand_button_divider"
+        android:src="?attr/dividerVertical"
+        android:layout_width="wrap_content"
+        android:layout_height="32dip"
+        android:scaleType="fitXY"
+        android:layout_gravity="top"
+        android:layout_marginTop="16dip"
+        android:layout_marginBottom="16dip" />
+
+    <ImageView
+        android:id="@+id/expand_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="top"
+        android:padding="16dip"
+        android:background="?attr/selectableItemBackground"
+        android:src="@drawable/ic_sysbar_quicksettings" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/volume_adjust_item.xml b/core/res/res/layout/volume_adjust_item.xml
index 4a0fbaf..57cecf4 100644
--- a/core/res/res/layout/volume_adjust_item.xml
+++ b/core/res/res/layout/volume_adjust_item.xml
@@ -26,14 +26,14 @@
         android:id="@+id/stream_icon"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:padding="16dip"
+        android:paddingLeft="16dip"
         android:background="?attr/selectableItemBackground"
-        />
+        android:contentDescription="@null" />
 
     <SeekBar
         style="?android:attr/seekBarStyle"
         android:id="@+id/seekbar"
-        android:layout_width="300dp"
+        android:layout_width="0dp"
         android:layout_height="wrap_content"
         android:layout_weight="1"
         android:padding="16dip"
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/transition/no_transition.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/transition/no_transition.xml
index 15d0890..5679738 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/transition/no_transition.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,4 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+<transitionSet/>
diff --git a/core/res/res/values-af/strings.xml b/core/res/res/values-af/strings.xml
index b9bdfb9..20d306d 100644
--- a/core/res/res/values-af/strings.xml
+++ b/core/res/res/values-af/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="UNIT">%2$s</xliff:g><xliff:g id="NUMBER">%1$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Titelloos&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkroniseer"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Te veel <xliff:g id="CONTENT_TYPE">%s</xliff:g> uitgevee."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet se berging is vol. Vee \'n aantal lêers uit om spasie vry te maak."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Horlosieberging is vol! Vee \'n paar lêers uit om plek te maak."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Foon se berging is vol. Vee \'n aantal lêers uit om spasie vry te maak."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netwerk kan dalk gemonitor word"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Deur \'n onbekende derde party"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Luitoestel aan"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Sit tans af…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Jou tablet gaan nou afskakel."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Jou horlosie gaan nou afskakel."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Jou foon gaan nou afsit."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Wil jy afskakel?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Herlaai na veilige modus"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegtuigmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegtuigmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegtuigmodus is AF"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Instellings"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veiligmodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-stelsel"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Laat die program toe om die inhoud van die aktiewe venster op te haal. Kwaadwillige programme kan die hele venster se inhoud ophaal, en al die teks ondersoek, behalwe wagwoorde."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktiveer toeganklikheid tydelik"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Laat \'n program toe om toeganklikheid tydelik op die toestel te aktiveer. Kwaadwillige programme kan sonder die toestemming van die gebruiker toeganklikheid verkry."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"haal vensterteken"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Laat \'n program toe om die vensterteken te gaan haal. Kwaadwillige programme kan dalk ongemagtigde interaksie met die programvenster uitvoer deur die stelsel te verpersoonlik."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"haal raamstatistiek"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Laat \'n program toe om raamstatistiek in te samel. Kwaadwillige programme kan dalk die raamstatistiek van vensters van ander programme af naboots."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filter gebeure"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Laat \'n program toe om \'n invoerfilter te registreer wat die stroom van alle gebruikergebeure filter voordat dit versend word. Kwaadwillige programme kan moontlik die stelsel-UI beheer sonder gebruikers se tussentrede."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelike afskakeling"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Laat die program toe om \'n kennisgewing uit te saai dat \'n SMS-boodskap ontvang is. Kwaadwillige programme kan dit dalk gebruik om inkomende SMS-boodskappe na te maak."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"stuur WAP-PUSH-ontvange uitsending"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Laat die program toe om \'n kennisgewing uit te saai dat \'n WAP PUSH-boodskap ontvang is. Kwaadwillige programme kan dit dalk gebruik om MMS-boodskap-ontvangsbewyse na te maak of die inhoud van enige webbladsy stilweg te vervang met kwaadwillige variante."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"stuur uitsending vir netwerktelling"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Laat die program toe om \'n kennisgewing uit te saai dat netwerke tellings moet kry. Nooit vir normale programme nodig nie."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"beperk hoeveelheid lopende prosesse"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Laat die program toe om die maksimum getal prosesse te beheer wat sal loop. Nooit nodig vir normale programme nie."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"dwing agtergrondprogramme om te sluit"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n VPN-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind aan \'n muurpapier"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n muurpapier te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"verbind met \'n steminteraksiediens"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Laat die houer toe om met die topvlak-koppelvlak van \'n steminteraksiediens te verbind. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"koppel aan \'n afstandskerm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Dit laat die houer toe om aan die top-koppelvlak van \'n afstandskerm te koppel. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind aan \'n legstukdiens"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Dit laat die houer toe om aan die topvlak-koppelvlak van \'n legstuk-diens te bind. Dit moet nooit vir normale programme nodig wees nie."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind aan \'n roeteverskafferdiens"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Laat die houer toe om aan enige geregistreerde roeteverskaffers te bind. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"skakel met \'n toestel-admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Laat die houer toe om bedoelings na \'n toesteladministrateur te stuur. Dit moet nooit vir normale programme nodig wees nie."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind aan \'n TV-invoer"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Laat die houer toe om aan die topvlak-koppelvlak van \'n TV-invoer te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"voeg \'n toesteladministrateur by of verwyder een"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Laat die houer aktiewe toesteladministrateurs byvoeg of verwyder. Behoort nooit nodig te wees vir normale programme nie."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"verander skermoriëntasie"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Laat die program toe om persoonlike profielinligting  wat op jou toestel gestoor is, soos jou naam en kontakbesonderhede, te lees. Dit beteken dat die program jou kan identifiseer en jou profielinligting moontlik aan ander mense kan stuur."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"verander jou eie kontakkaart"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Laat die program toe om persoonlike profielinligting, soos jou naam en kontakinligting, wat op jou toestel gestoor is, te verander of daarby te voeg. Dit beteken dat die program jou kan identifiseer en moontlik jou profielinligting na ander mense kan stuur."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"liggaamsensors (soos hartklopmonitors)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Laat die program toe om toegang tot data te verkry vanaf sensors wat jy gebruik om te meet wat binne jou liggaam aangaan, soos hartklop."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lees jou sosiale stroom"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Laat die program toe om toegang tot sosiale opdaterings van jou en jou vriende te verkry en dit te sinkroniseer. Wees versigtig wanneer jy inligting deel -- dit laat die program toe om kommunikasie tussen jou en jou vriende op sosiale netwerke te lees, ongeag vertroulikheid. Let wel: hierdie toestemming mag dalk nie op alle sosiale netwerke afgedwing word nie."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skryf aan jou sosiale stroom"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Verander WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Laat die program toe om die tablet aan WiMAX-netwerke te koppel en daarvan te ontkoppel."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Laat die program toe om die foon aan WiMAX-netwerke te koppel en daarvan te ontkoppel."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"gee telling vir netwerke"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Laat die program toe om netwerke te gradeer en beïnvloed watter netwerke die tablet moet verkies."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Laat die program toe om netwerke te gradeer en beïnvloed watter netwerke die foon moet verkies."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"bind saam met Bluetooth-toestelle"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Laat die program toe om die opstelling van Bluetooth op die tablet te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Laat die program toe om die opstelling van die Bluetooth op die foon te sien, en om verbindings met saamgebinde toestelle te maak en te aanvaar."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Laat die program toe om kennisgewings op te haal, te bestudeer en te verwyder, insluitende die kennisgewings wat deur ander programme geplaas is."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind aan \'n kennisgewingluisteraardiens"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Laat die houer toe om aan die top-koppelvlak van \'n kennisgewingluisteraardiens te bind. Behoort nooit vir gewone programme nodig te wees nie."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"verbind met \'n toestandverskafferdiens"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Laat die houer toe om met die topvlak-koppelvlak van \'n toestandverskafferdiens te verbind. Behoort nooit vir normale programme nodig te wees nie."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"roep die opstellingprogram op wat deur die diensverskaffer voorsien is"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Laat die houer toe om die opstellingsprogram wat deur die diensverskaffer voorsien word, op te roep. Behoort nooit vir gewone programme nodig te wees nie."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"luister vir waarnemings oor netwerktoestande"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Muurpapier"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Verander muurpapier"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kennisgewingluisteraar"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Toestandverskaffer"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN geaktiveer"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is geaktiveer deur <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak om die netwerk te bestuur."</string>
diff --git a/core/res/res/values-am/strings.xml b/core/res/res/values-am/strings.xml
index 22246c1..04bfee5 100644
--- a/core/res/res/values-am/strings.xml
+++ b/core/res/res/values-am/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ርዕስ አልባ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ሥምሪያ"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"በጣም ብዙ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ስርዞች።"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"የጡባዊ ተኮ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"የእጅ ሰዓት ማከማቻ ሙሉ ነው። ቦታ ለማስለቀቅ አንዳንድ ፋይሎችን ይሰርዙ።"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"የስልክ ማከማቻ ሙሉ ነው! ቦታ ነፃ ለማድረግ አንዳንድ ፋይሎች ሰርዝ።"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"አውታረ መረብ በክትትል ውስጥ ሊሆን ይችላል"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ባልታወቀ ሶስተኛ ወገን"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"መጥሪያ በርቷል"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"በመዝጋት ላይ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ጡባዊዎ ይዘጋል።"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"የእርስዎ የእጅ ሰዓት ይዘጋል።"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ስልክዎ ይዘጋል።"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"ዘግተህ መውጣት  ትፈልጋለህ?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"በአስተማማኝ ኹነታ ውስጥ ዳግም አስጀምር"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"የአውሮፕላን ሁነታ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"የአውሮፕላንሁነታ በርቷል"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"የአውሮፕላንሁነታ ጠፍቷል"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"ቅንብሮች"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"የሚያስተማምን ሁነታ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android ስርዓት"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"የነቃ መስኮት ይዘትን ለመበርበር ለመተግበሪያው ይፈቅዳሉ፡፡ ጠቅላላውን የመስኮት ይዘት ለመበርበር እና ከይለፍ ቃል በስተቀር ሁሉንም ጽሑፉን ለማየት ጎጂ መተግበሪያዎች ይችላሉ፡፡"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ተደራሽነት በጊዜያዊነት ያነቃል"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"አንድ መተግበሪያ በጊዜያዊነት በመሣሪያው ላይ ተደራሽነትን እንዲያነቃ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ያለተጠቃሚው ፍቃድ ተደራሽነትን ሊያነቁ ይችላሉ።"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"የመስኮት ማስመሰያ ሰርስሮ ያወጣል"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"አንድ መተግበሪያ የመስኮት ማስመሰያውን ሰርስሮ እንዲያወጣ ያስችላል። ተንኮል-አዘል ዌር ስርዓቱት በማስመሰል ከመተግበሪያው መስኮት ጋር ያልተፈቀደ መስተጋብር ሊፈጥሩ ይችላሉ።"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"የክፈፍ ስታቲስቲክሶችን ሰርስሮ ያወጣል"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"አንድ መተግበሪያ የክፈፍ ስታቲስቲክስን እንዲሰበስብ ያስችላል። ተንኮል-አዘል ዌር የሌሎች መተግበሪያዎች የክፈፍ ስታቲስቲክሶችን ሊመለከቱ ይችላሉ።"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"ክስተቶችን አጣራ"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"አንድ መተግበሪያ የሁሉንም ተጠቃሚዎች ክስተቶች ከመላካቸው በፊት እነሱን የሚያጣራ የግቤት ማጣሪያ እንዲመዘግብ ያስችለዋል። ተንኮል-አዘል መተግበሪያዎች ተጠቃሚው ጣልቃ ሳይገባ የስርዓቱን በይነገጽ ሊቆጣጠሩት ይችላሉ።"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ከፊል ዝጋ"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ኤስ ኤም ኤስ መልዕክት መቀበሉን ማሳወቂያ እንዲያሰራጭ ለመተግበሪያው ይፈቅዳሉ፡፡ መጪ ኤስ ኤም ኤስ መልዕክቶችን አመሳስሎ በማቅረብ  ተንኮል አዘል መተግበሪያዎች ይሄንን ሊጠቀሙበት ይችላሉ፡፡"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"የWAP-PUSH ደርስዋል ስርጭት ላክ"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"የWAP PUSH መልዕክት እንደተቀበለ ማሳወቂያ ለማሰራጨት ለመተግበሪያው ይፈቅዳሉ፡፡ ኤም ኤም ኤስ መልዕክት መቀበልን ለማስመሰል ወይም በተንኮል አዘል መሰሎች ለማንኛውም የድር ገፅ ይዘት በዝምታ ለመተካት ተንኮል አዘል መተግበሪያዎች ሊጠቀሙበት ይችላሉ፡፡"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ለአውታረ መረቦች የነጥብ ስጥ ስርጭት ይልካል"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"መተግበሪያው አውታረ መረቦች ነጥብ እንዲያዝለት የሚፈልጉት አንድ ማሳወቂያ እንዲያሰራጭ ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"የአሂድ ሂደቶችን ቁጥር ወስን"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"የሚሄዱ ሂደቶችን የመጨረሻ ቁጥር ለመቆጣጠር ለመተግበሪያው ይፈቅዳሉ፡፡ ለመደበኛ መተግበሪያዎች መቼም አያስፈልግም፡፡"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"የጀርባ መተግበሪያዎች እንዲዘጉ አስገድዳቸው"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"የVPN ግልጋሎትን ወደ ከፍተኛ-ደረጃ በየነ ገጽ ለማሳር ለመያዣው ይፈቅዳሉ፡፡ለተለመዱ መተግበሪያዎች አያስፈልግም፡፡"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"በልጣፍ ጠርዝ"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ልጣፍ ለመጠረዝ ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ከአንድ የድምጽ በይነተገናኝ ጋር ይሰሩ"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"ያዢው የአንድ የድምጽ በይነግንኙነት አገልግሎት የከፍተኛ ደረጃ በይነገጽ እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ከአንድ የርቀት ማሳያ ጋር ይጠርዛል"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ያዢው ከአንድ የርቀት ማሳያ ከፍተኛ-ደረጃ በይነገጽ ጋር እንዲጠርዝ ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ወደ ፍርግም አገልግሎት አያይዝ"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ያዡ ግቤት ስልቱን ወደ ከፍተኛ-ደረጃ ፍርግም አገልግሎት ለመጠረዝ  ይፈቅዳሉ። ለመደበኛ ትግበራዎች በፍፁም አያስፈልግም።"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ከመንገድ አቅራቢዎች አገልግሎት ጋር ያስተሳስሩ"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"አቃፊው ከማናቸውም የተመዘገቡ የመንገድ አቅራቢዎች ጋር እንዲተሳሰር ይፈቅድለታል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ከመሣሪያ አስተዳደር ጋር ተገናኝ"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ያዡ በይነመረብን ለመሣሪያ አስተዳዳሪ ለመላክ ይፈቅዳሉ። ለመደበኛ መተግበሪያዎች በፍፁም አያስፈልግም።"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ከአንድ የቴሌቪዥን ግብዓት ጋር እሰር"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"ባለቤቱ ከአንድ የቴሌቪዥን ግብዓት ከፍተኛ-ደረጃ በይነገጽ ጋር እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"የመሣሪያ አስተዳዳሪ ያክሉ ወይም ያስወግዱ"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ያዢው ንቁ የመሣሪያ አስተዳዳሪዎች እንዲያክል ወይም እንዲያስወግድ ያስችለዋል። ለመደበኛ መተግበሪያዎች ጭራሽ ሊያስፈልግ አይገባም።"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"የማያ ገፀ አቀማመጥን ለውጥ"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"መተግበሪያው ልክ እንደ ስምዎ እና የእውቂያ መረጃዎ ያሉ በመሳሪያዎ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲያነብ ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቁዎ እና የመገለጫ መረጃዎን ለሌሎች ሊልክ ይችላል።"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"የራስህን የዕውቂያ ካርድ አስተካክል"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"መተግበሪያው ልክ እንደ ስምዎ እና የእውቂያ መረጃዎ ያሉ በመሳሪያዎ ላይ የተከማቹ የግል መገለጫ መረጃዎችን እንዲቀይር ወይም እንዲያክልባቸው ይፈቅድለታል። ይህም ማለት መተግበሪያው ለይቶ ሊያውቅዎ እና የመገለጫ መረጃዎን ለሌሎች ሊልክ ይችላል።"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"የሰውነት መመርመሪያዎች (እንደ የልብ ምት መቆጣጠሪያዎች)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"መተግበሪያው እርስዎ በሰውነትዎ ውስጥ እየተካሄዱ ያሉ እንደ የልብ ምት የመሳሰሉ ነገሮችን ለመለካት የሚጠቀሙበትን ውሂብ ከመመርመሪያዎቹ ላይ እንዲደርስ ይፈቅድለታል።"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"የአንተን ማህበራዊ የውይይት ክፍሎች አንብብ"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"መተግበሪያው የአንተንና የጓኞችህን ማህበራዊ ዝማኔዎችን እንዲደርስባቸው እና እንዲያመሳስላቸው ይፈቅድለታል። መረጃ ስታጋራ ተጠንቀቅ -- ይህ መተግበሪያው ሚስጥራዊነትን ከግምት ሳያስገባ በማህበራዊ አውታረ መረቦች በአንተ እና በጓደኞችህ መካከል የሚደረጉ ግንኙነቶችን እንዲያነብ ይፈቅድለታል። ማስታወሻ፦ ይህ ፈቃድ ለሁሉም ማህበራዊ አውታር መረቦች ላይ ላይፈጸም ይችላል።"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ወደ የአንተ  ማህበራዊ የውይይት ክፍሎች ጻፍ"</string>
@@ -469,11 +508,11 @@
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"መተግበሪያው የጓደኞችህን እና የስራ ባልደረቦችህን ጨምሮ በጡባዊ ተኮህ ላይ ልታስተካክላቸው የምትችላቸውን ክስተቶች እንዲያክል፣ እንዲያስወግድ፣ እንዲለውጥ ይፈቅድለታል። ይህ መተግበሪያው ከቀን መቁጠሪያ ባለቤቶች የመጡ የሚመስሉ መልእክቶችን እንዲልክ ወይም ያለባለቤቱ እውቀት ክስተቶችን እንዲያስተካክል ሊፈቅድለት ይችላል።"</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"መተግበሪያው የጓደኞችዎን እና የስራ ባልደረቦችዎን ጨምሮ በስልክዎ ላይ ሊያስተካክሏቸው የሚችሏቸውን ክስተቶች እንዲያክል፣ እንዲያስወግድ፣ እንዲለውጥ ይፈቅድለታል። ይህ መተግበሪያው ከቀን መቁጠሪያ ባለቤቶች የመጡ የሚመስሉ መልዕክቶችን እንዲልክ ወይም ያለባለቤቱ እውቀት ክስተቶችን እንዲያስተካክል ሊፈቅድለት ይችላል።"</string>
     <string name="permlab_accessMockLocation" msgid="8688334974036823330">"ለሙከራ ጊዜያዊ ሥፍራ ፍጠር።"</string>
-    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"ለሙከራ የማስመሰል የመነሻ ምንጮችን ፍጠር ወይም አዲስ የአካባቢ አቅራቢ ጫን። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ GPS ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
+    <string name="permdesc_accessMockLocation" msgid="5808711039482051824">"ለሙከራ የጊዜያዊ የመነሻ ምንጮችን ይፍጠሩ ወይም አዲስ የአካባቢ አቅራቢ ይጫኑ። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ GPS ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
     <string name="permlab_accessLocationExtraCommands" msgid="2836308076720553837">"ተጨማሪ ሥፍራ አቅራቢ ትዕዛዞችን ድረስ።"</string>
     <string name="permdesc_accessLocationExtraCommands" msgid="5945166642335800763">"መተግበሪያው ተጨማሪ የአካባቢ አቅራቢ ትእዛዞችን እንዲደርስ ይፈቅድለታል። ይህ መተግበሪያው በGPS ወይም ሌላ የመነሻ ምንጮች ክወና ላይ ጣልቃ እንዲገባ ሊፈቅድለት ይችላል።"</string>
     <string name="permlab_installLocationProvider" msgid="6578101199825193873">"የሥፍራ አቅራቢ ለመጫን ፍቀድ"</string>
-    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"ለሙከራ የማስመሰል የመነሻ ምንጮችን ፍጠር ወይም አዲስ የአካባቢ አቅራቢ ጫን። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ GPS ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
+    <string name="permdesc_installLocationProvider" msgid="9066146120470591509">"ለሙከራ የጊዜያዊ የመነሻ ምንጮችን ይፍጠሩ ወይም አዲስ የአካባቢ አቅራቢ ይጫኑ። ይህ መተግበሪያው አካባቢውን እና/ወይም እንደ ጂፒኤስ ወይም የአካባቢ አቅራቢዎች ባሉ ሌላ የመነሻ ምንጮች የተመለሱ ሁኔታዎችን ችላ እንዲል ይፈቅድለታል።"</string>
     <string name="permlab_accessFineLocation" msgid="1191898061965273372">"ትክክለኛ አካባቢ (በጂ ፒ ኤስ እና አውታረ መረብ ላይ የተመሠረተ)"</string>
     <string name="permdesc_accessFineLocation" msgid="5295047563564981250">"መተግበሪያው የእርስዎን አለምአቀፍ የመሬት አቀማመጥ ስርዓትን (ጂ ፒ ኤስ) ወይም እንደ የተንቀሳቃሽ ስልክ ማማዎች እና Wi-Fi ያሉ የአውታረ መረብ አካባቢ ምንጮችን ተጠቅሞ ትክክለኛ አካባቢዎትን እንዲያውቅ ያስችለዋል። መተግበሪያው እነዚህ የአካባቢ አገልግሎቶችን እንዲጠቀምባቸው እነሱ ሊበሩ እና ለመሣሪያዎ የሚገኙ መሆን አለባቸው። መተግበሪያዎች እርስዎ የት እንዳሉ ለማወቅ ይህንን ሊጠቀሙበት ይችላሉ፣ እና ተጨማሪ ባትሪ ሊፈጁ ይችላሉ።"</string>
     <string name="permlab_accessCoarseLocation" msgid="4887895362354239628">"ግምታዊ አካባቢ (በአውታረ መረብ ላይ የተመሰረተ)"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"የWiMAX ሁኔታ ለውጥ"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"መተግበሪያው ጡባዊ ተኮውን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"መተግበሪያው ስልኩን ከWiMAX አውታረ መረብ ጋር እንዲያገናኝና እንዲያለያይ ይፈቅድለታል።"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ለአውታረ መረቦች ነጥብ ይሰጣል"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"መተግበሪያው ለአውታረ መረቦች ደረጃ እንዲሰጥ እና ጡባዊው የትኛዎቹን አውታረ መረቦች እንደሚመርጥ ላይ ተጽዕኖ እንዲያሳርፍ ያስችለዋል።"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"መተግበሪያው ለአውታረ መረቦች ደረጃ እንዲሰጥ እና ስልኩ የትኛዎቹን አውታረ መረቦች እንደሚመርጥ እና ላይ ተጽዕኖ እንዲያሳርፍ ያስችለዋል።"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ከብሉቱዝ መሣሪያዎች ጋር ተጣመር"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"መተግበሪያው በጡባዊ ተኮው ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"መተግበሪያው በስልኩ ላይ ያለውን የብሉቱዝ ውቅር እንዲያይ እና ከተጣመሩ መሳሪያዎች ጋር ግንኙነቶችን እንዲያደርግና እንዲቀበል ይፈቅድለታል።"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"መተግበሪያው ማሳወቂያዎችን እንዲያስመጣ፣ እንዲመረምር እና እንዲያጸዳ ያስችለዋል፣ በሌሎች መተግበሪያዎች የተለጠፉትንም ጨምሮ።"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ከአንድ የማሳወቂያ አዳማጭ አገልግሎት ጋር ይሰሩ"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ያዢው የማሳወቂያ አዳማጭ አገልግሎቱን ከከፍተኛ-ደረጃ በይነገጹ ጋር እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ከአንድ የሁኔታ አቅራቢ አገልግሎት ጋር ይሰሩ"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"ያዢው የአንድ የሁኔታ አቅራቢ አገልግሎት የከፍተኛ ደረጃ በይነገጽ እንዲያስር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን መጥራት"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ያዢው በድምጸ-ተያያዥ ሞደም የቀረበው የውቅር መተግበሪያውን እንዲጠራው ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ አያስፈልግም።"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"በአውታረ መረብ ሁኔታዎች ላይ የተስተዋሉ ነገሮችን ያዳምጣል"</string>
@@ -688,7 +732,7 @@
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"የግቤት መሣሪያ ማስተካከያ ቀይር"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"መተግበሪያው የማያ ንካ የማስተካከያ ልኬቶቹን እንዲቀይር ያስችለዋል። ለመደበኛ መተግበሪያዎች በጭራሽ ሊያስፈልግ አይገባም።"</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"የDRM የምስክር ወረቀቶች ላይ ይድረሱ"</string>
-    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"አንድ መተግበሪያ የDRM የምስክር ወረቀቶችን እንዲሰጥና እንዲጠቀም ያስችላል። ለመደበኛ መተግበሪያዎች በፍጹም አስፈላጊ አይሆንም።"</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"የይለፍ ቃል ደንቦች አዘጋጅ"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"በማያ-መክፈት የተፈቀዱ የይለፍ ቃል ርዝመት እና ቁምፊዎች ተቆጣጠር።"</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"የማሳያ-ክፈት ሙከራዎችን አሳይ"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ልጣፍ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ልጣፍ ለውጥ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ማሳወቂያ አዳማጭ"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"የሁኔታ አቅራቢ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ነቅቷል።"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN በ<xliff:g id="APP">%s</xliff:g>ገብሯል"</string>
     <string name="vpn_text" msgid="3011306607126450322">"አውታረመረብ ለማደራጀት  ንካ።"</string>
diff --git a/core/res/res/values-ar/strings.xml b/core/res/res/values-ar/strings.xml
index 9efd8eb..83168e4 100644
--- a/core/res/res/values-ar/strings.xml
+++ b/core/res/res/values-ar/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"تيرابايت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"بيتابايت"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بلا عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"مزامنة"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"عمليات حذف <xliff:g id="CONTENT_TYPE">%s</xliff:g> كثيرة للغاية."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"سعة تخزين الجهاز اللوحي ممتلئة! احذف بعض الملفات لإخلاء مساحة."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"سعة تخزين المشاهدة ممتلئة! احذف بعض الملفات لتحرير مساحة."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"سعة تخزين الهاتف ممتلئة. احذف بعض الملفات لإخلاء مساحة."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"قد تكون الشبكة مراقبة"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"بواسطة جهة خارجية غير معلومة"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"تشغيل الرنين"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"جارٍ إيقاف التشغيل..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"سيتم إيقاف تشغيل الجهاز اللوحي."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"سيتم إيقاف المشاهدة."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"سيتم إيقاف تشغيل هاتفك."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"هل تريد إيقاف التشغيل؟"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"إعادة تشغيل في الوضع الآمن"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"وضع الطائرة"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"وضع الطائرة قيد التشغيل"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"وضع الطائرة متوقف"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"الإعدادات"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"الوضع الآمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏نظام Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"للسماح للتطبيق باسترداد محتوى النافذة النشطة. يمكن للبرامج الضارة استرداد محتوى النافذة بالكامل وفحص جميع النصوص الموجودة بها باستثناء كلمات المرور."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"تمكين إمكانية الدخول مؤقتًا"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"يتيح لتطبيق تمكين إمكانية الدخول مؤقتًا بالجهاز. قد تتيح التطبيقات الضارة تمكين إمكانية الدخول بدون موافقة المستخدم."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"استرداد النافذة التي تم التقاطها"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"يتيح للتطبيق استعادة النافذة التي تم التقاطها. وقد تتمكن التطبيقات الضارة من تنفيذ تفاعل غير مصرح به مع نافذة التطبيق التي تنتحل صفة النظام."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"استرداد الإحصاءات الإطارية"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"يتيح للتطبيق جمع إحصاءات إطارية. وقد تتمكن التطبيقات الضارة من رصد الإحصاءات الإطارية للنوافذ من تطبيقات أخرى."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"تصفية الأحداث"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"للسماح لأحد التطبيقات بتسجيل فلتر إدخال يعمل على تصفية مجموعة البث من جميع أحداث المستخدمين قبل إرسالها. يمكن أن يتحكم برنامج ضار في واجهة المستخدم النظام دون تدخل المستخدم."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"إيقاف تشغيل جزئي"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"‏للسماح للتطبيق ببث إشعار باستلام رسالة قصيرة SMS. قد تستخدم التطبيقات الضارة هذا لتزييف الرسائل القصيرة SMS الواردة."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"‏إرسال بث WAP-PUSH المستلم"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"‏للسماح للتطبيق ببث إشعار باستلام رسالة WAP PUSH. يمكن أن تستخدم التطبيقات الضارة هذا لتزيف استلام رسالة وسائط متعددة أو لاستبدال محتوى أي صفحة ويب بمتغيرات ضارة بشكل غير ملحوظ."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"إرسال بث الشبكات التي تم تقييمها"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"السماح للتطبيق لكي يبث إشعارًا يفيد بأنه يلزم تقييم الشبكات. لا يلزم ذلك مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"تحديد عدد العمليات قيد التشغيل"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"للسماح للتطبيق بالتحكم في الحد الأقصى لعدد العمليات التي سيتم تشغيلها. غير مطلوب على الإطلاق للتطبيقات العادية."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"فرض إغلاق تطبيقات الخلفية"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الشبكة الظاهرية الخاصة (VPN). لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"الالتزام بخلفية ما"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للخلفية. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"الربط بخدمة التفاعل الصوتي"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة التفاعل الصوتي. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"الربط بالشاشة عن بُعد"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"للسماح للمالك بالالتزام بواجهة المستوى العلوي للعرض عن بُعد. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"الالتزام بخدمة أداة"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لخدمة الأداة. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"الربط مع خدمة مزود طريق"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"للسماح لحامل البطاقة الربط مع أي مزود طريق مسجل. لا يجب استخدامه على الإطلاق مع التطبيقات العادية."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"التفاعل مع مشرف الجهاز"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"للسماح للمالك بإرسال الأهداف إلى أحد مشرفي الجهاز. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"الالتزام بإدخال التلفزيون"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"للسماح للمالك بالالتزام بواجهة المستوى العلوي لإدخال التلفزيون. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"إضافة مشرف جهاز أو إزالته"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"للسماح بحامل البطاقة بإضافة مشرفي أجهزة نشطين أو إزالتهم. لا يلزم ذلك أبدًا للتطبيقات العادية."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"تغيير اتجاه الشاشة"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"للسماح للتطبيق بقراءة المعلومات الشخصية في الملف الشخصي المخزنة على الجهاز، مثل اسمك ومعلومات جهات الاتصال. ويعني ذلك أنه يمكن للتطبيق التعرف عليك كما يمكنه إرسال معلومات ملفك الشخصي إلى الآخرين."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"تعديل بطاقة جهة الاتصال الخاصة"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"للسماح للتطبيق بتغيير المعلومات الشخصية في الملف الشخصي المخزنة على الجهاز أو الإضافة إليها، مثل اسمك ومعلومات جهات الاتصال. ويعني ذلك أنه يمكن للتطبيق التعرف عليك كما يمكنه إرسال معلومات ملفك الشخصي إلى الآخرين."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"أجهزة استشعار الجسم (مثل شاشات معدل ضربات القلب)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"للسماح للتطبيق بالدخول إلى البيانات من أجهزة الاستشعار التي تستخدمها لقياس ما يجري داخل جسمك، مثل معدل ضربات القلب."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"قراءة المشاركات الاجتماعية"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"للسماح للتطبيق بالدخول إلى التحديثات الاجتماعية منك ومن أصدقائك ومزامنتها. توخ الحذر عند مشاركة المعلومات، حيث يتيح هذا للتطبيق قراءة عمليات التواصل بينك وبين أصدقائك على الشبكات الاجتماعية، بغض النظر عن مدى السرية. ملاحظة: لا يجوز فرض هذا الإذن على جميع الشبكات الاجتماعية."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"كتابة إلى المشاركات الاجتماعية"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"‏تغيير حالة WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"‏للسماح للتطبيق بتوصيل الجهاز اللوحي بشبكات WiMAX وقطع اتصاله بها."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"‏للسماح للتطبيق بتوصيل الهاتف بشبكات WiMAX وقطع اتصاله بها."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"تقييم الشبكات"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"للسماح للتطبيق بترتيب الشبكات وتحديد تلك الشبكات التي من المفضل أن يستخدمها الجهاز اللوحي."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"للسماح للتطبيق بترتيب الشبكات وتحديد تلك الشبكات التي من المفضل أن يستخدمها الهاتف."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"الاتصال بأجهزة بلوتوث"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"للسماح للتطبيق بعرض تهيئة البلوتوث على الجهاز اللوحي وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"للسماح للتطبيق بعرض تهيئة البلوتوث على الهاتف وإجراء اتصالات وقبولها مع الأجهزة المقترنة."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"يتيح للتطبيق استرجاع الإشعارات وفحصها ومسحها، بما في ذلك تلك التي نشرتها تطبيقات أخرى."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"الربط بخدمة تلقّي الإشعارات الصوتية"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"يتيح للمالك الربط بواجهة المستوى العلوي لخدمة تلقّي الإشعارات الصوتية. ولن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"الربط بخدمة موفر الحالة"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"للسماح للمالك بالربط بواجهة المستوى العلوي لخدمة موفر الحالة. لن تكون هناك حاجة إلى هذا الإعداد مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"استدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"للسماح للمالك باستدعاء تطبيق التهيئة الذي يوفره مشغل شبكة الجوال. لن تكون هناك حاجة إليه مطلقًا مع التطبيقات العادية."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"الاستماع إلى ملاحظات حول أحوال الشبكة"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"الخلفية"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغيير الخلفية"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"برنامج تلقّي الإشعارات الصوتية"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"موفر الحالة"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏تم تنشيط الشبكة الظاهرية الخاصة (VPN)"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏تم تنشيط VPN بواسطة <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"المس لإدارة الشبكة."</string>
diff --git a/core/res/res/values-bg/strings.xml b/core/res/res/values-bg/strings.xml
index 366de7c..2d22cdc 100644
--- a/core/res/res/values-bg/strings.xml
+++ b/core/res/res/values-bg/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без заглавие&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхронизиране"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Изтриванията за <xliff:g id="CONTENT_TYPE">%s</xliff:g> са твърде много."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Хранилището на таблета е пълно. Изтрийте файлове, за да освободите място."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Хранилището на часовника е пълно. Изтрийте файлове, за да освободите място."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Хранилището на телефона е пълно. Изтрийте файлове, за да освободите място."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежата може да се наблюдава"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"От неизвестна трета страна"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Звъненето е включено"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Изключва се..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблетът ви ще се изключи."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Часовникът ви ще се изключи."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефонът ви ще се изключи."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Искате ли да изключите?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Рестартиране в безопасен режим"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Самолетен режим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Самолетният режим е ВКЛЮЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Самолетният режим е ИЗКЛЮЧЕН"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Настройки"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасен режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Системно от Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Разрешава на приложението да извлича съдържанието от активния прозорец. Злонамерените приложения могат да извлекат цялото му съдържание и да проследят целия текст в него освен паролите."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"временно активиране на достъпността"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Разрешава на приложението временно да активира достъпността на устройството. Злонамерените приложения може да я активират без съгласието на потребителя."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"извличане на означението за прозорци"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Разрешава на приложението да извлича означението за прозорци. Представяйки се за системата, злонамерените приложения може да извършат неупълномощено взаимодействие с прозореца на приложението."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"извличане на статистически данни за кадрите"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Разрешава на приложението да събира статистически данни за кадрите. Злонамерените приложения може да наблюдават тези данни за прозорците на други приложения."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"филтриране на събитията"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешава на приложението да регистрира входящ филтър, който филтрира потока на всички потребителски събития преди изпращането им. Злонамерено приложение може да контролира системния потребителски интерфейс без намесата на потребителя."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частично изключване"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Разрешава на приложението да излъчва известие, че е получен SMS. Злонамерените приложения могат да използват това, за да фалшифицират входящите SMS съобщения."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"изпращане на излъчване при получено WAP PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Разрешава на приложението да излъчва известие, че е получено WAP PUSH съобщение. Злонамерените приложения могат да използват това, за да фалшифицират получаването на MMS или скрито да заменят съдържанието на произволна уеб страница със злонамерен вариант."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"изпращане на излъчване за оценяване на мрежите"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Разрешава на приложението да излъчи известие, че мрежите трябва да бъдат оценени. Не е необходимо за нормалните приложения."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ограничаване на броя изпълнявани процеси"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Разрешава на приложението да контролира максималния брой изпълнявани процеси. Нормалните приложения никога не се нуждаят от това."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудително затваряне на приложенията на заден план"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за VPN. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обвързване с тапет"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на тапет. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"свързване с услуга за гласово взаимодействие"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за гласово взаимодействие. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"свързване с отдалечен екран"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Разрешава на притежателя да се свърже с интерфейса от първо ниво на отдалечен екран. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обвързване с услуга за приспособления"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Разрешава на притежателя да се обвърже с интерфейса от най-високото ниво на услуга за приспособления. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"свързване с услуга за предоставяне на маршрути"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Разрешава на собственика да се свързва с всички регистрирани доставчици на маршрути. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаимодействие с администратор на устройството"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Разрешава на притежателя да изпраща намерения до администратор на устройството. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"свързване към вход на телевизор"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Разрешава на притежателя да се свърже към интерфейса от най-високото ниво за вход на телевизор. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"добавяне или премахване на администратор на устройства"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Разрешава на притежателя да добавя или премахва администратори на активни устройства. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"промяна на ориентацията на екрана"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Разрешава на приложението да чете информацията от личния потребителски профил, съхранена на устройството ви, например вашето име и данни за връзка. Това означава, че приложението може да ви идентифицира и да изпраща информацията за потребителския ви профил на други хора."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"промяна на собств. ви карт. с данни за контакт"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Разрешава на приложението да променя или добавя към личния потребителски профил информация, съхранена на устройството ви, като например вашето име и данни за връзка. Това означава, че приложението може да ви идентифицира и да изпраща данните за потребителския ви профил на други хора."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"телесни сензори (като монитори за сърдечния ритъм)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Разрешава на приложението да осъществява достъп до данни от използваните от вас сензори, за да измери какво се случва в тялото ви, като например сърдечен ритъм."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"четене на социалния ви поток"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Разрешава на приложението да осъществява достъп и да синхронизира социални актуализации от вас и приятелите ви. Бъдете внимателни при споделянето на информация – това позволява на приложението да чете съобщения помежду ви в социалните мрежи независимо от поверителността. Забележка: Възможно е ограниченията на това разрешение да не могат да бъдат наложени във всички социални мрежи."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писане в социалния ви поток"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промяна на състоянието на WiMAX мрежата"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Разрешава на приложението да свързва таблета към WiMAX мрежа и да прекратява връзката му с нея."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Разрешава на приложението да свързва телефона към WiMAX мрежа и да прекратява връзката му с нея."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"оценяване на мрежите"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Разрешава на приложението да класира мрежите и да повлияе върху това, кои да са предпочитаните за таблета."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Разрешава на приложението да класира мрежите и да повлияе върху това, кои да са предпочитаните за телефона."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"сдвояване с устройства с Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Разрешава на приложението да вижда конфигурацията на Bluetooth на таблета и да изгражда и приема връзки със сдвоени устройства."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Разрешава на приложението да вижда конфигурацията на Bluetooth на телефона и да изгражда и приема връзки със сдвоени устройства."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Разрешава на приложението да извлича, преглежда и изчиства известия, включително публикуваните от други приложения."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"обвързване с услуга за слушател на известия"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Разрешава на притежателя да се обвърже с интерфейса от първо ниво на услуга за слушател на известия. Нормалните приложения не би трябвало никога да се нуждаят от това."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"свързване с услуга за предоставяне на условия"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Разрешава на притежателя да се свърже с интерфейса от най-високото ниво на услуга за предоставяне на условия. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"извикване на предоставеното от оператора приложение за конфигуриране"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Разрешава на притежателя да извиква предоставеното от оператора приложение за конфигуриране. Нормалните приложения би трябвало никога да не се нуждаят от това."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"слушане за наблюдения на мрежовите условия"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Тапет"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промяна на тапета"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Слушател на известия"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Доставчик на условия"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN е активирана"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN е активирана от <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Докоснете за управление на мрежата."</string>
diff --git a/core/res/res/values-ca/strings.xml b/core/res/res/values-ca/strings.xml
index 6cba689..cfb77d3 100644
--- a/core/res/res/values-ca/strings.xml
+++ b/core/res/res/values-ca/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sense títol&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronització"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Massa supressions de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"L\'emmagatzematge de la tauleta és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"L\'emmagatzematge del rellotge està ple. Suprimeix uns quants fitxers per alliberar espai."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"L\'emmagatzematge del telèfon és ple. Suprimeix uns quants fitxers per alliberar espai."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"És possible que la xarxa estigui supervisada"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Per un tercer desconegut"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Timbre activat"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"S\'està apagant..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"La tauleta s\'apagarà."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"El rellotge s\'apagarà."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"El telèfon s\'apagarà."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vols apagar-lo?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reinicia en mode segur"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode d\'avió"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode d\'avió activat"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode d\'avió desactivat"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Configuració"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"+999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode segur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet que l\'aplicació recuperi el contingut de la finestra activa. Les aplicacions malicioses poden recuperar el contingut de tota la finestra i examinar-ne tot el text, excepte les contrasenyes."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activació temporal de l\'accessibilitat"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet que una aplicació activi temporalment l\'accessibilitat al dispositiu. És possible que les aplicacions malicioses activin l\'accessibilitat sense el consentiment de l\'usuari."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"recuperació del testimoni de la finestra"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permet que una aplicació recuperi el testimoni de la finestra. Les aplicacions malicioses poden suplantar la identitat del sistema per dur a terme una interacció no autoritzada amb la finestra de l\'aplicació."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"recuperació d\'estadístiques de fotogrames"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permet que una aplicació recopili estadístiques de fotogrames. Les aplicacions malicioses poden veure les estadístiques de fotogrames de finestres d\'altres aplicacions."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtra els esdeveniments"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet que una aplicació registri un filtre d\'entrada per a l\'emissió de tots els esdeveniments d\'usuari abans no s\'enviïn. Aplicacions malicioses podrien controlar la IU del sistema sense la intervenció de l\'usuari."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"apagar parcialment"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet que l\'aplicació difongui una notificació en què s\'indiqui que s\'ha rebut un missatge SMS. Les aplicacions malicioses poden fer servir aquesta funció per falsificar els missatges SMS entrants."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar una difusió de tipus WAP-PUSH-received"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet que l\'aplicació difongui una notificació que indica que s\'ha rebut un missatge d\'inserció WAP. Les aplicacions malicioses poden utilitzar-ho per falsificar la recepció dels missatges MMS o per substituir silenciosament el contingut d\'una pàgina web per variants malicioses."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar l\'emissió de la puntuació de les xarxes"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permet que l\'aplicació emeti una notificació necessària perquè les xarxes rebin una puntuació. No es necessita mai per a les aplicacions normals."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar el nombre de processos en execució"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet que l\'aplicació controli el nombre màxim de processos que s\'executaran. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"com fer que es tanquin les aplicacions en segon pla"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de VPN. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enllaça amb un fons de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet que el titular vinculi a la interfície de nivell superior d\'un fons de pantalla. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vinculació amb una eina d\'interacció de veu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet que el titular es vinculi amb la interfície de nivell superior d\'un servei d\'interacció de veu. No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincula a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet que el titular es vinculi a la interfície de nivell superior d\'una pantalla remota. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincula a un servei de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet que el titular vinculi a la interfície de nivell superior d\'un servei de widget. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"establir vincles amb un servei d\'aprovisionament de rutes"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permet que el titular estableixi vincles amb els proveïdors de rutes registrats. No hauria de ser mai necessari per a les aplicacions normals."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar amb un administrador del dispositiu"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet que el titular enviï intents a un administrador del sistema. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"Vinculació a una entrada de televisor"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permet que el titular es vinculi a la interfície de nivell superior d\'una entrada de televisor. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"afegeix un administrador al dispositiu o suprimeix-lo"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet que el titular afegeixi administradors actius al dispositiu o en suprimeixi. No s\'hauria de necessitar per a les aplicacions normals."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"canviar l\'orientació de la pantalla"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permet que l\'aplicació pugui llegir informació del perfil personal emmagatzemada al dispositiu, com ara el teu nom i la teva informació de contacte. Això significa que l\'aplicació et pot identificar i enviar la informació del teu perfil a altres persones."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modificació targeta contacte"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet que l\'aplicació pugui canviar o afegir informació del perfil personal emmagatzemada al dispositiu, com ara el teu nom i la teva informació de contacte. Això significa que l\'aplicació et pot identificar i enviar la informació del teu perfil a altres persones."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensors corp. (monitors freq. cardíaca)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet que l\'aplicació accedeixi a les dades dels sensors que utilitzes per mesurar els signes vitals del teu cos, com ara la freqüència cardíaca."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"llegeix el teu tauler d\'activitat social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet que l\'aplicació accedeixi i sincronitzi actualitzacions socials teves i dels teus amics. Vés amb compte en compartir informació: això permet que l\'aplicació llegeixi comunicacions entre tu i els teus amics a les xarxes socials, independentment de la confidencialitat. Nota: És possible que aquest permís no s\'apliqui a totes les xarxes socials."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escriu al tauler d\'activitat social"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Canvia l\'estat de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet que l\'aplicació connecti i desconnecti la tauleta de les xarxes WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet que l\'aplicació connecti i desconnecti el telèfon de les xarxes WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar les xarxes"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permet que l\'aplicació classifiqui les xarxes i indiqui quines han de ser les xarxes preferides de la tauleta."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permet que l\'aplicació classifiqui les xarxes i indiqui quines han de ser les xarxes preferides del telèfon."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"emparella amb dispositius Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet que l\'aplicació visualitzi la configuració de Bluetooth de la tauleta i que estableixi i accepti connexions amb dispositius sincronitzats."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet que una aplicació visualitzi la configuració de Bluetooth del telèfon i que estableixi i accepti connexions amb els dispositius sincronitzats."</string>
@@ -681,24 +723,26 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet que l\'aplicació recuperi, examini i esborri les notificacions, incloses les que han publicat altres aplicacions."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincula a un servei oient de notificacions"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet que el titular vinculi la interfície de nivell superior d\'un servei oient de notificacions. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vinculació amb el servei d\'un proveïdor de condicions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet que el titular es vinculi amb la interfície de nivell superior del servei d\'un proveïdor de condicions. No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoca l\'aplicació de configuració proporcionada per l\'operador"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet que el titular invoqui l\'aplicació de configuració proporcionada per l\'operador. No s\'hauria de necessitar mai per a les aplicacions normals."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"conèixer les observacions sobre les condicions de la xarxa"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permet que una aplicació conegui les observacions sobre les condicions de la xarxa. No s\'ha de necessitar mai per a aplicacions normals."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"canviar el calibratge del dispositiu d\'entrada"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permet que l\'aplicació modifiqui els paràmetres de calibratge de la pantalla tàctil. No ha de ser mai necessari per a aplicacions normals."</string>
-    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accés als certificats de DRM"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accedir als certificats de DRM"</string>
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permet que una aplicació proporcioni i utilitzi certificats de gestió de drets digitals (DRM, Digital Rights Management). No ha de ser mai necessari per a aplicacions normals."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Definir les normes de contrasenya"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Controla la longitud i els caràcters permesos a les contrasenyes de desbloqueig de pantalla."</string>
-    <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar intents de desbloqueig de pantalla"</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Controlar els intents de desbloqueig de pantalla"</string>
     <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Supervisa el nombre de contrasenyes incorrectes introduïdes per desbloquejar la pantalla i bloqueja la tauleta o n\'esborra totes les dades si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Supervisa el nombre de contrasenyes incorrectes introduïdes en desbloquejar la pantalla, i bloqueja el telèfon o esborra totes les dades del telèfon si s\'introdueixen massa contrasenyes incorrectes."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Canvia la contrasenya de desbloqueig de pantalla"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Canvia la contrasenya de desbloqueig de pantalla."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Bloqueig de pantalla"</string>
     <string name="policydesc_forceLock" msgid="1141797588403827138">"Controla com i quan es bloqueja la pantalla."</string>
-    <string name="policylab_wipeData" msgid="3910545446758639713">"Esborra totes les dades"</string>
+    <string name="policylab_wipeData" msgid="3910545446758639713">"Esborrar totes les dades"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Esborra les dades de la tauleta sense advertiment mitjançant un restabliment de les dades de fàbrica."</string>
     <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Esborra les dades del telèfon sense avisar, restablint les dades de fàbrica."</string>
     <string name="policylab_setGlobalProxy" msgid="2784828293747791446">"Defineix el servidor intermediari global del dispositiu"</string>
@@ -708,7 +752,7 @@
     <string name="policylab_encryptedStorage" msgid="8901326199909132915">"Encriptació d’emmagatzematge"</string>
     <string name="policydesc_encryptedStorage" msgid="2637732115325316992">"Requereix que les dades de l\'aplicació emmagatzemades estiguin encriptades."</string>
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Desactivar les càmeres"</string>
-    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedeix l\'ús de totes les càmeres del dispositiu."</string>
+    <string name="policydesc_disableCamera" msgid="2306349042834754597">"Impedeix l\'ús de les càmeres del dispositiu."</string>
     <string name="policylab_disableKeyguardFeatures" msgid="266329104542638802">"Des. funcions en bloq. tecles"</string>
     <string name="policydesc_disableKeyguardFeatures" msgid="3467082272186534614">"Impedeix l\'ús d\'algunes funcions en bloqueig de tecles."</string>
   <string-array name="phoneTypes">
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fons de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Canvia el fons de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Oient de notificacions"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveïdor de condicions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> ha activat VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca per gestionar la xarxa."</string>
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index b4972ef..868f899 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez názvu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronizace"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Příliš mnoho smazaných položek služby <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Úložiště tabletu je plné. Uvolněte místo smazáním některých souborů."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Úložiště hodinek je plné. Uvolněte místo smazáním některých souborů."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Paměť telefonu je plná. Uvolněte místo smazáním některých souborů."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Síť může být monitorována"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Původce: neznámá třetí strana"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Vyzvánění zapnuto"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Vypínání..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet se vypne."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Hodinky se vypnou."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Váš telefon bude vypnut."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Chcete zařízení vypnout?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Restart v nouzovém režimu"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V letadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V letadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V letadle je VYPNUTÝ"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Nastavení"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Nouzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikaci načíst obsah aktivního okna. Škodlivé aplikace mohou načíst obsah celého okna a prozkoumat všechen text kromě hesel."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasná aktivace usnadnění přístupu"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikaci dočasně aktivovat usnadnění přístupu v zařízení. Škodlivé aplikace mohou usnadnění přístupu aktivovat bez souhlasu uživatele."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"načíst token okna"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Umožňuje aplikaci načíst token okna. Škodlivé aplikace se mohou vydávat za systém a provádět s oknem aplikace neoprávněné interakce."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"načíst statistiky rámců"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Umožňuje aplikaci shromažďovat statistiky rámců. Škodlivé aplikace mohou sledovat statistiky rámců oken ostatních aplikací."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrování událostí"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožní aplikaci registrovat vstupní filtr, který filtruje stream všech uživatelských přenosů před jejich odvysíláním. Škodlivé aplikace mohou používat uživatelské rozhraní systému bez zásahu uživatele."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"částečné vypnutí"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Umožňuje aplikaci vysílat oznámení o přijetí zprávy SMS. Škodlivé aplikace mohou toto oprávnění použít k vytváření falešných příchozích zpráv SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"odeslání vysílání typu WAP-PUSH-received"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Umožňuje aplikaci vysílat oznámení o přijetí zprávy WAP PUSH. Škodlivé aplikace mohou toto oprávnění použít k vytváření falešných přijatých zpráv MMS nebo utajenému nahrazení obsahu libovolné webové stránky jejich škodlivými variantami."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"odeslání skóre vysílaných sítěmi"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Umožňuje aplikaci vysílat oznámení, že je třeba zadat skóre sítí. Běžné aplikace toto oprávnění nepotřebují."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"omezení počtu spuštěných procesů"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikaci řídit maximální počet spuštěných procesů. Běžné aplikace toto oprávnění nikdy nepotřebují."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynucení zavření aplikací na pozadí"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteli navázat se na nejvyšší úroveň služby VPN. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vazba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní tapety. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"navázání na hlasovou interakci"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby hlasové interakce. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"připojit se ke vzdálenému displeji"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteli připojit se k vysokoúrovňovému rozhraní vzdáleného displeje. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"navázat se na službu widgetu"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteli navázat se na nejvyšší úroveň služby widgetu. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"navázání na službu poskytovatele tras"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umožňuje držiteli navázat se na libovolného poskytovatele registrovaných tras. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovat se správcem zařízení"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteli oprávnění odesílat informace správci zařízení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"navázání na televizní vstup"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní televizního vstupu. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"přidat nebo odebrat správce zařízení"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Opravňuje držitele přidávat nebo odebírat aktivní správce zařízení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"změna orientace obrazovky"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Umožňuje aplikaci číst údaje v osobním profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"úprava vaší vlastní vizitky"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikaci změnit nebo přidat údaje osobního profilu uložené v zařízení, například jméno nebo kontaktní údaje. Znamená to, že vás aplikace může identifikovat a odeslat údaje z profilu dalším aplikacím."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"tělesné senzory (například snímače tepu)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Umožňuje aplikaci přistupovat k datům ze senzorů, pomocí kterých měříte činnost svého těla, například tep."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čtení vašeho sociálního streamu"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikaci získat přístup k sociálním aktualizacím od vašich přátel a synchronizaci těchto aktualizací. Při sdílení informací buďte opatrní – toto oprávnění umožňuje aplikaci číst komunikaci mezi vámi a vašimi přáteli v sociálních sítích bez ohledu na její důvěrnost. Poznámka: Toto oprávnění nemusí platit pro všechny sociální sítě."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zápis do sociálního streamu"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Změnit stav připojení WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikaci připojovat tablet k sítím WiMAX a odpojovat jej od nich."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Umožňuje aplikaci připojovat telefon k sítím WiMAX a odpojovat jej od nich."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"zadání skóre sítí"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Umožňuje aplikaci hodnotit sítě a ovlivňovat, které sítě by měl tablet preferovat."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Umožňuje aplikaci hodnotit sítě a ovlivňovat, které sítě by měl telefon preferovat."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"párování se zařízeními Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikaci zobrazit konfiguraci tabletu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikaci zobrazit konfiguraci telefonu s rozhraním Bluetooth, vytvářet připojení ke spárovaným zařízením a přijímat tato připojení."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikacím načítat, zobrazovat a mazat oznámení včetně těch přidaných jinými aplikacemi."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"navázání na službu pro poslouchání oznámení"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteli navázat se na nejvyšší úroveň služby pro poslouchání oznámení. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"navázání na službu poskytovatele podmínky"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Umožňuje držiteli navázat se na nejvyšší úroveň rozhraní služby poskytovatele podmínky. Běžné aplikace by toto oprávnění neměly nikdy potřebovat."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolat konfigurační aplikaci poskytnutou operátorem"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje vyvolání konfigurační aplikace poskytnuté operátorem. Běžné aplikace by toto oprávnění neměly nikdy požadovat."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"naslouchat informacím o stavu sítě"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Změnit tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikace poslouchající oznámení"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Poskytovatel podmínky"</string>
     <string name="vpn_title" msgid="19615213552042827">"Síť VPN je aktivována"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikace <xliff:g id="APP">%s</xliff:g> aktivovala síť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykem zobrazíte správu sítě."</string>
diff --git a/core/res/res/values-da/strings.xml b/core/res/res/values-da/strings.xml
index d3469f1..206db12 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Tb"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pb"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Uden titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkroniser"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"For mange <xliff:g id="CONTENT_TYPE">%s</xliff:g> sletninger"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Din tablets lager er fuldt. Slet nogle filer for at frigøre plads."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Urets lager er fuldt. Slet nogle filer for at frigøre plads."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefonens lager er fuldt. Slet nogle filer for at frigøre plads."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netværket kan være overvåget"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Af en ukendt tredjepart"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringeren er aktiveret"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Lukker ned..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din tablet slukkes nu."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Dit ur lukkes ned."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon slukkes nu."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vil du slukke?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Genstart i sikker tilstand"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flytilstand"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flytilstand er TIL"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flytilstand er slået FRA"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Indstillinger"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikker tilstand"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillader, at appen kan hente indholdet i det aktive vindue. Ondsindede apps kan hente al indholdet i vinduet og undersøge al dens tekst med undtagelse af adgangskoder."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivere hjælpefunktioner midlertidigt"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillader, at en app midlertidigt kan aktivere hjælpefunktioner på enheden. Skadelige apps kan muligvis aktivere hjælpefunktioner uden brugerens samtykke."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"hente vinduestoken"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Tillader, at en applikation kan hente vinduestokenet. Skadelige apps udfører muligvis uautoriseret interaktion med applikationsvinduet ved at efterligne systemet."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"hente rammestatistik"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Tillader, at en applikation kan indsamle rammestatistik. Skadelige apps kan muligvis observere rammestatistikker for vinduer fra andre apps."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer begivenheder"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillader, at en applikation registrerer et inputfilter, som filtrerer alle brugeres strøm, før disse afsendes. Skadelige apps kan muligvis kontrollere systemets grænseflade uden brugerens deltagelse."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis lukning"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Tillader, at appen kan udsende en underretning om, at der er modtaget en sms-besked. Ondsindede apps kan bruge dette til at simulere indgående sms-beskeder."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-modtaget udsendelse"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Tillader, at appen kan udsende en underretning om, at der er modtaget en WAP PUSH-besked. Ondsindede apps kan bruge dette til at simulere modtagelse af mms-beskeder eller i det skjulte erstatte indholdet på en webside med ondsindede varianter."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"sende underretninger om bedømmelse af netværk"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Tillader, at appen kan udsende en underretning om, at netværket skal bedømmes. Dette er aldrig nødvendigt for almindelige apps."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"begræns antallet af kørende processer"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillader, at appen kan kontrollere det maksimale antal kørende processer. Dette er aldrig nødvendigt til normale apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge baggrundsapps til at lukke"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Tillader, at brugeren forpligter sig til en VPN-tjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt i almindelige apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"knyt til en baggrund"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Tillader, at indehaveren kan binde en baggrunds grænseflade på øverste niveau. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"oprette binding til en tjeneste til stemmeinteraktion"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Tillader, at brugeren opretter en binding til det øverste niveau af grænsefladen i en tjeneste til stemmeinteraktion. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind til en ekstern skærm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Tillader, at brugeren kan foretage en binding til grænsefladens øverste niveau på en ekstern skærm. Bør aldrig være nødvendigt til almindelige apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"forpligt til en widgettjeneste"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Tillader, at brugeren kan forpligte sig til en grænseflade for en widgettjeneste på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"oprette tilknytning til en ruteudbydertjeneste"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Tillader, at indehaveren opretter tilknytninger til registrerede ruteudbydere. Dette bør aldrig være nødvendigt for normale apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikere med en enhedsadministrator"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillader, at brugeren kan sende hensigter til en enhedsadministrator. Dette bør aldrig være nødvendigt for almindelige apps."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"knyt til en tv-indgang"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Giver indehaveren mulighed for at knytte sig til det øverste grænsefladeniveau for en tv-indgang. Dette bør ikke være nødvendigt i normale apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tilføje eller fjerne en enhedsadministrator"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillader, at man tilføjer eller fjerner aktive enhedsadministratorer. Dette burde aldrig være nødvendigt til normale apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"skift skærmretning"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Tillader, at appen kan læse de personlige profiloplysninger, der er gemt på din enhed, f.eks. dit navn og dine kontaktoplysninger. Det betyder, at appen kan identificere dig og sende dine profiloplysninger til andre."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"ændre dit eget kontaktkort"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Tillader, at appen kan ændre eller tilføje oplysninger i din personlige profil, der er gemt på din enhed, f.eks. dit navn eller dine kontaktoplysninger. Dette betyder, at andre apps kan identificere dig og sende profiloplysninger til andre."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kropssensorer (f.eks. pulsmålere)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Tillader, at appen får adgang til data fra sensorer, du bruger til at måle, hvad der sker inde i din krop, f.eks. din puls."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"læs din sociale strøm"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Tillader, at appen kan få adgang til og synkronisere sociale opdateringer fra dig og dine venner. Vær forsigtig, når du deler oplysninger – med denne tilladelse kan appen læse kommunikation mellem dig og dine venner på sociale netværk, uanset fortrolighed. Bemærk! Denne tilladelse håndhæves muligvis ikke på alle sociale netværk."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skriv i din sociale strøm"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Skift WiMAX-tilstand"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillader, at appen kan oprette forbindelse fra tabletten og afbryde forbindelsen til tabletten på WiMAX-netværk."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Tillader, at appen kan oprette forbindelse fra telefonen og afbryde forbindelsen til telefonen på WiMAX-netværk."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"bedømme netværk"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Tillader, at appen rangerer netværk og påvirker, hvilke netværk tabletten bør foretrække."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Tillader, at appen rangerer netværk og påvirker, hvilke netværk telefonen bør foretrække."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"parre med Bluetooth-enheder"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på tabletten samt kan oprette og acceptere forbindelser med parrede enheder."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillader, at appen kan læse konfigurationen af ​​Bluetooth på telefonen samt kan oprette og acceptere forbindelser med parrede enheder."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillader, at appen kan hente, undersøge og rydde underretninger, f.eks. dem, der er sendt af andre apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"forpligte sig til en underretningslyttertjeneste"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Tillader brugeren at forpligte sig til en underretningslyttertjenestes grænseflade på øverste niveau. Bør aldrig være nødvendigt til almindelige apps."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"oprette binding til en tjeneste til formidling af betingelser"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Tillader, at brugeren opretter en binding til det øverste niveau af grænsefladen i en tjeneste til formidling af betingelser. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"aktivere konfigurationsappen, der leveres af mobilselskabet"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Tillader, at brugeren aktiverer konfigurationsappen, der er forsynet af mobilselskabet. Dette bør aldrig være nødvendigt for almindelige apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"observer netværksforhold"</string>
@@ -1159,7 +1203,7 @@
     <string name="smv_process" msgid="5120397012047462446">"Processen <xliff:g id="PROCESS">%1$s</xliff:g> har overtrådt sin egen StrictMode-politik."</string>
     <string name="android_upgrading_title" msgid="1584192285441405746">"Android opgraderes..."</string>
     <string name="android_upgrading_apk" msgid="7904042682111526169">"Optimerer app <xliff:g id="NUMBER_0">%1$d</xliff:g> ud af <xliff:g id="NUMBER_1">%2$d</xliff:g>."</string>
-    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Sådan åbner du dine apps."</string>
+    <string name="android_upgrading_starting_apps" msgid="451464516346926713">"Åbner dine apps."</string>
     <string name="android_upgrading_complete" msgid="1405954754112999229">"Gennemfører start."</string>
     <string name="heavy_weight_notification" msgid="9087063985776626166">"<xliff:g id="APP">%1$s</xliff:g> er i gang"</string>
     <string name="heavy_weight_notification_detail" msgid="1721681741617898865">"Tryk for at skifte til appen"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Baggrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Skift baggrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Underretningslytter"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tjeneste til formidling af betingelser"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktiveret."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveres af <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryk for at administrere netværket."</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 52ea81c..87d4aa0 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Unbenannt&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisierung"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zu viele <xliff:g id="CONTENT_TYPE">%s</xliff:g> gelöscht."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Der Tablet-Speicher ist voll. Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Der Speicher Ihrer Uhr ist voll. Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Der Handyspeicher ist voll! Löschen Sie Dateien, um Speicherplatz freizugeben."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Das Netzwerk wird möglicherweise überwacht."</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Von einem unbekannten Dritten"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Klingelton ein"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Wird heruntergefahren..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ihr Tablet wird heruntergefahren."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ihre Uhr wird heruntergefahren."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon wird heruntergefahren."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Möchten Sie das Gerät herunterfahren?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Im abgesicherten Modus starten"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flugmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flugmodus ist AN."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flugmodus ist AUS."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Einstellungen"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Abgesicherter Modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-System"</string>
@@ -314,9 +339,13 @@
     <string name="permlab_retrieve_window_content" msgid="8022588608994589938">"Bildschirminhalt abrufen"</string>
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ermöglicht der App, den Inhalt des aktiven Fensters abzurufen. Schädliche Apps können so den gesamten Fensterinhalt abrufen und mit Ausnahme von Passwörtern den gesamten Text auswerten."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Bedienungshilfen vorübergehend aktivieren"</string>
-    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ermöglicht einer App, die Bedienungshilfen auf dem Gerät vorübergehend zu aktivieren. Schädliche Apps können Bedienungshilfen ohne die Zustimmung des Nutzers aktivieren."</string>
+    <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ermöglicht der App, die Bedienungshilfen auf dem Gerät vorübergehend zu aktivieren. Schädliche Apps können Bedienungshilfen ohne die Zustimmung des Nutzers aktivieren."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"Fenstertoken abrufen"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Berechtigt eine App zum Abruf des Fenstertokens. Bösartige Apps können sich als System ausgeben und unautorisiert mit dem App-Fenster interagieren."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"Framestatistiken abrufen"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Berechtigt eine App zur Erfassung von Framestatistiken. Bösartige Apps können möglicherweise die Framestatistiken für Fenster von anderen Apps beobachten."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"Ereignisse filtern"</string>
-    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht einer App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
+    <string name="permdesc_filter_events" msgid="8006236315888347680">"Ermöglicht der App, einen Eingabefilter zu registrieren, der den Stream aller Nutzerereignisse vor ihrem Versand filtert. Eine schädliche App kann die System-UI ohne Eingriff des Nutzers kontrollieren."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Partielles Herunterfahren"</string>
     <string name="permdesc_shutdown" msgid="7046500838746291775">"Versetzt den Aktivitätsmanager in einen heruntergefahrenen Zustand. Führt kein vollständiges Herunterfahren aus."</string>
     <string name="permlab_stopAppSwitches" msgid="4138608610717425573">"App-Wechsel verhindern"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine SMS empfangen wurde. Schädliche Apps können so eingehende SMS fälschen."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Von WAP-PUSH empfangenen Broadcast senden"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ermöglicht der App, eine Benachrichtigung zu senden, dass eine WAP PUSH-Nachricht empfangen wurde. Schädliche Apps können so den Empfang von MMS vortäuschen oder unbemerkt den Inhalt einer beliebigen Webseite durch schädliche Inhalte ersetzen."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"Netzwerkbewertungen senden"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ermöglicht der App, Benachrichtigungen zu senden, dass Netzwerke bewertet werden müssen. Für normale Apps ist dies nie erforderlich."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"Anzahl der laufenden Prozesse beschränken"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ermöglicht der App, die maximale Anzahl an aktiven Prozessen zu steuern. Wird nie für normale Apps benötigt."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Apps im Hintergrund schließen"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ermöglicht dem Halter, sich an die Oberfläche eines VPN-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"An einen Hintergrund binden"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ermöglicht dem Halter, sich an die Oberfläche eines Hintergrunds auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"An einen Sprachinteraktionsdienst binden"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Sprachinteraktionsdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"An Remote-Display binden"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ermöglicht dem Halter, sich an die Oberfläche eines Remote-Displays auf oberster Ebene zu binden. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"An einen Widget-Dienst binden"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ermöglicht dem Halter, sich an die Oberfläche eines Widget-Dienstes auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"An Routenanbieterdienst binden"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ermöglicht dem Inhaber die Bindung an registrierte Routenanbieter. Sollte für normale Apps nicht erforderlich sein"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Interaktion mit einem Geräteadministrator"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ermöglicht dem Halter, Intents an einen Geräteadministrator zu senden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"An eine TV-Eingabe binden"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ermöglicht dem Inhaber, sich an die Oberfläche einer TV-Eingabe auf oberster Ebene zu binden. Sollte nie für normale Apps benötigt werden."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"Geräteadministrator hinzufügen oder entfernen"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ermöglicht dem Inhaber, aktive Geräteadministratoren hinzuzufügen oder zu entfernen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"Bildschirmausrichtung ändern"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Ermöglicht der App, auf Ihrem Gerät gespeicherte personenbezogene Profildaten zu lesen, einschließlich Ihres Namens und Ihrer Kontaktdaten. Die App kann Sie somit identifizieren und Ihre Profildaten an andere senden."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"Ihre Kontaktkarten ändern"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ermöglicht der App, auf Ihrem Gerät gespeicherte personenbezogene Profildaten zu ändern, einschließlich Ihres Namens und Ihrer Kontaktdaten, sowie Daten hinzuzufügen. Die App kann Sie so identifizieren und Ihre Profildaten an andere senden."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"Körpersensoren (wie Herzfrequenzmesser)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ermöglicht der App den Zugriff auf Daten von Sensoren, mit denen Ihre Vitalfunktionen, etwa die Herzfrequenz, gemessen werden."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"In sozialem Stream lesen"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ermöglicht der App, auf Updates aus sozialen Netzwerken von Ihnen und Ihren Freunden zuzugreifen und diese zu synchronisieren. Seien Sie vorsichtig, wenn Sie Informationen teilen: Der App wird erlaubt, die Kommunikation zwischen Ihnen und Ihren Freunden in sozialen Netzwerken zu lesen, unabhängig von der Vertraulichkeit der kommunizierten Informationen. Hinweis: Diese Berechtigung kann möglicherweise nicht in allen sozialen Netzwerken erzwungen werden."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"In sozialem Stream schreiben"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-Status ändern"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ermöglicht der App, eine Verbindung zwischen dem Tablet und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ermöglicht der App, eine Verbindung zwischen dem Telefon und WiMAX-Netzwerken herzustellen und solche zu trennen."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"Netzwerke bewerten"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ermöglicht der App, Netzwerke zu bewerten und die Auswahl des jeweiligen Netzwerks für das Tablet zu beeinflussen"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ermöglicht der App, Netzwerke zu bewerten und die Auswahl des jeweiligen Netzwerks für das Telefon zu beeinflussen"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Pairing mit Bluetooth-Geräten durchführen"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ermöglicht der App, die Bluetooth-Konfiguration eines Tablets einzusehen und Verbindungen zu gekoppelten Geräten herzustellen und zu akzeptieren."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ermöglicht der App, die Bluetooth-Konfiguration des Telefons einzusehen und Verbindungen mit gekoppelten Geräten herzustellen und zu akzeptieren."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ermöglicht der App das Abrufen, Überprüfen und Löschen von Benachrichtigungen, einschließlich Benachrichtigungen, die von anderen Apps gepostet wurden"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"An Benachrichtigungs-Listener-Dienst binden"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ermöglicht dem Inhaber, sich an die Oberfläche der obersten Ebene eines Benachrichtigungs-Listener-Dienstes zu binden. Sollte nie für normale Apps benötigt werden."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"An einen Bedingungsanbieterdienst binden"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ermöglicht dem Inhaber, sich an die Oberfläche eines Bedingungsanbieterdienstes auf oberster Ebene zu binden. Für normale Apps sollte dies nie erforderlich sein."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufrufen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ermöglicht dem Inhaber, die vom Mobilfunkanbieter bereitgestellte Konfigurations-App aufzurufen. Sollte für normale Apps nie benötigt werden."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Informationen zu den Netzwerkbedingungen erfassen"</string>
@@ -1316,7 +1360,7 @@
     <string name="permlab_copyProtectedData" msgid="4341036311211406692">"Inhalte kopieren"</string>
     <string name="permdesc_copyProtectedData" msgid="4390697124288317831">"Ermöglicht der App das Aufrufen des Standard-Containerdienstes zum Kopieren von Inhalten. Nicht für normale Apps vorgesehen."</string>
     <string name="permlab_route_media_output" msgid="1642024455750414694">"Medienausgabe umleiten"</string>
-    <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ermöglicht einer App, die Medienausgabe auf andere externe Geräte umzuleiten."</string>
+    <string name="permdesc_route_media_output" msgid="4932818749547244346">"Ermöglicht der App, die Medienausgabe auf andere externe Geräte umzuleiten."</string>
     <string name="permlab_access_keyguard_secure_storage" msgid="7565552237977815047">"Zugriff auf mit Keyguard geschützten Speicher"</string>
     <string name="permdesc_access_keyguard_secure_storage" msgid="5866245484303285762">"Ermöglicht einer App den Zugriff auf mit Keyguard geschützten Speicher"</string>
     <string name="permlab_control_keyguard" msgid="172195184207828387">"Anzeige und Ausblenden des Keyguard steuern"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hintergrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Hintergrund ändern"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Benachrichtigungs-Listener"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Bedingungsanbieter"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wurde von <xliff:g id="APP">%s</xliff:g> aktiviert."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Zum Verwalten des Netzwerks berühren"</string>
diff --git a/core/res/res/values-el/strings.xml b/core/res/res/values-el/strings.xml
index 8b7e618..9105cb2 100644
--- a/core/res/res/values-el/strings.xml
+++ b/core/res/res/values-el/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Χωρίς τίτλο&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Συγχρονισμός"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Πάρα πολλές <xliff:g id="CONTENT_TYPE">%s</xliff:g> διαγραφές."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Ο αποθηκευτικός χώρος του tablet είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Ο αποθηκευτικός χώρος παρακολούθησης είναι πλήρης! Διαγράψτε μερικά αρχεία για να απελευθερώσετε χώρο."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Ο αποθηκευτικός χώρος του τηλεφώνου είναι πλήρης. Διαγράψτε μερικά αρχεία για να δημιουργήσετε ελεύθερο χώρο."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Το δίκτυο ενδέχεται να παρακολουθείται"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Από ένα άγνωστο τρίτο μέρος"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ειδοποίηση ήχου ενεργή"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Απενεργοποίηση..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Το tablet σας θα απενεργοποιηθεί."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Η παρακολούθησή σας θα τερματιστεί."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Το τηλέφωνό σας θα απενεργοποιηθεί."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Θέλετε να γίνει τερματισμός λειτουργίας;"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Επανεκκίνηση στην ασφαλή λειτουργία"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Λειτουργία πτήσης"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Η λειτουργία πτήσης είναι ενεργοποιημένη."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Λειτ. πτήσης είναι ανενεργή"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Ρυθμίσεις"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Ασφαλής λειτουργία"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Σύστημα Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Επιτρέπει στην εφαρμογή την ανάκτηση του περιεχομένου του ενεργού παραθύρου. Τυχόν κακόβουλες εφαρμογές ενδέχεται να ανακτήσουν ολόκληρο το περιεχόμενο του παραθύρου και να εξετάσουν ολόκληρο το κείμενό του εκτός από τους κωδικούς πρόσβασης."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"προσωρινή ενεργοποίηση προσβασιμότητας"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Επιτρέπει σε μια εφαρμογή να ενεργοποιήσει την προσβασιμότητα στη συσκευή. Οι κακόβουλες εφαρμογές ενδέχεται να ενεργοποιήσουν την προσβασιμότητα χωρίς τη συγκατάθεση των χρηστών."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ανάκτηση διακριτικού παραθύρου"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Επιτρέπει σε μια εφαρμογή να ανακτήσει το διακριτικό παραθύρου. Οι κακόβουλες εφαρμογές μπορούν να εκτελούν μη εξουσιοδοτημένη αλληλεπίδραση με το παράθυρο της εφαρμογής, σε απομίμηση του συστήματος."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"ανάκτηση στατιστικών πλαισίου"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Επιτρέπει σε μια εφαρμογή να συλλέγει στατιστικά στοιχεία πλαισίου. Οι κακόβουλες εφαρμογές μπορούν να παρατηρούν τα στατιστικά στοιχεία πλαισίου των παραθύρων από άλλες εφαρμογές."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"φιλτράρισμα συμβάντων"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Επιτρέπει σε μια εφαρμογή να καταγράφει ένα φίλτρο εισαγωγής, το οποίο φιλτράρει τη ροή όλων των συμβάντων χρήστη πριν την αποστολή τους. Μια κακόβουλη εφαρμογή μπορεί να ελέγξει τη διεπαφή του συστήματος χωρίς την παρέμβαση του χρήστη."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"μερικός τερματισμός λειτουργίας"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Επιτρέπει στην εφαρμογή την εκπομπή ειδοποίησης σχετικά με τη λήψη μηνύματος SMS. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για τη δημιουργία πλαστών εισερχόμενων μηνυμάτων SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"αποστολή εκπομπής που έχει ληφθεί με WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Επιτρέπει στην εφαρμογή τη μετάδοση μιας ειδοποίησης ότι έχει ληφθεί κάποιο μήνυμα WAP PUSH. Τυχόν κακόβουλες εφαρμογές ενδέχεται να χρησιμοποιήσουν αυτήν τη δυνατότητα για τη λήψη πλαστών μηνυμάτων MMS ή την εν αγνοία του χρήστη αντικατάσταση του περιεχομένου οποιασδήποτε ιστοσελίδας με κακόβουλες παραλλαγές."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"αποστολή μετάδοσης κατάταξης δικτύων"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Επιτρέπει στην εφαρμογή να μεταδίδει μια ειδοποίηση ότι απαιτείται κατάταξη των δικτύων. Δεν απαιτείται ποτέ για τις συνήθεις εφαρμογές."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"περιορισμός αριθμού εκτελούμενων διαδικασιών"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Επιτρέπει στην εφαρμογή τον έλεγχο του μέγιστου αριθμού διαδικασιών που θα εκτελούνται. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"αναγκαστικός τερματισμός εφαρμογών στο παρασκήνιο"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας Vpn. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"δέσμευση σε ταπετσαρία"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας ταπετσαρίας. Δεν απαιτείται για συνήθεις εφαρμογές."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"σύνδεση σε παράγοντα φωνητικής αλληλεπίδρασης"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας φωνητικής αλληλεπίδρασης. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"μεταφορά σε μια απομακρυσμένη οθόνη"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας απομακρυσμένης οθόνης. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"δέσμευση σε υπηρεσία γραφικών στοιχείων"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας γραφικών στοιχείων. Δεν απαιτείται για κανονικές εφαρμογές."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"σύνδεση σε μια υπηρεσία παρόχου δρομολογητή"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Δίνει στον κάτοχο τη δυνατότητα σύνδεσης με οποιονδήποτε εγγεγραμμένο πάροχο δρομολογητή. Δεν απαιτείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"επικοινωνία με έναν διαχειριστή συσκευής"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Επιτρέπει στον κάτοχο την αποστολή στόχων σε έναν διαχειριστή συσκευής. Δεν είναι απαραίτητο για συνήθεις εφαρμογές."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"σύνδεση σε μία είσοδο τηλεόρασης"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανώτερου επιπέδου μιας εισόδου τηλεόρασης. Δεν απαιτείται ποτέ για τις συνηθισμένες εφαρμογές."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"προσθήκη ή κατάργηση ενός διαχειριστή συσκευής"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Επιτρέπει στον κάτοχο να προσθέτει ή να καταργεί ενεργούς διαχειριστές συσκευών. Δεν θα πρέπει να ζητείται ποτέ για κανονικές εφαρμογές."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"αλλαγή προσανατολισμού οθόνης"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Επιτρέπει στην εφαρμογή την ανάγνωση προσωπικών πληροφοριών προφίλ οι οποίες είναι αποθηκευμένες στη συσκευή σας, όπως το όνομα και τα στοιχεία επικοινωνίας σας. Αυτό σημαίνει ότι η εφαρμογή μπορεί να σας αναγνωρίσει και να στείλει τις πληροφορίες του προφίλ σας σε άλλους."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"τροποποίηση κάρτας επαφής"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Επιτρέπει στην εφαρμογή την αλλαγή ή την προσθήκη προσωπικών πληροφοριών προφίλ οι οποίες είναι αποθηκευμένες στη συσκευή σας, όπως το όνομα και τα στοιχεία επικοινωνίας σας. Αυτό σημαίνει ότι η εφαρμογή μπορεί να σας αναγνωρίσει και να στείλει τις πληροφορίες του προφίλ σας σε άλλα άτομα."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"αισθητήρες λειτουργιών (π.χ. καρδιακό ρυθμό)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Επιτρέπει στην εφαρμογή την πρόσβαση στα δεδομένα από τους αισθητήρες που χρησιμοποιείτε για να παρακολουθείτε τις εσωτερικές λειτουργίες σας, όπως τον καρδιακό ρυθμό."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"διαβάστε τη ροή σας κοινωνικών δικτύων"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Επιτρέπει στην εφαρμογή την πρόσβαση και το συγχρονισμό κοινωνικών ενημερώσεων από εσάς και τους φίλους σας. Θα πρέπει να είστε προσεκτικοί όταν μοιράζεστε πληροφορίες -- αυτό δίνει τη δυνατότητα στην εφαρμογή να διαβάζει τις επικοινωνίες ανάμεσα σε εσάς και τους φίλους σας σε κοινωνικά δίκτυα, ανεξάρτητα από το επίπεδο εμπιστευτικότητας. Σημείωση: αυτή η άδεια ίσως να μην μπορεί να εφαρμοστεί σε όλα τα κοινωνικά δίκτυα."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"γράψτε στη ροή σας κοινωνικών δικτύων"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Αλλαγή κατάστασης WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Επιτρέπει στην εφαρμογή τη σύνδεση στο tablet και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Επιτρέπει στην εφαρμογή τη σύνδεση στο τηλέφωνο και την αποσύνδεση από αυτό, από δίκτυα WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"κατάταξη δικτύων"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Επιτρέπει στην εφαρμογή να κατατάσσει τα δίκτυα και να επιλέγει τα προτιμώμενα δίκτυα του tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Επιτρέπει στην εφαρμογή να κατατάσσει τα δίκτυα και να επιλέγει τα προτιμώμενα δίκτυα του τηλεφώνου."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"σύζευξη με συσκευές Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο tablet, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Επιτρέπει στην εφαρμογή να προβάλλει τη διαμόρφωση του Bluetooth στο τηλέφωνο, καθώς και να πραγματοποιεί και να αποδέχεται συνδέσεις με συζευγμένες συσκευές."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Επιτρέπει στην εφαρμογή να ανακτά, να εξετάζει και να απαλείφει ειδοποιήσεις, συμπεριλαμβανομένων εκείνων που δημοσιεύονται από άλλες εφαρμογές."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"δέσμευση σε υπηρεσία ακρόασης ειδοποίησης"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Επιτρέπει στον κάτοχο τη δέσμευση στη διεπαφή ανωτάτου επιπέδου μιας υπηρεσίας ακρόασης ειδοποιήσεων. Δεν απαιτείται σε κανονικές εφαρμογές."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"σύνδεση σε μια υπηρεσία παρόχου συνθηκών"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Επιτρέπει στον κάτοχο τη σύνδεση στη διεπαφή ανωτάτου επιπέδου ενός παρόχου συνθηκών. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Επιτρέπει στον κάτοχο την κλήση της εφαρμογής διαμόρφωσης που παρέχεται από την εταιρεία κινητής τηλεφωνίας. Δεν απαιτείται για κανονικές εφαρμογές."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"λήψη παρατηρήσεων σχετικά με την κατάσταση δικτύου"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ταπετσαρία"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Αλλαγή ταπετσαρίας"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Υπηρεσία ακρόασης ειδοποίησης"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Πάροχος συνθηκών"</string>
     <string name="vpn_title" msgid="19615213552042827">"Το VPN ενεργοποιήθηκε"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Το VPN ενεργοποιήθηκε από την εφαρμογή <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Αγγίξτε για τη διαχείριση του δικτύου."</string>
@@ -1360,7 +1405,7 @@
     <string name="vpn_lockdown_error" msgid="6009249814034708175">"Σφάλμα πάντα ενεργοποιημένου VPN"</string>
     <string name="vpn_lockdown_config" msgid="6415899150671537970">"Αγγίξτε για διαμόρφωση"</string>
     <string name="upload_file" msgid="2897957172366730416">"Επιλογή αρχείου"</string>
-    <string name="no_file_chosen" msgid="6363648562170759465">"Δεν έχει επιλεγεί αρχείο"</string>
+    <string name="no_file_chosen" msgid="6363648562170759465">"Δεν επιλέχθηκε κανένα αρχείο."</string>
     <string name="reset" msgid="2448168080964209908">"Επαναφορά"</string>
     <string name="submit" msgid="1602335572089911941">"Υποβολή"</string>
     <string name="car_mode_disable_notification_title" msgid="3164768212003864316">"Η λειτουργία αυτοκινήτου είναι ενεργοποιημένη"</string>
diff --git a/core/res/res/values-en-rGB/strings.xml b/core/res/res/values-en-rGB/strings.xml
index 179691b..51a85e3 100644
--- a/core/res/res/values-en-rGB/strings.xml
+++ b/core/res/res/values-en-rGB/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sync"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Too many <xliff:g id="CONTENT_TYPE">%s</xliff:g> deletions."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet storage is full. Delete some files to free space."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Watch storage is full. Delete some files to free up space."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Phone storage is full. Delete some files to free space."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Network may be monitored"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"By an unknown third party"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringer on"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Shutting down…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Your tablet will shut down."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Your watch will shut down."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Your phone will shut down."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Do you want to shut down?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot to safe mode"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"temporary enable accessibility"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Allows an application to temporarily enable accessibility on the device. Malicious apps may enable accessibility without user consent."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"retrieve window token"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Allows an application to retrieve the window token. Malicious apps may perform unauthorised interaction with the application window impersonating the system."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"retrieve frame statistics"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Allows an application to collect frame statistics. Malicious apps may observe the frame statistics of windows from other apps."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Allows the app to broadcast a notification that an SMS message has been received. Malicious apps may use this to forge incoming SMS messages."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-received broadcast"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Allows the app to broadcast a notification that a WAP PUSH message has been received. Malicious apps may use this to forge MMS message receipt or to silently replace the content of any web page with malicious variants."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"send score networks broadcast"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Allows the app to broadcast a notification that networks need to be scored. Never needed for normal apps."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limit number of running processes"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Allows the app to control the maximum number of processes that will run. Never needed for normal apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"force background apps to close"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind to a voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Allows the holder to bind to the top-level interface of a voice interaction service. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind to a route provider service"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Allows the holder to bind to any registered route providers. Should never be needed for normal apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Allows the app to read personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modify your own contact card"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Allows the app to change or add to personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"body sensors (like heart rate monitors)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Allows the app to access data from sensors that you use to measure what’s happening inside your body, such as heart rate."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"read your social stream"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Allows the app to access and sync social updates from you and your friends. Be careful when sharing information - this allows the app to read communications between you and your friends on social networks, regardless of confidentiality. Note: this permission may not be enforced on all social networks."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"write to your social stream"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"change WiMAX state"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Allows the app to connect the phone to and disconnect the phone from WiMAX networks."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score networks"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Allows the app to rank networks and influence which networks the tablet should prefer."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Allows the app to rank networks and influence which networks the phone should prefer."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"pair with Bluetooth devices"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
diff --git a/core/res/res/values-en-rIN/strings.xml b/core/res/res/values-en-rIN/strings.xml
index 179691b..51a85e3 100644
--- a/core/res/res/values-en-rIN/strings.xml
+++ b/core/res/res/values-en-rIN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Untitled&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sync"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Too many <xliff:g id="CONTENT_TYPE">%s</xliff:g> deletions."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet storage is full. Delete some files to free space."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Watch storage is full. Delete some files to free up space."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Phone storage is full. Delete some files to free space."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Network may be monitored"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"By an unknown third party"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringer on"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Shutting down…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Your tablet will shut down."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Your watch will shut down."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Your phone will shut down."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Do you want to shut down?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot to safe mode"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Aeroplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Aeroplane mode is ON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Aeroplane mode is OFF"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Settings"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Allows the app to retrieve the content of the active window. Malicious apps may retrieve the entire window content and examine all its text except passwords."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"temporary enable accessibility"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Allows an application to temporarily enable accessibility on the device. Malicious apps may enable accessibility without user consent."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"retrieve window token"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Allows an application to retrieve the window token. Malicious apps may perform unauthorised interaction with the application window impersonating the system."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"retrieve frame statistics"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Allows an application to collect frame statistics. Malicious apps may observe the frame statistics of windows from other apps."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filter events"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Allows an application to register an input filter which filters the stream of all user events before they are dispatched. Malicious app may control the system UI without user intervention."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"partial shutdown"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Allows the app to broadcast a notification that an SMS message has been received. Malicious apps may use this to forge incoming SMS messages."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"send WAP-PUSH-received broadcast"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Allows the app to broadcast a notification that a WAP PUSH message has been received. Malicious apps may use this to forge MMS message receipt or to silently replace the content of any web page with malicious variants."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"send score networks broadcast"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Allows the app to broadcast a notification that networks need to be scored. Never needed for normal apps."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limit number of running processes"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Allows the app to control the maximum number of processes that will run. Never needed for normal apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"force background apps to close"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Allows the holder to bind to the top-level interface of a Vpn service. Should never be needed for normal apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bind to wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Allows the holder to bind to the top-level interface of wallpaper. Should never be needed for normal applications."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind to a voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Allows the holder to bind to the top-level interface of a voice interaction service. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind to a remote display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Allows the holder to bind to the top-level interface of a remote display. Should never be needed for normal apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind to a widget service"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Allows the holder to bind to the top-level interface of a widget service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind to a route provider service"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Allows the holder to bind to any registered route providers. Should never be needed for normal apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interact with device admin"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Allows the holder to send intents to a device administrator. Should never be needed for normal apps."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bind to a TV input"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Allows the holder to bind to the top-level interface of a TV input. Should never be needed for normal apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"add or remove a device admin"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Allows the holder to add or remove active device administrators. Should never be needed for normal apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"change screen orientation"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Allows the app to read personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modify your own contact card"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Allows the app to change or add to personal profile information stored on your device, such as your name and contact information. This means that the app can identify you and may send your profile information to others."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"body sensors (like heart rate monitors)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Allows the app to access data from sensors that you use to measure what’s happening inside your body, such as heart rate."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"read your social stream"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Allows the app to access and sync social updates from you and your friends. Be careful when sharing information - this allows the app to read communications between you and your friends on social networks, regardless of confidentiality. Note: this permission may not be enforced on all social networks."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"write to your social stream"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"change WiMAX state"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Allows the app to connect the tablet to and disconnect the tablet from WiMAX networks."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Allows the app to connect the phone to and disconnect the phone from WiMAX networks."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score networks"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Allows the app to rank networks and influence which networks the tablet should prefer."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Allows the app to rank networks and influence which networks the phone should prefer."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"pair with Bluetooth devices"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Allows the app to view the configuration of Bluetooth on the tablet and to make and accept connections with paired devices."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Allows the app to view the configuration of the Bluetooth on the phone and to make and accept connections with paired devices."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Allows the app to retrieve, examine, and clear notifications, including those posted by other apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bind to a notification listener service"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind to a condition provider service"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invoke the carrier-provided configuration app"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"listen for observations on network conditions"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Change wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Condition provider"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activated"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN is activated by <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Touch to manage the network."</string>
diff --git a/core/res/res/values-es-rUS/strings.xml b/core/res/res/values-es-rUS/strings.xml
index dc67e27..2a4f7e9 100644
--- a/core/res/res/values-es-rUS/strings.xml
+++ b/core/res/res/values-es-rUS/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Se ha agotado el espacio de almacenamiento de la tablet. Elimina algunos archivos para liberar espacio."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"El almacenamiento del reloj está completo. Elimina algunos archivos para liberar espacio."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Se ha agotado el espacio de almacenamiento del dispositivo. Elimina algunos archivos para liberar espacio."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Es posible que la red esté supervisada"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por un tercero desconocido"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Timbre activado"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Apagando…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tu tablet se apagará."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Se apagará el reloj."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Tu dispositivo se apagará."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"¿Deseas apagarlo?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar en modo seguro"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"El modo avión está Activado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"El modo avión está Desactivado"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Configuración"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones maliciosas pueden recuperar el contenido completo de la ventana y examinar todo el texto, excepto las contraseñas."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Activación temporal de la accesibilidad"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite a una aplicación activar temporalmente la accesibilidad en el dispositivo. Las aplicaciones maliciosas pueden activar la accesibilidad sin el consentimiento del usuario."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"recuperar token de ventana"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permite que una aplicación recupere el token de ventana. Las aplicaciones maliciosas pueden interaccionar sin autorización con la ventana de la aplicación al hacerse pasar por el sistema."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"recuperar estadísticas de marcos"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permite que una aplicación recopile estadísticas de marcos. Las aplicaciones maliciosas pueden observar estas estadísticas de ventanas desde otras aplicaciones."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre la transmisión de todos los eventos del usuario antes de ser enviados. Las aplicaciones maliciosas pueden controlar la IU del sistema sin la intervención del usuario."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que la aplicación transmita una notificación acerca de la recepción de un mensaje SMS. Las aplicaciones maliciosas pueden utilizar este permiso para falsificar mensajes SMS entrantes."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar emisiones WAP-PUSH-recibido"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que la aplicación transmita una notificación acerca de la recepción de un mensaje WAP PUSH. Las aplicaciones maliciosas pueden utilizar este permiso para falsificar la recepción de mensajes MMS o para reemplazar sin aviso el contenido de cualquier página web con variantes maliciosas."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmisión de puntuación de redes"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que la aplicación transmita una notificación que las redes necesitan para recibir una puntuación. Las aplicaciones normales no necesitan nunca este permiso."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar la cantidad de procesos en ejecución"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle la cantidad máxima de procesos que se ejecutarán. Las aplicaciones normales no deben utilizar este permiso."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones de fondo"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite al titular vincularse a la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite al propietario vincularse a la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deben utilizar este permiso."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vincular con un servicio de interacción por voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite vincular con la interfaz de nivel superior de un servicio de interacción por voz. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vincular a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite al propietario vincularse a la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a un servicio de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite al propietario vincularse a la interfaz de nivel superior del servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"vincular con un servicio de proveedor de rutas"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite al propietario vincular con proveedores de rutas registrados. No debe ser necesario para las aplicaciones normales."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con un administrador de dispositivos"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite enviar intentos a un administrador de dispositivos. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a una entrada de TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite al propietario vincularse a la interfaz de nivel superior de una entrada de TV. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"agregar o eliminar un administrador de dispositivos"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite al propietario agregar o eliminar administradores de dispositivos activos. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar la orientación de la pantalla"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que la aplicación consulte la información del perfil personal almacenada en el dispositivo, como el nombre o la información de contacto, lo que significa que la aplicación puede identificar al usuario y enviar la información de su perfil a otros usuarios."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modif. tarjeta contacto propia"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que la aplicación modifique la información del perfil personal almacenada en el dispositivo, como el nombre o la información de contacto, o que agregue contenido a esa información. Esto significa que puede identificarte y enviar la información de tu perfil a otros usuarios."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporales (frec. card)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que la aplicación acceda a datos de sensores que utilizas para medir lo que sucede en tu cuerpo, como la frecuencia cardíaca."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Lectura de tu muro social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que la aplicación acceda a las actualizaciones de tus redes sociales y las de tus amigos, y que las sincronice. Ten cuidado al compartir información, ya que la aplicación puede utilizar este permiso para leer las conversaciones que tengas con tus amigos en las redes sociales sin tener en cuenta si son confidenciales. Nota: Este permiso no se puede utilizar en todas las redes sociales."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Escritura en tu muro social"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar el estado de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte la tablet a una red WiMAX y que la desconecte de ella."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el dispositivo a una red WiMAX y que lo desconecte de ella."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar redes"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que la aplicación clasifique redes e influya en las redes que la tablet debería preferir."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que la aplicación clasifique redes e influya en las redes que el teléfono debería preferir."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación vea la configuración de Bluetooth de la tablet y que cree y acepte conexiones con los dispositivos sincronizados."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación vea la configuración de Bluetooth del dispositivo y que cree y acepte conexiones con los dispositivos sincronizados."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y elimine notificaciones, incluidas aquellas publicadas por otras aplicaciones."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Vincular a un servicio de agente de escucha de notificaciones"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite al propietario vincularse a la interfaz de nivel superior de un servicio de agente de escucha de notificaciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular con un servicio de proveedor de condiciones"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite vincular con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el proveedor"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite al propietario ejecutar la aplicación de configuración proporcionada por el proveedor. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Detectar cambios en el estado de la red"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Papel tapiz"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Agente de escucha de notificaciones"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN está activado por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 8386b02..2e0d68b 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sin título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronización"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminaciones de <xliff:g id="CONTENT_TYPE">%s</xliff:g>"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Se ha agotado el espacio de almacenamiento del tablet. Elimina algunos archivos para liberar espacio."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"El almacenamiento del reloj está lleno. Elimina algunos archivos para liberar espacio."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Se ha agotado el espacio de almacenamiento del teléfono. Elimina algunos archivos para liberar espacio."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Es posible que la red esté supervisada"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por un tercero desconocido"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Timbre activado"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Apagando..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"El tablet se apagará."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"El reloj se apagará."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"El teléfono se apagará."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"¿Seguro que quieres apagar el teléfono?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar en modo seguro"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avión"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avión activado. Desactivar"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avión desactivado. Activar"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Ajustes"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt; 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que la aplicación recupere el contenido de la ventana activa. Las aplicaciones malintencionadas pueden recuperar todo el contenido de la ventana y analizar todo el texto de la misma, excepto las contraseñas."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"habilitar la accesibilidad de forma temporal"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que una aplicación habilite la accesibilidad en el dispositivo de forma temporal. Las aplicaciones maliciosas pueden habilitar la accesibilidad sin el consentimiento del usuario."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"recuperar token de ventana"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permite que una aplicación recupere el token de ventana. Las aplicaciones maliciosas pueden interactuar sin autorización con la ventana de la aplicación suplantando la identidad del sistema."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"recuperar estadísticas de enmarcación"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permite que una aplicación recopile estadísticas de enmarcación. Las aplicaciones maliciosas pueden observar estas estadísticas de ventanas desde otras aplicaciones."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que una aplicación registre un filtro de entrada que filtre el flujo de los eventos del usuario antes de que se envíe. Las aplicaciones malintencionadas pueden controlar la interfaz del sistema sin la intervención del usuario."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"cierre parcial"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que la aplicación emita una notificación cuando se haya recibido un mensaje SMS. Las aplicaciones malintencionadas pueden usar este permiso para falsificar mensajes SMS entrantes."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar emisión recibida mediante mensaje WAP PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que la aplicación envíe una notificación cuando se haya recibido un mensaje WAP PUSH. Las aplicaciones malintencionadas pueden usar este permiso para falsificar la recepción de un mensaje MMS o para reemplazar sin aviso el contenido de cualquier página web con variantes malintencionadas."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar notificaciones sobre la puntuación de las redes"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que la aplicación emita una notificación que la red necesita para recibir una puntuación. Las aplicaciones normales no necesitan nunca este permiso."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar el número de procesos en ejecución"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que la aplicación controle el número máximo de procesos que se ejecutarán. No es necesario nunca para las aplicaciones normales."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forzar el cierre de aplicaciones en segundo plano"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite enlazar con la interfaz de nivel superior de un servicio de VPN. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"enlazar con un fondo de pantalla"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite enlazar con la interfaz de nivel superior de un fondo de pantalla. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"enlazar con un servicio de interacción de voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite enlazar con la interfaz de nivel superior de un servicio de interacción de voz. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"enlazar a una pantalla remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite enlazar con la interfaz de nivel superior de una pantalla remota. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"enlazar con un servicio de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite enlazar con la interfaz de nivel superior de un servicio de widget. Las aplicaciones normales no deberían necesitar este permiso."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"enlazar con un servicio de proveedor de rutas"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite enlazar con proveedores de rutas registrados. No debe ser necesario para las aplicaciones normales."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactuar con el administrador de un dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que se envíen intentos a un administrador de dispositivos. Las aplicaciones normales nunca deberían necesitar este permiso."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"enlazar a una entrada de TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite enlazar con la interfaz de nivel superior de una entrada de TV. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"añadir o eliminar un administrador de dispositivos"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite añadir o eliminar administradores de dispositivos activos. No debe ser necesario para aplicaciones normales."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"cambiar orientación de la pantalla"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que la aplicación consulte la información del perfil personal almacenada en el dispositivo (como el nombre o la información de contacto), lo que significa que la aplicación puede identificar al usuario y enviar la información de su perfil a otros usuarios."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modificar tu propia tarjeta de contacto"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que la aplicación modifique la información del perfil personal almacenada en el dispositivo (como el nombre o la información de contacto) o que añada contenido a esa información, lo que significa que puede identificar al usuario y enviar la información de su perfil a otros usuarios."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sens. corp. (mon. frec. card.)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que la aplicación acceda a datos de sensores que utilizas para medir lo que sucede en tu cuerpo, como la frecuencia cardíaca."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"consulta tu actividad social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que la aplicación acceda a novedades de redes sociales tuyas y de tus amigos y las sincronice. Ten cuidado al compartir información, ya que la aplicación puede utilizar este permiso para leer conversaciones privadas con tus amigos en las redes sociales sin tener en cuenta si son confidenciales. Nota: este permiso no se puede utilizar en todas las redes sociales."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escribir en tu actividad social"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Cambiar estado de WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que la aplicación conecte el tablet a redes WiMAX y lo desconecte de ellas."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que la aplicación conecte el teléfono a redes WiMAX y lo desconecte de ellas."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"puntuar redes"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que la aplicación clasifique redes e influya en las redes que el tablet debe preferir."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que la aplicación clasifique una red e influya en las redes que el teléfono debe preferir."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"vincular con dispositivos Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que la aplicación acceda a la configuración de Bluetooth del tablet y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que la aplicación acceda a la configuración de Bluetooth del teléfono y que establezca y acepte conexiones con los dispositivos sincronizados."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que la aplicación recupere, examine y borre notificaciones, incluidas las que han publicado otras aplicaciones."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"enlazar con un servicio de detector de notificaciones"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite enlazar con la interfaz de nivel superior de un servicio de detector de notificaciones. No debe ser necesario para las aplicaciones normales."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"enlazar con un servicio de proveedor de condiciones"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite enlazar con la interfaz de nivel superior de un servicio de proveedor de condiciones. Las aplicaciones normales no deberían necesitar este permiso."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ejecutar la aplicación de configuración proporcionada por el operador"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite ejecutar la aplicación de configuración proporcionada por el operador. No debe ser necesario para aplicaciones normales."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar cambios en el estado de la red"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fondo de pantalla"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambiar fondo de pantalla"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Detector de notificaciones"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Proveedor de condiciones"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toca para administrar la red."</string>
diff --git a/core/res/res/values-et-rEE/strings.xml b/core/res/res/values-et-rEE/strings.xml
index 4d15e4a..32abeb8 100644
--- a/core/res/res/values-et-rEE/strings.xml
+++ b/core/res/res/values-et-rEE/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Pealkirjata&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sünkroonimine"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Liiga palju üksuse <xliff:g id="CONTENT_TYPE">%s</xliff:g> kustutusi."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tahvelarvuti mäluruum on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Kella talletusruum on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefonimälu on täis. Ruumi vabastamiseks kustutage mõned failid."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Võrku võidakse jälgida"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Tundmatu kolmas osapool:"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Helin on sees"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Väljalülitamine ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Teie tahvelarvuti lülitub välja."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Teie kell lülitub välja."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Teie telefon lülitub välja."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Kas soovite välja lülitada?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Ohutus režiimis taaskäivitamine"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lennurežiim"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lennurežiim on SEES"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lennurežiim on VÄLJAS"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Seaded"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Turvarežiim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-süsteem"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Võimaldab rakendusel kätte saada aktiivse akna sisu. Pahatahtlikud rakendused võivad hankida kogu akna sisu ja uurida kogu selle teksti, välja arvatud paroole."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ajutine hõlbustuse lubamine"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lubab rakendusel ajutiselt lubada seadmes hõlbustuse. Pahatahtlikud rakendused võivad lubada hõlbustuse kasutaja nõusolekuta."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"aknaloa toomine"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Lubab rakendusel tuua aknaloa. Pahatahtlikud rakendused võivad jäljendada süsteemi ja suhelda rakenduse aknaga ilma loata."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"raamistatistika toomine"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Lubab rakendusel koguda raamistatistikat. Pahatahtlikud rakendused võivad jälgida teiste rakenduste akende raamistatistikat."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtreeri sündmused"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Võimaldab rakendusel registreerida sisestusfiltri, mis filtreerib kõigi kasutaja sündmuste voo, enne kui need ära saadetakse. Pahatahtlik rakendus võib süsteemi kasutajaliidest juhtida ilma kasutaja sekkumiseta."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"osaline väljalülitamine"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Võimaldab rakendusel edastada teatise SMS-sõnumi vastuvõtmise kohta. Pahatahtlikud rakendused võivad seda kasutada sissetulevate SMS-sõnumite võltsimiseks."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"saada WAP-PUSH-vastuvõetud saateid"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Võimaldab rakendusel edastada teatise WAP PUSH-sõnumi vastuvõtmise kohta. Pahatahtlikud rakendused võivad seda kasutada MMS-sõnumite vastuvõtmise võltsimiseks või mis tahes veebilehe sisu salaja asendamiseks pahatahtlikuga."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"võrkude levi hinnangu saatmine"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Lubab rakendusel levitada märguannet, et võrke tuleb hinnata. Seda ei ole kunagi vaja tavapäraste rakenduste puhul."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"piira töötavate protsesside arvu"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Võimaldab rakendusel juhtida töötavate protsesside maksimaalset arvu. Tavarakenduste puhul pole seda vaja."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"sundige taustarakendused sulguma"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Võimaldab omanikul siduda VPN-teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"taustapildiga sidumine"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lubab omanikul siduda taustapildi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"seo häälinteraktsiooniga"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Lubab omanikul siduda häälinteraktsiooni teenuse ülataseme liidesega. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"kaugekraaniga sidumine"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lubab omanikul siduda rakenduse kaugekraani ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vidinateenusega sidumine"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lubab omanikul siduda vidina teenuse ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"sidumine marsruudi pakkumisteenusega"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Lubab õiguste omajal luua seosed kõikide registreeritud marsruutide pakkujatega. Pole kunagi vajalik tavaliste rakenduste korral."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"seadme administraatoriga suhtlemine"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Võimaldab omanikul saata kavatsusi seadme administraatorile. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"sidumine TV-sisendiga"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lubab omanikul siduda TV-sisendi ülataseme liidesega. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"seadme administraatori lisamine või eemaldamine"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Võimaldab omanikul lisada või eemaldada aktiivseid seadme administraatoreid. Tavarakenduste puhul ei tohiks see kunagi vajalik olla."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"muuda ekraani paigutust"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Võimaldab rakendusel lugeda seadmesse salvestatud isiklikku profiiliteavet, näiteks teie nime ja kontaktteavet. See tähendab, et rakendus saab teid tuvastada ja saata teie profiiliteavet teistele."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"muutke oma kontaktikaarti"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Võimaldab rakendusel muuta või lisada seadmesse salvestatud isiklikku profiiliteavet, näiteks teie nime ja kontaktteavet. See tähendab, et rakendus saab teid tuvastada ja saata teie profiiliteavet teistele."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kehaandurid (nt pulsilugeja)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Lubab rakendusel saada juurdepääsu selliste andurite andmetele, mida kasutate kehas toimuva (nt pulsi) mõõtmiseks."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Sotsiaalvoo lugemine"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Annab rakendusele juurdepääsu ja võimaldab sünkroonida teie ja teie sõprade sotsiaalseid värskendusi. Olge teabe jagamisel ettevaatlik – see võimaldab rakendusel lugeda teie suhtlusi sõpradega suhtlusvõrgustikes konfidentsiaalsusest hoolimata. Märkus: see luba ei pruugi jõustuda kõigis suhtlusvõrgustikes."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Sotsiaalvoogu kirjutamine"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-i oleku muutmine"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Võimaldab rakendusel luua ja katkestada tahvelarvuti ühenduse WiMAX-i võrkudega."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Võimaldab rakendusel luua ja katkestada telefoni ühenduse WiMAX-i võrkudega."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"võrkude hindamine"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Lubab rakendusel võrke hinnata ja mõjutada seda, milliseid võrke peaks tahvelarvuti eelistama."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Lubab rakendusel võrke hinnata ja mõjutada seda, milliseid võrke peaks telefon eelistama."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"siduge Bluetoothi seadmetega"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Võimaldab rakendusel vaadata tahvelarvuti Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Võimaldab rakendusel vaadata telefoni Bluetooth-konfiguratsiooni ning luua ja heaks kiita ühendusi seotud seadmetega."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Võimaldab rakendusel tuua, kontrollida ja kustutada märguandeid, sh neid, mille on postitanud teised rakendused."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"seo märguannete kuulamisteenusega"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Võimaldab omanikul siduda märguannete kuulamisteenuse ülemise taseme kasutajaliidese. Seda ei tohiks tavarakenduste puhul kunagi vaja olla."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"seo tingimuse pakkuja teenusega"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lubab omanikul siduda tingimuse pakkuja teenuse ülataseme liidesega. Pole kunagi vajalik tavaliste rakenduste puhul."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operaatoripoolse konfiguratsioonirakenduse aktiveerimine"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lubab omanikul aktiveerida operaatoripoolse konfiguratsioonirakenduse. Tavarakenduste puhul ei peaks seda kunagi vaja minema."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"võrgutingimuste teabe kuulamine"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustapilt"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Muutke taustapilti"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Märguannete kuulamisteenus"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Tingimuse pakkuja"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktiveeritud"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-i aktiveeris <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Võrgu haldamiseks puudutage."</string>
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index b621d49..c5abcbd 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ترابایت"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"پتابایت"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&lt;بدون عنوان&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"همگام‌سازی"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"تعداد موارد حذف شده <xliff:g id="CONTENT_TYPE">%s</xliff:g> بسیار زیاد است."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"‏حافظه رایانهٔ لوحی پر است! برخی از فایل‎ها را حذف کنید تا فضا آزاد شود."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"حافظه ساعت پر است. برای آزادسازی فضا، چند فایل را حذف کنید."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"حافظه تلفن پر است. بعضی از فایل‌ها را حذف کنید تا فضا آزاد شود."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ممکن است شبکه نظارت شده باشد"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"توسط یک شخص ثالث ناشناس"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"زنگ روشن"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"در حال خاموش شدن…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"رایانهٔ لوحی شما خاموش می‌شود."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ساعت شما خاموش می‌شود."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"گوشی شما خاموش می‌شود."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"‏آیا می‎خواهید تلفن خاموش شود؟"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"راه‌اندازی مجدد در حالت امن"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"حالت هواپیما"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"حالت هواپیما روشن است"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"حالت هواپیما خاموش است"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"تنظیمات"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"حالت ایمن"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏سیستم Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"‏به برنامه اجازه می‎دهد تا محتوای پنجره فعال را بازیابی کند. برنامه‎های مخرب می‎توانند کل محتوای پنجره را بازیابی کنند و همه متن آنرا به غیر از گذرواژه‎ها امتحان کنند."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"قابلیت دسترسی به طور موقت فعال شود"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"به یک برنامه اجازه می‌دهد به صورت موقت قابلیت دسترسی را در دستگاه فعال کند. برنامه‌های مخرب می‌توانند قابلیت دسترسی را بدون رضایت کاربر فعال کنند."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"بازیابی کد پنجره"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"به یک برنامه کاربردی اجازه می‌دهد کد پنجره را بازیابی کند. برنامه‌های مخرب ممکن است با جعل کردن سیستم، تعامل غیرمجازی با پنجره برنامه انجام دهند."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"بازیابی آمار قاب‌ها"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"به یک برنامه کاربردی اجازه می‌دهد آمار قاب‌ها را جمع‌آوری کند. برنامه‌های مخرب ممکن است از برنامه‌های دیگر آمار قاب‌های مربوط به پنجره‌ها را مشاهده کنند."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"فیلتر کردن رویدادها"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"به یک برنامه کاربردی اجازه می‌دهد یک فیلتر ورودی را که جریان تمام رویدادهای کاربران را قبل از ارسال شدن فیلتر می‌کند، ثبت نماید. برنامه‌ کاربردی مخرب ممکن است رابط کاربری سیستم را بدون مداخله کاربر، کنترل کند."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"خاموش شدن جزئی"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"‏به برنامه اجازه می‎دهد تا اعلان دریافت پیام کوتاه را پخش کند. برنامه‎های مخرب می‎توانند از این برای جعل پیام‌های کوتاه ورودی استفاده کنند."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"‏ارسال پخش دریافت شده توسط WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"‏به برنامه اجازه می‎دهد تا اعلانی را پخش کند که پیام WAP PUSH دریافت کرده است. برنامه‎های مخرب می‎توانند از آن استفاده کنند تا دریافت پیام MMS را جعل کنند یا محتوای هر صفحهٔ وب را با انواع مخرب جایگزین کنند."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ارسال اعلان پخش برای امتیازبندی شبکه‌ها"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"به برنامه اجازه می‌دهد تا اعلانی پخش کند که شبکه‌ها باید امتیازبندی شوند. هرگز برای برنامه‌های عادی مورد نیاز نیست."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"محدود کردن تعداد فرآیندهای در حال اجرا"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"‏به برنامه اجازه می‎دهد تا حداکثر تعداد پردازشهایی را که اجرا خواهد شد کنترل کند. هرگز برای برنامه‎های عادی لازم نیست."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"بستن اجباری برنامه‌های پس‌زمینه"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏به دارنده اجازه می‌دهد که به رابط سطح بالای سرویس Vpn متصل شود. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"پیوند شده به تصویر زمینه"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"‏به دارنده اجازه می‎دهد تا به رابط سطح بالای تصویر زمینه متصل شود. برنامه‎های معمولی هرگز به این ویژگی نیاز ندارند."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"مقید بودن به سرویس تعامل صوتی"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"به دارنده امکان می‌دهد به واسط سطح بالای سرویس تعامل صوتی مقید باشد. برای برنامه‌های عادی هرگز نباید لازم باشد."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"اتصال به نمایشگر راه دور"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"به دارنده ام‍ک‍ان می‌دهد تا به رابط سطح بالای نمایشگر راه دور وصل شود. نباید هرگز برای برنامه‌های عادی لازم باشد."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"اتصال به یک سرویس ابزارک"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"به دارنده اجازه می‌دهد که به رابط سطح بالای سرویس ابزارک متصل شود. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"اتصال به یک سرویس ارائه‌دهنده مسیر"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"به دارنده امکان می‌دهد به هر ارائه‌دهنده مسیر ثبت شده‌ای متصل شود. هرگز برای برنامه‌های عادی مورد نیاز نیست."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"تعامل با یک سرپرست دستگاه"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"‏به دارنده اجازه می‎دهد اهداف خود را به سرپرست دستگاه ارسال کند. برنامه‎های معمولی هیچگاه به این ویژگی نیازی ندارند."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"اتصال به ورودی تلویزیون"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"به برنامه امکان می‌دهد که به رابط سطح بالای ورودی تلویزیون متصل شود. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"اضافه یا حذف سرپرست دستگاه"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"به دارنده اجازه می‌دهد سرپرستان دستگاه فعال را اضافه یا حذف کند.هرگز نباید برای برنامه‌های عادی مورد نیاز باشد."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"تغییر جهت صفحه"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"‏به برنامه اجازه می‎دهد اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را بخواند. یعنی برنامه می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را به دیگران ارسال کند."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"اصلاح کارت تماس شما"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"‏به برنامه اجازه می‎دهد تا اطلاعات نمایه شخصی ذخیره شده در دستگاه شما، مانند نام و اطلاعات تماس شما را تغییر دهد یا اضافه کند. یعنی برنامه‎ می‎تواند شما را شناسایی کند و ممکن است اطلاعات نمایهٔ شما را برای دیگران ارسال کند."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"حسگرهای بدن (مانند پایشگرهای ضربان قلب)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"به برنامه امکان می‌دهد به اطلاعات حسگرهایی که استفاده می‌کنید، دسترسی پیدا کند تا اندازه‌گیری‌های مربوط به آنچه که درون بدنتان رخ می‌دهد، مانند ضربان قلب، را انجام دهد."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"خواندن جریان اجتماعی شما"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"به برنامه اجازه می‌دهد به به‌روزرسانی‌های اجتماعی از طرف شما و دوستان شما دسترسی پیدا کرده و آن‌ها را همگام‌سازی کند. دقت کنید که هنگام اشتراک‌گذاری -- این ویژگی به برنامه اجازه می‌دهد ارتباطات بین شما و دوستان شما را در شبکه‌های اجتماعی، صرفنظر از محرمانه بودن آن‌ها بخواند. توجه: این مجوز ممکن است در همه شبکه‌های اجتماعی اجرا نشود."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"نوشتن در جریان اجتماعی شما"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"‏تغییر وضعیت WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"به برنامه امکان می‌دهد رایانهٔ لوحی را به شبکه‌های وایمکس متصل کرده یا اتصال آن را از این شبکه‌ها قطع کند."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"‏به برنامه امکان می‎دهد تا تلفن را به شبکه‌های وایمکس متصل کرده یا اتصال آنرا از این شبکه‌ها قطع کند."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"امتیازبندی شبکه‌ها"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"به برنامه اجازه می‌دهد که شبکه‌ها را درجه‌بندی کند و روی اینکه رایانه لوحی باید کدام شبکه را در اولویت قرار دهد تأثیر می‌گذارد."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"به برنامه اجازه می‌دهد که شبکه‌ها را درجه‌بندی کند و روی اینکه تلفن باید کدام شبکه را در اولویت قرار دهد تأثیر می‌گذارد."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"جفت کردن با دستگاه‌های بلوتوث"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"‏به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در رایانهٔ لوحی را مشاهده کند و اتصال با دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"‏به برنامه اجازه می‎دهد تا پیکربندی بلوتوث در تلفن را مشاهده کند، و اتصالات دستگاه‌های مرتبط را برقرار کرده و بپذیرد."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"به برنامه اجازه می‌دهد به بازیابی، بررسی و پاک کردن اعلان‌ها از جمله موارد پست شده توسط سایر برنامه‌ها بپردازد."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"اتصال به یک سرویس شنونده اعلان"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"به دارنده اجازه می‌دهد به یک رابط سطح بالای سرویس شنونده اعلان متصل شود. هرگز نباید برای برنامه‌های عادی لازم شود."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"مقید بودن به سرویس ارائه‌دهنده وضعیت"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"به دارنده امکان می‌دهد تا به واسط سطح بالای سرویس ارائه‌دهنده وضعیت مقید باشد. برای برنامه‌های عادی هرگز نباید لازم باشد."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"لغو برنامه پیکربندی ارائه شده توسط شرکت مخابراتی"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"به دارنده اجازه می‌دهد که تنظیمات برنامه شرکت مخابراتی را لغو کند. هرگز برای برنامه‌های معمولی مورد نیاز نیست."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"گوش دادن برای بررسی شرایط شبکه"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"تصویر زمینه"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"تغییر تصویر زمینه"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"شنونده اعلان"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ارائه‌دهنده وضعیت"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN فعال شد"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN توسط <xliff:g id="APP">%s</xliff:g> فعال شده است"</string>
     <string name="vpn_text" msgid="3011306607126450322">"برای مدیریت شبکه لمس کنید."</string>
diff --git a/core/res/res/values-fi/strings.xml b/core/res/res/values-fi/strings.xml
index 6dd5e56..945c7ab 100644
--- a/core/res/res/values-fi/strings.xml
+++ b/core/res/res/values-fi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Tt"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Pt"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Nimetön&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkronointi"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Liikaa <xliff:g id="CONTENT_TYPE">%s</xliff:g>-poistoja."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tablet-laitteen tallennustila on täynnä. Vapauta tilaa poistamalla tiedostoja."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Kellon tallennustila on täynnä. Vapauta tilaa poistamalla tiedostoja."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Puhelimen tallennustila on täynnä. Vapauta tilaa poistamalla tiedostoja."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Verkkoa saatetaan valvoa"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Valvoja on tuntematon kolmas osapuoli."</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Soittoääni: normaali"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Suljetaan..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet-laitteesi sammutetaan."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Kello sammutetaan."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Puhelin suljetaan."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Haluatko sammuttaa?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Käynnistä vikasietotilassa"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lentokonetila"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lentokonetila on KÄYTÖSSÄ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lentokonetila on POIS KÄYTÖSTÄ"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Asetukset"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Suojattu tila"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-järjestelmä"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Antaa sovelluksen noutaa aktiivisen ikkunan sisällön. Haitalliset sovellukset voivat noutaa koko ikkunan sisällön ja tarkastella sen kaikkea tekstiä lukuun ottamatta salasanoja."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ota esteettömyystila käyttöön väliaikaisesti"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Antaa sovelluksen ottaa esteettömyystilan käyttöön laitteessa väliaikaisesti. Haitalliset sovellukset voivat ottaa esteettömyystilan käyttöön ilman käyttäjän lupaa."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ikkunan tunnisteen noutaminen"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Antaa sovelluksen noutaa ikkunan tunnisteen. Haitalliset sovellukset saattavat käyttää sovelluksen ikkunaa luvattomasti esiintymällä järjestelmänä."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"kehystilastojen noutaminen"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Antaa sovelluksen kerätä kehystilastoja. Haitalliset sovellukset saattavat tarkkailla toisten sovellusten ikkunoiden kehystilastoja."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"suodata tapahtumat"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Antaa sovelluksen rekisteröidä syöttösuodattimen, joka suodattaa kaikkien käyttäjätapahtumien streamin ennen tapahtumien näyttämistä. Haitalliset sovellukset voivat hallita järjestelmän käyttöliittymää ilman käyttäjän lupaa."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"sulje puhelin osittain"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Sallii sovelluksen lähettää ilmoituksen tekstiviestin vastaanotosta. Haitalliset sovellukset voivat käyttää tätä saapuvien tekstiviestien väärentämiseen."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"lähetä WAP-PUSH-vastaanotettu lähetys"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Antaa sovelluksen lähettää ilmoituksen WAP PUSH -viestin vastaanotosta. Haitalliset sovellukset voivat käyttää tätä MMS-viestien vastaanoton väärentämiseen tai sivujen sisällön korvaamiseen huomaamattomasti haitallisella sisällöllä."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"lähetä verkkojen pisteet"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Sallii sovelluksen lähettää ilmoituksen verkon pisteytystarpeesta. Ei tarvita tavallisissa sovelluksissa."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"rajoita käynnissä olevien prosessien määrää"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Antaa sovelluksen hallita suoritettavien sovellusten enimmäismäärää. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pakota taustasovelluksia sulkeutumaan"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Antaa sovelluksen sitoutua VPN-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sido taustakuvaan"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Antaa sovelluksen sitoutua taustakuvan ylätason käyttöliittymään. Ei tavallisten sovellusten käyttöön."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"etänäyttöön sitoutuminen"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Antaa sovelluksen sitoutua etänäytön ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sitoudu widget-palveluun"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Antaa sovelluksen sitoutua widget-palvelun ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"reitin tarjoajan palveluun sitominen"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Antaa sovelluksen luoda sidoksen mihin tahansa rekisteröityyn reitin tarjoajaan. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunikoi laitteen järjestelmänvalvojan kanssa"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Antaa sovelluksen lähettää aikomuksia laitteen järjestelmänvalvojalle. Ei tavallisten sovellusten käyttöön."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"sido TV-tuloon"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Antaa sovelluksen sitoutua TV-tulon ylemmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lisää tai poista laitteen järjestelmänvalvoja"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Haltija voi lisätä tai poistaa aktiivisen laitteen järjestelmänvalvojia. Tätä ei pitäisi tarvita tavallisille sovelluksille."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"muuta näytön suuntaa"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Antaa sovelluksen lukea laitteelle tallennettuja henkilökohtaisia tietoja, kuten nimen ja yhteystietoja. Sovellus voi tunnistaa sinut ja lähettää profiilitietojasi muille."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"muokkaa omia yhteystietoja"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Antaa sovelluksen muuttaa laitteelle tallennettuja henkilökohtaisia tietoja, kuten nimeä ja yhteystietoja, tai lisätä niitä. Sovellus voi tunnistaa sinut ja lähettää profiilitietojasi muille."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kehon anturit (kuten sykemittarit)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Antaa sovelluksen käyttää tietoja antureista, joita käytetään kehon toimintojen kuten sykkeen mittaamiseen."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lue sosiaalista streamia"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Antaa sovelluksen käyttää ja synkronoida sinun tai kavereidesi päivityksiä sosiaalisista palveluista. Mieti tarkkaan ennen tietojen jakamista: tämän luvan saaneet sovellukset voivat lukea sinun ja kavereidesi välisiä viestejä sosiaalisissa verkkopalveluissa huolimatta viestien arkaluonteisuudesta. Huom: tätä lupaa ei saa ottaa käyttöön kaikissa sosiaalisissa verkkopalveluissa."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"kirjoita sosiaaliseen streamiin"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Vaihda WiMAX-verkon tilaa"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Antaa sovelluksen muodostaa tablet-laitteella yhteyden WiMAX-verkkoon ja katkaista yhteyden."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Antaa sovelluksen muodostaa puhelimella yhteyden WiMAX-verkkoon ja katkaista yhteyden."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"pisteytä verkot"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Sallii sovelluksen asettaa verkkoja paremmuusjärjestykseen ja vaikuttaa siihen, mikä verkko tablet-laitteen kannattaa valita."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Sallii sovelluksen asettaa verkkoja paremmuusjärjestykseen ja vaikuttaa siihen, mikä verkko puhelimen kannattaa valita."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"muodosta laitepari Bluetooth-laitteiden kanssa"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Antaa sovelluksen tarkastella tablet-laitteen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Antaa sovelluksen tarkastella puhelimen Bluetooth-asetuksia sekä muodostaa ja hyväksyä laitepariyhteyksiä muihin laitteisiin."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Antaa sovelluksen noutaa, tutkia ja tyhjentää ilmoituksia (myös muiden sovelluksien lähettämiä)."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sido ilmoituskuuntelijapalveluun"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Antaa sovelluksen sitoutua ilmoituskuuntelijan ylimmän tason käyttöliittymään. Ei tavallisten sovelluksien käyttöön."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Palveluntarjoajan määrityssovelluksen käynnistäminen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Antaa luvanhaltijan käynnistää palveluntarjoajan määrityssovelluksen. Ei tavallisten sovelluksien käyttöön."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"verkon tilahavaintojen kuunteleminen"</string>
@@ -1190,8 +1238,8 @@
     <string name="ringtone_picker_title" msgid="3515143939175119094">"Soittoäänet"</string>
     <string name="ringtone_unknown" msgid="5477919988701784788">"Tuntematon soittoääni"</string>
   <plurals name="wifi_available">
-    <item quantity="one" msgid="6654123987418168693">"Wifi-verkko käytettävissä"</item>
-    <item quantity="other" msgid="4192424489168397386">"Wifi-verkkoja käytettävissä"</item>
+    <item quantity="one" msgid="6654123987418168693">"Wi-Fi-verkko käytettävissä"</item>
+    <item quantity="other" msgid="4192424489168397386">"Wi-Fi-verkkoja käytettävissä"</item>
   </plurals>
   <plurals name="wifi_available_detailed">
     <item quantity="one" msgid="1634101450343277345">"Avoin wifi-verkko käytettävissä"</item>
@@ -1201,10 +1249,10 @@
     <string name="network_available_sign_in" msgid="8495155593358054676">"Kirjaudu verkkoon"</string>
     <!-- no translation found for network_available_sign_in_detailed (8000081941447976118) -->
     <skip />
-    <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wifi-yhteyden muodostaminen epäonnistui"</string>
+    <string name="wifi_watchdog_network_disabled" msgid="7904214231651546347">"Wi-Fi-yhteyden muodostaminen epäonnistui"</string>
     <string name="wifi_watchdog_network_disabled_detailed" msgid="5548780776418332675">" : huono internetyhteys."</string>
     <string name="wifi_p2p_dialog_title" msgid="97611782659324517">"Suora wifi-yhteys"</string>
-    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käynnistä suora wifi-yhteys. Wifi-asiakas/-hotspot poistetaan käytöstä."</string>
+    <string name="wifi_p2p_turnon_message" msgid="2909250942299627244">"Käynnistä suora wifi-yhteys. Wi-Fi-asiakas/-hotspot poistetaan käytöstä."</string>
     <string name="wifi_p2p_failed_message" msgid="3763669677935623084">"Suoran wifi-yhteyden käynnistäminen epäonnistui."</string>
     <string name="wifi_p2p_enabled_notification_title" msgid="2068321881673734886">"Wi-Fi Direct on käytössä"</string>
     <string name="wifi_p2p_enabled_notification_message" msgid="1638949953993894335">"Tarkastele asetuksia koskettamalla"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Taustakuva"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Vaihda taustakuvaa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ilmoituskuuntelija"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN on aktivoitu"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> on aktivoinut VPN-yhteyden"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Voit hallinnoida verkkoa koskettamalla."</string>
@@ -1457,12 +1507,12 @@
     <string name="data_usage_3g_limit_title" msgid="7093334419518706686">"2G-3G-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_4g_limit_title" msgid="7636489436819470761">"4G-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_mobile_limit_title" msgid="7869402519391631884">"Mobiilitiedonsiirto pois käytöstä"</string>
-    <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Wifi-tiedonsiirto pois käytöstä"</string>
+    <string name="data_usage_wifi_limit_title" msgid="8992154736441284865">"Wi-Fi-tiedonsiirto pois käytöstä"</string>
     <string name="data_usage_limit_body" msgid="3317964706973601386">"Ota käyttöön koskettamalla."</string>
     <string name="data_usage_3g_limit_snoozed_title" msgid="7026739121138005231">"2G-3G-tiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_4g_limit_snoozed_title" msgid="1106562779311209039">"4G-tiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_mobile_limit_snoozed_title" msgid="279240572165412168">"Mobiilitiedonsiirtoraja ylitetty"</string>
-    <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wifi-tiedonsiirtoraja ylitetty"</string>
+    <string name="data_usage_wifi_limit_snoozed_title" msgid="8743856006384825974">"Wi-Fi-tiedonsiirtoraja ylitetty"</string>
     <string name="data_usage_limit_snoozed_body" msgid="7035490278298441767">"<xliff:g id="SIZE">%s</xliff:g> yli asetetun rajan"</string>
     <string name="data_usage_restricted_title" msgid="5965157361036321914">"Rajoitettu taustatietojen käyttö"</string>
     <string name="data_usage_restricted_body" msgid="6741521330997452990">"Poista rajoitus koskettamalla."</string>
diff --git a/core/res/res/values-fr-rCA/strings.xml b/core/res/res/values-fr-rCA/strings.xml
index 7a8c975..c917749 100644
--- a/core/res/res/values-fr-rCA/strings.xml
+++ b/core/res/res/values-fr-rCA/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"To"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans_titre&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchroniser"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"La mémoire de la tablette est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"La mémoire de la montre est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Le réseau peut être surveillé"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Par un tiers inconnu"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Sonnerie activée"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Votre tablette va s\'éteindre."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Votre montre va s\'éteindre."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Voulez-vous éteindre l\'appareil?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Redémarrer en mode sans échec"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Paramètres"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activer temporairement l\'accessibilité"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet à une application d\'activer temporairement l\'accessibilité sur l\'appareil. Des applications malveillantes peuvent activer l\'accessibilité sans le consentement de l\'utilisateur."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"récupérer les jetons de fenêtre"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permet à une application de récupérer les jetons de fenêtre. Des applications malveillantes peuvent effectuer des interactions non autorisées avec la fenêtre de l\'application, se faisant passer pour le système."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"récupérer les statistiques de référence"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permet à une application d\'obtenir des statistiques de référence. Des applications malveillantes peuvent observer les statistiques de référence de fenêtres dans d\'autres applications."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message texte. Des applications malveillantes peuvent utiliser cette fonctionnalité pour créer de faux messages entrants."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"envoyer une diffusion de réception de WAP par poussée"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message WAP par poussée. Des applications malveillantes peuvent utiliser cette fonctionnalité pour créer de faux messages multimédias entrants ou pour remplacer le contenu d\'une page Web par du contenu malveillant."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"diffuser le classement des réseaux"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Autorise l\'application à diffuser une notification signalant que les réseaux doivent être évalués. Cela n\'est jamais nécessaire pour les applications normales."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"restreindre le nombre de processus en cours d\'exécution"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet à l\'application de définir le nombre maximal de processus devant s\'exécuter. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forcer la fermeture des applications en arrière-plan"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service RPV. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"se fixer à un fond d\'écran"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"s\'associer à un service d\'interaction vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'interaction vocale. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"lier à un écran distant"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un écran distant. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"s\'associer à un service de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service de widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"associer à un fournisseur d\'itinéraires enregistré"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permet à l\'application autorisée de s\'associer à des fournisseurs d\'itinéraires enregistrés. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur d\'un périphérique"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"s\'associer à une entrée de téléviseur"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'une entrée de téléviseur. Les applications standards ne devraient pas avoir à utiliser cette fonctionnalité."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ajouter ou supprimer un administrateur de l\'appareil"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet à l\'application d\'ajouter ou de supprimer des administrateurs actifs de l\'appareil. Les applications standards ne devraient jamais utiliser cette autorisation."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"modifier l\'orientation de l\'écran"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permet à l\'application d\'accéder aux données de profil enregistrées sur votre appareil, comme votre nom et vos coordonnées. L\'application peut alors vous identifier et envoyer les données de votre profil à des tiers."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modifier votre fiche de contact"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet à l\'application de modifier les données de profil enregistrées sur votre appareil, telles que votre nom et vos coordonnées, ou d\'en ajouter. Elle peut alors vous identifier et envoyer vos données de profil à des tiers."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"capteurs corporels (tels que les moniteurs de fréquence cardiaque)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet à l\'application d\'accéder aux données des capteurs utilisés pour mesurer des valeurs physiologiques, telles que votre fréquence cardiaque."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lire les flux de réseaux sociaux"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet à l\'application d\'accéder à vos mises à jour sur les réseaux sociaux, ainsi qu\'à celles de vos amis, et de les synchroniser. Soyez prudent lorsque vous partagez de l\'information. Cette autorisation permet à l\'application de lire les communications entre vous et vos amis sur les réseaux sociaux, indépendamment de leur caractère confidentiel. Remarque : Il est possible que cette autorisation ne soit pas appliquée sur tous les réseaux sociaux."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"modifier vos flux de réseaux sociaux"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifier l\'état du WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"classer les réseaux"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Autorise l\'application à classer les réseaux et à influencer la sélection du réseau par la tablette."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Autorise l\'application à classer les réseaux et à influencer la sélection du réseau par le téléphone."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"s\'associer à des appareils Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration du fournisseur de services"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par le fournisseur de services. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
@@ -1266,11 +1310,11 @@
     <string name="dlg_confirm_kill_storage_users_text" msgid="5100428757107469454">"Si vous activez la mémoire de stockage USB, certaines applications en cours d\'utilisation vont être fermées et risquent de rester indisponibles jusqu\'à ce que la mémoire de stockage USB soit désactivée."</string>
     <string name="dlg_error_title" msgid="7323658469626514207">"Échec du fonctionnement de la mémoire de stockage USB."</string>
     <string name="dlg_ok" msgid="7376953167039865701">"OK"</string>
-    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'appareil multimédia"</string>
+    <string name="usb_mtp_notification_title" msgid="3699913097391550394">"Connecté en tant qu\'app. multimédia"</string>
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Connecté en tant qu\'appareil photo"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Connecté en tant que programme d\'installation"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Connecté à un accessoire USB"</string>
-    <string name="usb_notification_message" msgid="2290859399983720271">"Appuyez ici pour accéder aux autres options USB."</string>
+    <string name="usb_notification_message" msgid="2290859399983720271">"Appuyez pour accéder aux autres options USB."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"Formater mémoire?"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"Formater la carte SD?"</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"Tous les fichiers stockés sur la mémoire de stockage USB vont être effacés. Cette action est irréversible."</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index a57823f..9359606 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"To"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Po"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sans nom&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronisation"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Trop de contenus supprimés (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"La mémoire de la tablette est pleine. Supprimez des fichiers pour libérer de l\'espace."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"La mémoire de la montre est saturée. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"La mémoire du téléphone est pleine. Veuillez supprimer des fichiers pour libérer de l\'espace."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Il est possible que le réseau soit surveillé."</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Par un tiers inconnu"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Sonnerie activée"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Arrêt en cours..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Votre tablette va s\'éteindre."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"La montre va s\'éteindre."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Votre téléphone va s\'éteindre."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Voulez-vous éteindre l\'appareil ?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Redémarrer en mode sans échec"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Le mode Avion est activé."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Le mode Avion est désactivé."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Paramètres"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode sécurisé"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Système Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permet à l\'application de récupérer le contenu de la fenêtre active. Des applications malveillantes peuvent exploiter cette fonctionnalité pour récupérer et lire la totalité du contenu de la fenêtre, à l\'exception des mots de passe."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activer temporairement l\'accessibilité"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permet à une application d\'activer temporairement l\'accessibilité sur l\'appareil. Des applications malveillantes peuvent activer l\'accessibilité sans le consentement de l\'utilisateur."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"récupérer les jetons de fenêtre"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permettre à une application de récupérer les jetons de fenêtre. Des applications malveillantes peuvent interagir avec la fenêtre de l\'application sans votre autorisation en se faisant passer pour le système."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"récupérer des statistiques de référence"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permettre à une application de collecter des statistiques de référence. Des applications malveillantes peuvent suivre les statistiques de référence de fenêtres dans d\'autres applications."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrer les événements"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permet à une application d\'enregistrer un filtre d\'entrée pour filtrer le flux de tous les événements des utilisateurs avant qu\'ils ne soient traités. Des applications malveillantes peuvent contrôler l\'interface utilisateur du système sans l\'intervention de l\'utilisateur."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"arrêt partiel"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un SMS. Des applications malveillantes peuvent exploiter cette fonctionnalité pour créer de faux SMS entrants."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Envoi de diffusion de réception de WAP PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permet à l\'application d\'envoyer une notification indiquant la réception d\'un message WAP PUSH. Des applications malveillantes peuvent exploiter cette fonctionnalité pour créer de faux MMS entrants ou pour remplacer le contenu d\'une page Web par du contenu malveillant."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"diffuser des notifications pour l\'évaluation des réseaux"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Autoriser l\'application à diffuser une notification signalant que les réseaux doivent être évalués. Cette autorisation n\'est pas nécessaire pour les applications standards."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"Nombre maximal de processus en cours d\'exécution"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permet à l\'application de contrôler le nombre maximal de processus devant s\'exécuter. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forcer la fermeture des applications en arrière-plan"</string>
@@ -349,7 +380,7 @@
     <string name="permdesc_confirm_full_backup" msgid="1748762171637699562">"Permet à l\'application de lancer l\'interface utilisateur de confirmation de sauvegarde complète. Seules certaines applications peuvent bénéficier de cette permission."</string>
     <string name="permlab_internalSystemWindow" msgid="2148563628140193231">"Affichage de fenêtres non autorisées"</string>
     <string name="permdesc_internalSystemWindow" msgid="7458387759461466397">"Permet à l\'application de créer des fenêtres destinées à être utilisées par l\'interface utilisateur du système interne. Les applications standards ne doivent pas utiliser cette fonctionnalité."</string>
-    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"S\'afficher en surimpression dans les autres applis"</string>
+    <string name="permlab_systemAlertWindow" msgid="3543347980839518613">"Se superposer aux autres applis"</string>
     <string name="permdesc_systemAlertWindow" msgid="8584678381972820118">"Permet à l\'application d\'ignorer d\'autres applications ou certaines parties de l\'interface utilisateur. Cela peut altérer votre utilisation de l\'interface de n\'importe quelle application, ou modifier ce que vous pensez voir dans d\'autres applications."</string>
     <string name="permlab_setAnimationScale" msgid="2805103241153907174">"Réglage de la vitesse des animations"</string>
     <string name="permdesc_setAnimationScale" msgid="7690063428924343571">"Permet à l\'application de modifier à tout moment la vitesse générale des animations pour les ralentir ou les accélérer."</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service VPN. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Se fixer sur un fond d\'écran"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un fond d\'écran. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"s\'associer à un service d\'interaction vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'interaction vocale. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"s\'associer à un écran à distance"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permettre à l\'application autorisée de s\'associer à l\'interface de niveau supérieur d\'un écran à distance. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associer à un service widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permet à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'un service widget. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"s\'associer à un fournisseur d\'itinéraires"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permettre à l\'application autorisée de s\'associer à n\'importe quel fournisseur d\'itinéraires. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir avec l\'administrateur du périphérique"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permet à l\'application autorisée d\'envoyer des intentions à l\'administrateur de l\'appareil. Les applications standards ne doivent jamais avoir recours à cette fonctionnalité."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"s\'associer à une entrée TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permettre à l\'application autorisée de s\'associer à l\'interface de plus haut niveau d\'une entrée TV. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ajouter ou supprimer un administrateur de l\'appareil"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permet à l\'application autorisée d\'ajouter ou de supprimer des administrateurs actifs de l\'appareil. Les applications standards ne devraient pas nécessiter cette autorisation."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"Changement d\'orientation de l\'écran"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permet à l\'application d\'accéder aux informations de profil stockées sur votre appareil, telles que votre nom et vos coordonnées. L\'application peut alors vous identifier et envoyer vos informations de profil à des tiers."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modifier votre fiche de contact"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permet à l\'application de modifier les informations de profil stockées sur votre appareil, telles que votre nom et vos coordonnées, ou d\'en ajouter. Elle peut alors vous identifier et envoyer vos informations de profil à des tiers."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"capteurs corporels (tels que les cardiofréquencemètres)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permet à l\'application d\'accéder aux données des capteurs utilisés pour mesurer des valeurs physiologiques, telles que votre fréquence cardiaque."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lire votre flux de réseau social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permet à l\'application d\'accéder à vos mises à jour sur les réseaux sociaux, ainsi qu\'à celles de vos amis, et de les synchroniser. Soyez prudent lorsque vous partagez des informations. Cette autorisation permet à l\'application de lire les communications entre vous et vos amis sur les réseaux sociaux, indépendamment de leur caractère confidentiel. Remarque : il est possible que cette autorisation ne soit pas appliquée sur tous les réseaux sociaux."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"écrire sur votre flux social"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifier l\'état du WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permet à l\'application de connecter la tablette aux réseaux WiMAX et de l\'en déconnecter."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permet à l\'application de connecter le téléphone aux réseaux WiMAX et de l\'en déconnecter."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"évaluer les réseaux"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Autoriser l\'application à classer les réseaux et à influencer la sélection du réseau sur la tablette"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Autoriser l\'application à classer les réseaux et à influencer la sélection du réseau sur le téléphone"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"associer à des appareils Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur la tablette, et d\'établir et accepter des connexions avec les appareils associés."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permet à l\'application d\'accéder à la configuration du Bluetooth sur le téléphone, et d\'établir et accepter des connexions avec les appareils associés."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permet aux applications de récupérer, d\'examiner et d\'autoriser les notifications, y compris celles envoyées par d\'autres applications."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service d\'écoute des notifications. Ne devrait jamais être nécessaire pour les applications normales."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"s\'associer à un service de fournisseur de conditions"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permet à l\'application de s\'associer à l\'interface de niveau supérieur d\'un service de fournisseur de conditions. Ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"faire appel à l\'application de configuration fournie par l\'opérateur"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permet à l\'application autorisée de faire appel à l\'application de configuration fournie par l\'opérateur. Cette fonctionnalité ne devrait pas être nécessaire pour les applications standards."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"détecter des observations sur les conditions du réseau"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fond d\'écran"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Changer de fond d\'écran"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Outil d\'écoute des notifications"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fournisseur de conditions"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN activé"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN activé par <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Appuyez ici pour gérer le réseau."</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index bdba457..3d5f4df 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;शीर्षक-रहित&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"समन्वयन"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"बहुत से <xliff:g id="CONTENT_TYPE">%s</xliff:g> हटाए जाते हैं."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"टेबलेट संग्रहण भर गया है. स्‍थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"घड़ी संग्रहण भर गया है. स्‍थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"फ़ोन संग्रहण भर गया है. स्‍थान रिक्त करने के लिए कुछ फ़ाइलें हटाएं."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"किसी अज्ञात तृतीय पक्ष के द्वारा"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"रिंगर चालू"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"शट डाउन हो रहा है..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"आपकी टेबलेट शट डाउन हो जाएगी."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"आपकी घड़ी बंद हो जाएगी."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"आपका फ़ोन शट डाउन हो जाएगा."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"क्‍या आप शट डाउन करना चाहते हैं?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"सुरक्षित मोड में रीबूट करें"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"हवाई जहाज मोड"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"हवाई जहाज मोड चालू है"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"हवाई जहाज मोड बंद है"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"सेटिंग"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"सुरक्षित मोड"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android सिस्‍टम"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ऐप्स को सक्रिय विंडो की सामग्री पुनर्प्राप्त करने देता है. दुर्भावनापूर्ण ऐप्स विंडो की संपूर्ण सामग्री प्राप्त कर सकते हैं और पासवर्ड को छोड़कर इसके सभी पाठ जांच सकते हैं."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"आसान तरीका को अस्थायी रूप से सक्षम करें"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ऐप्स  को उपकरण पर आसान तरीका को अस्थायी रूप से सक्षम करने देता है. दुर्भावनापूर्ण ऐप्स  उपयोगकर्ता की सहमति के बिना आसान तरीका को सक्षम कर सकते हैं."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"विंडो टोकन प्राप्त करें"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"एप्लिकेशन को विंडो टोकन प्राप्त करने देती है. दुर्भावनापूर्ण ऐप्स सिस्टम का प्रतिरूपण करने वाली एप्लिकेशन विंडो से अनधिकृत इंटरैक्शन कर सकते हैं."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"फ़्रेम के आंकड़े प्राप्त करें"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"एप्लिकेशन को फ़्रेम के आंकड़े एकत्र करने देती है. दुर्भावनापूर्ण ऐप्स अन्य ऐप्स से विंडो के फ़्रेम के आंकड़ों को देख सकते हैं."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"ईवेंट फ़िल्टर करें"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"ऐप्स को इनपुट फ़िल्‍टर पंजीकृत करने देता है, जो सभी उपयोगकर्ता ईवेंट के स्‍ट्रीम को भेजे जाने से पहले फ़िल्‍टर करता है. दुर्भावनापूर्ण ऐप्स उपयोगकर्ता के हस्‍तक्षेप के बिना सिस्‍टम UI को नियंत्रित कर सकता है."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"आंशिक शटडाउन"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ऐप्स  को वह सूचना प्रसारित करने देता है जो SMS संदेश ने प्राप्त की है. दुर्भावनापूर्ण ऐप्स  इसका उपयोग नकली इनकमिंग संदेश गढ़ने के लिए कर सकते हैं."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-प्राप्त प्रसारण भेजें"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ऐप्स  को वह सूचना प्रसारित करने देता है जो WAP PUSH संदेश को प्राप्त हुआ है. दुर्भावनापूर्ण ऐप्स  इसका उपयोग नकली MMS संदेश प्राप्त करने या किसी वेबपृष्ठ की सामग्री को दुर्भावनापूर्ण दूसरे रूप से चुपचाप प्रतिस्थापित करने के लिए कर सकते हैं."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"स्कोर नेटवर्क प्रसारण भेजें"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ऐप्स को यह सूचना प्रसारित करने देती है कि नेटवर्क को स्कोर किए जाने की आवश्यकता है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"चल रही प्रक्रियाओं की संख्‍या सीमित करें"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ऐप्स  को चलाई जाने वाली अधिकतम प्रक्रियाओं को नियंत्रित करने देता है. सामान्य ऐप्स  के लिए कभी आवश्यक नहीं होती."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"पृष्ठभूमि ऐप्स को बलपूर्वक बंद करें"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"धारक को किसी Vpn सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"वॉलपेपर से आबद्ध करें"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"धारक को किसी वॉलपेपर के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"किसी ध्वनि सहभागिताकर्ता से आबद्ध हों"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"धारक को किसी ध्वनि सहभागिता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"रिमोट डिस्प्ले से आबद्ध करें"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"धारक को किसी रिमोट डिस्प्ले के शीर्ष-स्‍तरीय इंटरफ़ेस से आबद्ध होने देती है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"किसी विजेट सेवा से आबद्ध करें"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"धारक को किसी विजेट सेवा के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"किसी रूट प्रदाता सेवा से आबद्ध हों"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"धारक को किसी भी पंजीकृत रूट प्रदाता से आबद्ध रहने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"किसी उपकरण व्‍यवस्‍थापक के साथ सहभागिता करें"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"धारक को किसी उपकरण व्‍यवस्‍थापक को उद्देश्य भेजने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"टीवी इनपुट से आबद्ध करें"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"धारक को किसी टीवी इनपुट के शीर्ष-स्‍तर इंटरफ़ेस से आबद्ध होने देती है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"उपकरण उपकरण सुचारू ढ़ंग से चलाने वाले को जोड़ें या निकालें"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"धारक को सक्रिय डिवाइस व्यवस्थापकों को जोड़ने या निकालने देता है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"स्‍क्रीन अभिविन्‍यास बदलें"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"ऐप्स  को आपके उपकरण में संग्रहीत व्यक्तिगत प्रोफ़ाइल जानकारी, जैसे आपका नाम और संपर्क जानकारी, पढ़ने देता है. इसका अर्थ है कि ऐप्स  आपको पहचान सकता है और आपकी प्रोफ़ाइल जानकारी अन्य लोगों को भेज सकता है."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"स्‍वयं का संपर्क कार्ड बदलें"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ऐप्स  को आपके उपकरण में संग्रहीत निजी प्रोफ़ाइल जानकारी, जैसे आपका नाम और संपर्क जानकारी को बदलने या उसमें कुछ जोड़ने देता है. इसका अर्थ है कि ऐप्स  आपको पहचान सकता है और आपकी प्रोफ़ाइल जानकारी अन्य लोगों को भेज सकता है."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"बॉडी सेंसर (जैसे हृदय गति मॉनीटर)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"एप्लिकेशन को ऐसे सेंसर का डेटा एक्सेस करने देती है जिनका उपयोग आप यह मापने के लिए करते हैं कि आपके शरीर के भीतर क्या चल रहा है, जैसे हृदय गति."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"अपनी सामाजिक स्‍ट्रीम पढ़ें"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"एप को आपके और आपके मित्रों की नई सामाजिक जानकारी तक पहुंचने और उन्हें समन्‍वयित करने देता है. जानकारी साझा करते समय सावधान रहें - इससे गोपनीयता पर ध्यान दिए बिना, एप सामाजिक नेटवर्क पर आपके और आपके मित्रों के बीच संचारों को पढ़ सकता है. ध्‍यान दें: यह अनुमति सभी सामाजिक नेटवर्क पर लागू नहीं की जा सकती."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"सामाजिक स्‍ट्रीम में लिखें"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX स्‍थिति बदलें"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ऐप्स को WiMAX नेटवर्क से टेबलेट को कनेक्‍ट और डिस्‍कनेक्‍ट करने देता है."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ऐप्स को WiMAX नेटवर्क से फ़ोन को कनेक्‍ट और डिस्‍कनेक्‍ट करने देता है."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"स्कोर नेटवर्क"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ऐप्स को नेटवर्क को रैंक करने देती है और इस बात पर ज़ोर देती है कि टेबलेट को किस नेटवर्क को प्राथमिकता देनी चाहिए."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ऐप्स को नेटवर्क को रैंक करने देती है और इस बात पर ज़ोर देती है कि फ़ोन को किस नेटवर्क को प्राथमिकता देनी चाहिए."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth उपकरणों के साथ युग्मित करें"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ऐप्स को टेबलेट पर Bluetooth का कॉन्‍फ़िगरेशन देखने, और युग्‍मित उपकरणों के साथ कनेक्‍शन बनाने और स्‍वीकार करने देता है."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ऐप्स को फ़ोन पर Bluetooth का कॉन्‍फ़िगरेशन देखने, और युग्‍मित उपकरणों के साथ कनेक्‍शन बनाने और स्‍वीकार करने देता है."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को सूचनाओं को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"सूचना श्रवणकर्ता सेवा से जुड़ें"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को सूचना श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन ऐप्स  प्रारंभ करें"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"धारक को वाहक के द्वारा उपलब्ध कराया गया कॉन्फ़िगरेशन ऐप्स  प्रारंभ करने देता है. सामान्‍य ऐप्स के लिए कभी भी आवश्‍यक नहीं होना चाहिए."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"नेटवर्क स्थितियों के अवलोकनों को सुनें"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"सूचना श्रवणकर्ता"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN सक्रिय"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN को <xliff:g id="APP">%s</xliff:g> द्वारा सक्रिय किया गया है"</string>
     <string name="vpn_text" msgid="3011306607126450322">"नेटवर्क प्रबंधित करने के लिए स्‍पर्श करें."</string>
diff --git a/core/res/res/values-hr/strings.xml b/core/res/res/values-hr/strings.xml
index fcd51ab..a195512 100644
--- a/core/res/res/values-hr/strings.xml
+++ b/core/res/res/values-hr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkronizacija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Previše brisanja stavki <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Prostor za pohranu tabletnog računala pun je. Izbrišite nekoliko datoteka kako biste oslobodili prostor."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Memorija sata je puna. Izbrišite neke datoteke da biste oslobodili prostor."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Prostor za pohranu na telefonu je pun. Izbrišite nekoliko datoteka kako biste oslobodili prostor."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mreža se možda nadzire"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Od strane nepoznate treće strane"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Zvono uključeno"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Isključivanje..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Vaš tabletni uređaj će se isključiti."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Sat će se isključiti."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Vaš će se telefon isključiti."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Želite li isključiti uređaj?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Ponovno pokretanje u sigurnom načinu rada"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uključen je način rada u zrakoplovu"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Isključen je način rada u zrakoplovu"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Postavke"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Siguran način rada"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sustav Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Omogućuje aplikaciji dohvaćanje sadržaja aktivnog prozora. Zlonamjerne aplikacije mogu dohvatiti sav sadržaj prozora i pregledati sav njegov tekst osim zaporki."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"privremeno omogući dostupnost"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikacija može privremeno omogućiti dostupnost na uređaju. Zlonamjerne aplikacije mogu omogućiti dostupnost bez korisnikova odobrenja."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"učitavanje prozora tokena"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Omogućuje aplikaciji učitavanje tokena prozora. Zlonamjerne aplikacije mogu stupati u neovlaštenu interakciju s prozorom aplikacije lažno se predstavljajući kao sustav."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"učitavanje statističkih pokazatelja okvira"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Omogućuje aplikaciji prikupljanje statističkih podataka okvira. Zlonamjerne aplikacije mogu pratiti statističke podatke okvira prozora iz drugih aplikacija."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje događaja"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Aplikaciji omogućuje registraciju ulaznog filtra koji filtrira strujanje svih korisničkih događaja prije otpreme. Zlonamjerne aplikacije mogu kontrolirati korisničko sučelje sustava bez znanja korisnika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"djelomično isključivanje"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Omogućuje aplikaciji emitiranje obavijesti da je primljena SMS poruka. Zlonamjerne aplikacije mogu to upotrijebiti za krivotvorenje dolaznih SMS poruka."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"slanje WAP-PUSH-primljenih prijenosa"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Omogućuje aplikaciji emitiranje obavijesti da je primljena WAP PUSH poruka. Zlonamjerne aplikacije mogu to upotrijebiti da bi krivotvorile prijem MMS poruka ili da bi potajno zamijenile sadržaj bilo koje web-stranice zlonamjernim varijantama."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"slanje obavijesti za ocjenjivanje mreža"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Aplikaciji omogućuje emitiranje obavijesti da se mreža treba ocijeniti. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ograničavanje broja pokrenutih postupaka"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Omogućuje aplikaciji upravljanje maksimalnim brojem postupaka koji će biti pokrenuti. Nikada nije potrebno za uobičajene aplikacije."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"prisilno zatvaranje pozadinskih aplikacija"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Nositelju omogućuje vezanje uz sučelje najviše razine VPN usluge. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezano s pozadinskom slikom"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Nositelju omogućuje povezivanje sa sučeljem pozadinske slike najviše razine. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"povezivanje s uslugom glasovne interakcije"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine usluge glasovne interakcije. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"vezanje uz udaljeni zaslon"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Nositelju omogućuje vezanje uza sučelje najviše razine udaljenog zaslona. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vezanje na uslugu widgeta"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge widgeta. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"povezivanje s davateljem usluge usmjeravanja poziva"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Nositelju omogućuje povezivanje s registriranim davateljem usluga usmjeravanja poziva. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s administratorom uređaja"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Nositelju omogućuje slanje namjera administratoru uređaja. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"povezivanje s TV ulazom"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Nositelju omogućuje vezanje uz sučelje najviše razine TV ulaza. Ne bi smjelo biti potrebno za normalne aplikacije."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodavanje ili uklanjanje administratora uređaja"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Omogućuje nositelju dodavanje ili uklanjanje administratora aktivnih uređaja. Nikada ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"promjena orijentacije zaslona"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Aplikaciji omogućuje čitanje osobnih podataka profila pohranjenih na uređaju, kao što su vaše ime ili kontaktni podaci. To znači da vas aplikacija može identificirati i slati informacije s vašeg profila drugima."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"izmjena vaše kontaktne kartice"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Aplikaciji omogućuje promjenu ili dodavanje osobnih podataka profila pohranjenih na uređaju, kao što su vaše ime i kontaktni podaci. To znači da vas aplikacija može identificirati i slati informacije s vašeg profila drugima."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"senzori tjelesnih funkcija (npr. monitori otkucaja srca)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Aplikaciji omogućuje pristup podacima iz senzora koje upotrebljavate za mjerenje onoga što se odvija u vašem tijelu, poput otkucaja srca."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čitanje društvenog streama"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Aplikaciji omogućuje pristup vašim ažuriranjima na društvenim mrežama i ažuriranjima vaših prijatelja, kao i sinkronizaciju tih ažuriranja. Budite oprezni kad dijelite informacije – to aplikaciji omogućuje čitanje poruka između vas i vaših prijatelja na društvenim mrežama, neovisno o povjerljivosti. Napomena: ta se dozvola možda ne primjenjuje na svim društvenim mrežama."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"pisanje društvenog streama"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Promjena stanja WiMAX mreže"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogućuje povezivanje tabletnog računala s WiMAX mrežama i prekidanje veze tabletnog računala s njima."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Aplikaciji omogućuje povezivanje telefona s WiMAX mrežama i prekidanje veze telefona s njima."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocjenjivanje mreža"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Aplikaciji omogućuje rangiranje mreža i utjecanje na odabir preferiranih mreža na tabletu."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Aplikaciji omogućuje rangiranje mreža i utjecanje na odabir preferiranih mreža na telefonu."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"uparivanje s Bluetooth uređajima"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na tabletnom računalu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogućuje pregled konfiguracije Bluetootha na telefonu te uspostavljanje i prihvaćanje veza s uparenim uređajima."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Omogućuje aplikaciji dohvaćanje, pregledavanje i brisanje obavijesti, uključujući obavijesti drugih aplikacija."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vezanje uz uslugu slušatelja obavijesti"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nositelju omogućuje vezanje uz sučelje najviše razine usluge slušatelja obavijesti. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezivanje s uslugom davatelja uvjeta"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Vlasniku omogućuje povezivanje sa sučeljem najviše razine usluge davatelja uvjeta. Nije potrebno za normalne aplikacije."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"pozovi operaterovu aplikaciju za konfiguraciju"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Dopušta nositelju pozivanje operaterove aplikacije za konfiguraciju. Ne bi smjelo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"praćenje motrenja mrežnih uvjeta"</string>
@@ -688,7 +732,7 @@
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"promjena kalibracije uređaja za unos"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Omogućuje aplikaciji izmjenu parametara kalibracije dodirnog zaslona. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"pristup DRM certifikatima"</string>
-    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Nikad ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Aplikaciji omogućuje pružanje i korištenje DRM certifikata. Ne bi trebalo biti potrebno za uobičajene aplikacije."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Postavi pravila zaporke"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Upravljajte duljinom zaporki za otključavanje zaslona i dopuštenim znakovima u tim zaporkama."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Nadgledaj pokušaje otključavanja zaslona"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Pozadinska slika"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Promjena pozadinske slike"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Slušatelj obavijesti"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Davatalj uvjeta"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikacija <xliff:g id="APP">%s</xliff:g> aktivirala je VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dodirnite za upravljanje mrežom."</string>
diff --git a/core/res/res/values-hu/strings.xml b/core/res/res/values-hu/strings.xml
index 4932e88..6e82bb8 100644
--- a/core/res/res/values-hu/strings.xml
+++ b/core/res/res/values-hu/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Névtelen&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Szinkronizálás"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Túl sok <xliff:g id="CONTENT_TYPE">%s</xliff:g> törlés."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"A táblagép tárhelye tele van. Szabadítson fel helyet néhány fájl törlésével."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Az óra tárhelye megtelt. Szabadítson fel helyet néhány fájl törlésével."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"A telefon tárhelye megtelt. Hely felszabadításához töröljön néhány fájlt."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Lehet, hogy a hálózat felügyelt"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ismeretlen harmadik fél által"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Csengő bekapcsolva"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Leállítás..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"A táblagép ki fog kapcsolni."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Az óra ki fog kapcsolni."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"A telefon le fog állni."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Kikapcsolja?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Újraindítás csökkentett módban"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Repülőgép üzemmód"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Repülőgép üzemmód bekapcsolva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Repülőgép üzemmód kikapcsolva"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Beállítások"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Biztonsági üzemmód"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android rendszer"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lehetővé teszi az alkalmazás számára az aktív ablak tartalmának letöltését. A rosszindulatú alkalmazások letölthetik az ablak teljes tartalmát, és a jelszavak kivételével az összes szöveget megvizsgálhatják."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Ideiglenes hozzáférés engedélyezése"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Engedélyezi egy alkalmazás számára, hogy ideiglenesen hozzáférést biztosítson az eszközhöz. A kártékony alkalmazások a felhasználó beleegyezése nélkül engedélyezhetik a hozzáférést."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ablaktoken lekérése"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Lehetővé teszi, hogy az alkalmazás lekérje az ablaktokent. A kártékony alkalmazások jogosulatlan kapcsolatot létesíthetnek az alkalmazásablakkal a rendszer nevében."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"keretstatisztikák lekérése"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Lehetővé teszi, hogy az alkalmazás keretstatisztikákat gyűjtsön. A kártékony alkalmazások figyelhetik a más alkalmazások ablakainak keretstatisztikáit."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"események szűrése"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Lehetővé teszi az alkalmazás számára, hogy egy bemeneti szűrőt használjon, amely megszűri a falon megjelenő felhasználói eseményeket, még mielőtt megjelennének. A rosszindulatú alkalmazások felhasználói beavatkozás nélkül irányíthatják a rendszer kezelőfelületét."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"részleges rendszerleállítás"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Lehetővé teszi az alkalmazás számára értesítés küldését SMS érkezéséről. A rosszindulatú alkalmazások beérkező SMS-ek hamisítására használhatják fel ezt."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH alapú üzenetek küldése"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Lehetővé teszi az alkalmazás számára értesítés küldését WAP PUSH üzenet érkezése esetén. A rosszindulatú alkalmazások arra használhatják ezt, hogy MMS-kézbesítési jelentést hamisítsanak, vagy hogy a háttérben rosszindulatú variánssal cseréljék le bármelyik weboldal tartalmát."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"hálózatpontozási értesítés küldése"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Lehetővé teszi, hogy az alkalmazás szétküldjön egy értesítést, amely szerint a hálózatokat pontozni kell. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"futó folyamatok számának korlátozása"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lehetővé teszi az alkalmazás számára a futtatható folyamatok maximális számának vezérlését. Soha nem lehet rá szüksége a normál alkalmazásoknak."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"háttéralkalmazások leállításának kényszerítése"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lehetővé teszi a használó számára, hogy csatlakozzon egy VPN-szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"összekapcsolás háttérképpel"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lehetővé teszi, hogy a tulajdonos kötelezővé tegye egy háttérkép legfelső szintű felületét. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"csatlakozás egy hangvezérlőhöz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Lehetővé teszi a használó számára, hogy csatlakozzon egy hangvezérlő szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"csatlakozás egy távoli kijelzőhöz"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lehetővé teszi a használó számára, hogy csatlakozzon egy távoli kijelző legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"csatlakozás modulszolgáltatáshoz"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lehetővé teszi a használó számára, hogy csatlakozzon egy modulszolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"csatlakozás egy útvonal-szolgáltatóhoz"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Az eszköz kezelője csatlakozhat bármely regisztrált útvonal-szolgáltatóhoz. A normál alkalmazások esetében erre nincs szükség."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"az eszközkezelő használata"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lehetővé teszi a tulajdonos számára, hogy célokat küldjön egy eszközkezelőnek. A normál alkalmazásoknak erre soha nincs szüksége."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"csatlakozás tévébemenethez"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lehetővé teszi, hogy a tulajdonos kapcsolódjon egy tévébemenet legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"eszközrendszergazda hozzáadása vagy eltávolítása"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Lehetővé teszi a tulajdonos számára, hogy aktív eszközrendszergazdákat adjon meg vagy távolítson el. A normál alkalmazásoknál erre soha nincs szükség."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"képernyő irányának módosítása"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Lehetővé teszi az alkalmazás számára, hogy hozzáférést biztosítson az eszközön tárolt személyes profiladatokhoz, például a névhez és az elérhetőségekhez. Ez azt jelenti, hogy az alkalmazás azonosíthatja Önt, és elküldheti másoknak profiladatait."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"saját névjegykártya módosítása"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lehetővé teszi az alkalmazás számára az eszközön tárolt személyes profiladatok, például a név és az elérhetőségek módosítását vagy hozzáadását. Ez azt jelenti, hogy az alkalmazás azonosíthatja Önt, és elküldheti másoknak profiladatait."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"testérzékelők (pl. pulzusmérő)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Lehetővé teszi, hogy az alkalmazás hozzáférjen az olyan érzékelők által észlelt adatokhoz, amelyek az Ön életfunkcióit – például a pulzusszámát – figyelik."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"közösségi adatfolyam olvasása"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lehetővé teszi az alkalmazás számára, hogy hozzáférjen az Ön és ismerősei közösségi oldalakon szereplő frissítéseihez. Legyen elővigyázatos, amikor információt tesz közzé -- így az alkalmazás hozzáférhet az ismerőseivel a közösségi hálózatokon folytatott magánbeszélgetésekhez, a tartalom titkos jellegétől függetlenül. Megjegyzés: előfordulhat, hogy ez nincs minden közösségi hálózaton engedélyezve."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"írás a közösség adatfolyamra"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-állapot módosítása"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lehetővé teszi az alkalmazás számára, hogy a táblagépet csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lehetővé teszi az alkalmazás számára, hogy a telefont csatlakoztassa WiMAX-hálózathoz vagy leválassza azt róla."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"hálózatok pontozása"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Lehetővé teszi, hogy az alkalmazás rangsorolja a hálózatokat, illetve befolyásolja, hogy a táblagép mely hálózatokat részesítse előnyben."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Lehetővé teszi, hogy az alkalmazás rangsorolja a hálózatokat, illetve befolyásolja, hogy a telefon mely hálózatokat részesítse előnyben."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth-eszközök párosítása"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lehetővé teszi az alkalmazás számára a táblagépen lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Lehetővé teszi az alkalmazás számára a telefonon lévő Bluetooth beállításainak megtekintését, valamint kapcsolatok kezdeményezését és fogadását a párosított eszközökkel."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lehetővé teszi, hogy az alkalmazás értesítéseket kérdezzen le, vizsgáljon és tisztítson meg, beleértve az egyéb alkalmazások által közzétett értesítéseket is."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"csatlakozzon értesítésfigyelő szolgáltatáshoz"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lehetővé teszi a használó számára, hogy csatlakozzon egy értesítésfigyelő szolgáltatás legfelső szintű felületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"csatlakozás egy feltételbiztosító szolgáltatáshoz"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Lehetővé teszi a használó számára, hogy csatlakozzon egy feltételbiztosító szolgáltatás legfelső szintű kezelőfelületéhez. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"a szolgáltatói konfigurációs alkalmazás hívása"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lehetővé teszi a használó számára a szolgáltató által biztosított konfigurációs alkalmazás hívását. A normál alkalmazásoknak erre soha nincs szükségük."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"hálózati körülményekkel kapcsolatos észrevételek figyelemmel kísérése"</string>
@@ -688,7 +732,7 @@
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"beviteli eszköz kalibrációjának módosítása"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lehetővé teszi, hogy az alkalmazás módosítsa az érintőképernyő kalibrációs paramétereit. A normál alkalmazásoknál erre elvileg soha nincs szükség."</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"DRM-tanúsítványokhoz való hozzáférés"</string>
-    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szüksége."</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Engedélyezi egy alkalmazás számára a DRM-tanúsítványokhoz való hozzáférést és azok használatát. Átlagos alkalmazásoknak erre nem lehet szükségük."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Jelszavakkal kapcsolatos szabályok beállítása"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"A képernyőzár-feloldási jelszavakban engedélyezett karakterek és hosszúság vezérlése."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Képernyőzár-feloldási kísérletek figyelése"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Háttérkép"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Háttérkép megváltoztatása"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Értesítésfigyelő"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Feltételbiztosító"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiválva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A(z) <xliff:g id="APP">%s</xliff:g> aktiválta a VPN-t"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Érintse meg a hálózat kezeléséhez."</string>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index 805f77b..12e5fdb 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Տբ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Պբ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Անանուն&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Համաժամել"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Չափից շատ <xliff:g id="CONTENT_TYPE">%s</xliff:g> հեռացումներ:"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Գրասալիկի պահոցը լիքն է: Ջնջեք մի քանի ֆայլ` տարածք ազատելու համար:"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Ժամացույցի ֆայլերի պահեստը լիքն է: Ջնջեք որոշ ֆայլեր՝ տարածք ազատելու համար:"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Հեռախոսի պահոցը լիքն է: Ջնջեք մի քանի ֆայլեր` տարածություն ազատելու համար:"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Ցանցը կարող է վերահսկվել"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Անհայտ երրորդ կողմի կողմից"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Զանգակը միացված է"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Անջատվում է…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ձեր գրասալիկը կանջատվի:"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ձեր ժամացույցը կանջատվի:"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ձեր հեռախոսը կանջատվի:"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Ցանկանու՞մ եք անջատել:"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Վերաբեռնել անվտանգ ռեժիմի"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Ինքնաթիռային ռեժիմ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Ինքնաթիռային ռեժիմը միացված է"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Ինքնաթիռային ռեժիմը անջատված է"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Կարգավորումներ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Անվտանգ ռեժիմ"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android համակարգ"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Թույլ է տալիս հավելվածին առբերել ակտիվ պատուհանի պարունակությունը: Վնասարար հավելվածները կարող են առբերել պատուհանի լրիվ պարունակությունը և հետազոտել դրա ամբողջ տեքստը` բացառությամբ գաղտնաբառերի:"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ժամանակավոր միացնել մուտքի հնարավորությունը"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Թույլ է տալիս հավելվածին ժամանակավորապես մուտքի հնարավորություն տալ սարքին: Վնասարար հավելվածները կարող են մուտքի հնարավորություն ընձեռել առանց օգտվողի համաձայնության:"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"առբերել պատուհանի այլանիշը"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Ծրագրին թույլ է տալիս առբերել պատուհանի այլանիշը: Վնասակար ծրագրերը կարող են չթույլատրված ազդեցություն ունենալ ծրագրի պատուհանին՝ նմանակելով համակարգը:"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"առբերել շրջանակի վիճակագրությունը"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Ծրագրին թույլ է տալիս հավաքել շրջանակի վիճակագրությունը: Վնասակար ծրագրերը կարող են այլ ծրագրերից հետևել շրջանակի վիճակագրությանը պատուհանների համար:"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"զտել իրադարձությունները"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Թույլ է տալիս հավելվածին գրանցել մուտքագրման զտիչ, որը զտում է օգտվողի իրադարձությունների ամբողջ հոսքը` նախքան դրանք կուղարկվեն: Վնասարար հավելվածը կարող է կառավարել համակարգի UI-ը` առանց ձեր միջամտության:"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"մասնակի անջատում"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Թույլ է տալիս հավելվածին հաղորդել ծանուցում, որ ստացվել է SMS հաղորդագրություն: Վնասարար հավելվածները կարող են օգտագործել սա` կեղծելու մուտքային SMS հաղորդագրությունները:"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ուղարկել ստացված WAP-PUSH-ի  հաղորդում"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Թույլ է տալիս հավելվածին հաղորդել ծանուցում, որ ստացվել է WAP PUSH հաղորդագրություն: Վնասարար հավելվածները կարող են օգտագործել սա` կեղծելու MMS հաղորդագրության ստացումը կամ աննկատ փոխարինելու ցանկացած կայքի բովանդակությունը վնասարար տարբերակներով:"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ուղարկել ցանցերի գնահատականի հեռարձակում"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ծրագրին թույլ է տալիս հեռարձակել ծանուցում, որ ցանցերը պետք է հաշվարկվեն: Նորմալ ծրագրերում երբեք պետք չի գալիս:"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"սահմանափակել աշխատող գործընթացների թիվը"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Թույլ է տալիս հավելվածին վերահսկել գործընթացների առավելագույն թիվը, որ աշխատելու են: Երբևէ անհրաժեշտ չէ սովորական հավելվածների համար:"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"ստիպել, որ առաջին պլանի հավելվածները փակվեն"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Թույլ է տալիս սեփականատիրոջը միանալ Vpn ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"միանալ պաստառին"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Թույլ է տալիս սեփականատիրոջը միանալ պաստառի վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"միանալ հեռակա էկրանին"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Թույլ է տալիս սեփականատիրոջը միանալ հեռակա էկրանի վերին մակարդակի ինտերֆեյսին: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"միանալ վիջեթ ծառայությանը"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Թույլ է տալիս սեփականատիրոջը միանալ վիջեթ ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"կապվել երթուղու մատակարարի ծառայությանը"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Թույլ է տալիս տիրոջը կապվել երթուղու մատակարարներից ցանկացածին: Սովորական ծրագրերի համար երբեք անհրաժեշտ չէ:"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"փոխգործակցել սարքի կառավարչի հետ"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Թույլ է տալիս սեփականատիրոջը ուղարկել մտադրություններ սարքի կառավարչին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"միանալ հեռուստացույցի մուտքին"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Թույլ է տալիս սեփականատիրոջը միանալ հեռուստացույցի մուտքի վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ավելացնել կամ հեռացնել սարքի արդմինիստրատոր"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Թույլ է տալիս սեփականատիրոջը ավելացնել կամ հեռացնել սարքի ակտիվ ադմինիստրատորներ: Երբեք չպետք է անհրաժեշտ լինի սովորական ծրագրերին:"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"փոխել էկրանի դիրքավորումը"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Թույլ է տալիս հավելվածին կարդալ ձեր սարքում պահված անհատական ​​պրոֆիլի տվյալները, ինչպիսիք են ձեր անունը և կոնտակտային տվյալները: Սա նշանակում է, որ հավելվածը կարող է ձեզ ճանաչել և ուղարկել ձեր պրոֆիլի տվյալները ուրիշներին:"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"փոփոխել ձեր սեփական կոնտակտային քարտը"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Թույլ է տալիս հավելվածին փոխել կամ ավելացնել ձեր սարքում պահված անհատական ​​պրոֆիլի տվյալները, ինչպիսիք են ձեր անունը և կոնտակտային տվյալները: Սա նշանակում է, որ հավելվածը կարող է ձեզ ճանաչել և ուղարկել ձեր պրոֆիլի տվյալները ուրիշներին:"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"մարմնի սենսորներ (օր.` սրտի)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ծրագրին թույլ է տալիս մատչել ձեր կողմից օգտագործվող սենսորների տվյալները՝ չափելու, թե ինչ է տեղի ունենում ձեր մարմնի ներսում, ինչպես օրինակ՝ սրտի զարկերը:"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"կարդալ ձեր սոցիալական հոսքը"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Թույլ է տալիս հավելվածին մուտք գործել և համաժամեցնել ձեր և ձեր ընկերների սոցիալական թարմացումները: Զգույշ եղեք տեղեկություններ տարածելիս. այն թույլ է տալիս հավելվածին կարդալ ձեր և ձեր ընկերների միջև անձնական հաղորդագրությունները սոցիալական ցանցերում` անկախ գաղտնիությունից: Նշում. այս թույլտվությունը չի կարող գործածվել բոլոր սոցիալական ցանցերում:"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"գրել ձեր սոցիալական հոսքում"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Փոխել WiMAX-ի կարգավիճակը"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Թույլ է տալիս հավելվածին գրասալիկը միացնել WiMAX ցանցին և անջատվել այդ ցանցից:"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Թույլ է տալիս հավելվածին հեռախոսը միացնել WiMAX ցանցին և անջատել այդ ցանցից:"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ցանցերի գնահատական"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ծրագրին թույլ է տալիս դասակարգել ցանցերը և ազդել գրասալիկի նախընտրելի ցանցի ընտրության գործընթացի վրա:"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ծրագրին թույլ է տալիս դասակարգել ցանցերը և ազդել հեռախոսի նախընտրելի ցանցի ընտրության գործընթացի վրա:"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"զուգակցվել Bluetooth սարքերի հետ"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը գրասալիկի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Թույլ է տալիս հավելվածին տեսնել Bluetooth-ի կարգավորումը հեռախոսի վրա և կապվել ու կապեր ընդունել զուգակցված սարքերի հետ:"</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Թույլ է տալիս հավելվածին առբերել, ուսումնասիրել և մաքրել ծանուցումներն, այդ թվում նաև այլ հավելվածների կողմից գրառվածները:"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"միանալ ծանուցումների ունկնդրիչ ծառայությանը"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Թույլ է տալիս սեփականատիրոջը միանալ ծանուցումները ունկնդրող ծառայության վերին մակարդակի ինտերֆեյսին: Սովորական հավելվածների համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Թույլ է տալիս սեփականատիրոջը գործարկել օպերատորի կողմից տրամադրված կազմաձևման ծրագիրը: Սովորական ծրագրերի համար երբևէ չպետք է անհրաժեշտ լինի:"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"լսել դիտարկումներ ցանցային պայմանների վերաբերյալ"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Պաստառ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Փոխել պաստառը"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ծանուցման ունկնդիր"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN-ը ակտիվացված է"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-ն ակտիվացված է <xliff:g id="APP">%s</xliff:g>-ի կողմից"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Հպեք` ցանցի կառավարման համար:"</string>
diff --git a/core/res/res/values-in/strings.xml b/core/res/res/values-in/strings.xml
index e161466..2fb00bb 100644
--- a/core/res/res/values-in/strings.xml
+++ b/core/res/res/values-in/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Tanpa judul&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinkron"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak <xliff:g id="CONTENT_TYPE">%s</xliff:g> penghapusan."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Penyimpanan tablet penuh. Hapus beberapa file untuk mengosongkan ruang."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Penyimpanan arloji penuh. Hapus beberapa file untuk mengosongkan ruang."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Penyimpanan di ponsel penuh. Hapus sebagian file untuk mengosongkan ruang."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Jaringan mungkin dipantau"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Oleh pihak ketiga yang tidak dikenal"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Pendering nyala"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Sedang mematikan..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet Anda akan dimatikan."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Arloji Anda akan dimatikan."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ponsel Anda akan dimatikan."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Anda ingin mematikannya?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reboot ke mode aman"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mode pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mode pesawat AKTIF"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mode pesawat MATI"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Setelan"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mode aman"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Mengizinkan apl mengambil konten jendela aktif. Apl berbahaya dapat mengambil seluruh konten jendela dan memeriksa semua teksnya kecuali sandi."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktifkan aksesibilitas untuk sementara"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Memungkinkan aplikasi mengaktifkan aksesibilitas pada perangkat untuk sementara. Aplikasi berbahaya dapat mengaktifkan aksesibilitas tanpa izin pengguna."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"mengambil token jendela"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Memungkinkan aplikasi mengambil token jendela. Aplikasi berbahaya dapat melakukan interaksi yang tidak sah dengan jendela aplikasi dengan meniru sistem."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"mengambil statistik bingkai"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Memungkinkan aplikasi mengumpulkan statistik bingkai. Aplikasi berbahaya dapat mengamati statistik bingkai jendela dari aplikasi lain."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"memfilter acara"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Mengizinkan aplikasi mendaftarkan filter masukan yang memfilter streaming semua acara pengguna sebelum acara dikirimkan. Aplikasi berbahaya dapat mengontrol UI sistem tanpa campur tangan pengguna."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penghentian sebagian"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Mengizinkan apl menyiarkan pemberitahuan bahwa pesan SMS telah diterima. Apl berbahaya dapat menggunakan ini untuk memalsukan pesan SMS masuk."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"kirim siaran WAP-PUSH-diterima"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Mengizinkan apl menyiarkan pemberitahuan bahwa pesan WAP PUSH telah diterima. Apl berbahaya dapat menggunakan ini untuk memalsukan penerimaan pesan MMS atau diam-diam mengganti konten laman web apa pun dengan varian berbahaya."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"mengirim siaran beri skor jaringan"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Memungkinkan aplikasi menyiarkan pemberitahuan bahwa jaringan perlu diberi skor. Tidak pernah diperlukan untuk aplikasi normal."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"batasi jumlah dari proses yang berjalan"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Mengizinkan apl mengontrol jumlah maksimum proses yang akan berjalan. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"paksa aplikasi latar belakang agar menutup"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan Vpn. Tidak pernah diperlukan oleh apl normal."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"mengikat ke wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu wallpaper. Tidak pernah diperlukan oleh apl normal."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"mengikat ke pemicu interaksi suara"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari layanan interaksi suara. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"mengikat ke layar jarak jauh"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Mengizinkan pemegang mengikat ke antarmuka tingkat atas dari layar jarak jauh. Tidak pernah diperlukan untuk aplikasi normal."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"mengikat ke layanan widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Mengizinkan pemegang mengikat antarmuka tingkat tinggi dari suatu layanan widget. Tidak pernah diperlukan oleh apl normal."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"mengikat ke layanan penyedia rute"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Memungkinkan pemegang mengikat ke penyedia rute terdaftar mana pun. Tidak pernah dibutuhkan untuk aplikasi normal."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan admin perangkat"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Mengizinkan pemegang mengirimkan tujuan kepada administrator perangkat. Tidak pernah diperlukan oleh apl normal."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"mengikat ke masukan TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Memungkinkan pemegang mengikat ke antarmuka tingkat tinggi dari masukan TV. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"menambah atau menghapus admin perangkat"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Memungkinkan pemegang menambahkan atau menghapus administrator perangkat aktif. Tidak pernah dibutuhkan oleh aplikasi normal."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ubah orientasi layar"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Memungkinkan aplikasi membaca informasi profil pribadi yang tersimpan di perangkat Anda, misalnya nama dan informasi kontak Anda. Ini artinya aplikasi dapat mengenali dan mengirim informasi profil Anda ke orang lain."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"ubah kartu kontak Anda"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Memungkinkan aplikasi mengubah atau menambah informasi profil pribadi yang tersimpan di perangkat Anda, seperti nama dan informasi kontak. Ini berarti aplikasi tersebut dapat mengenali Anda dan mengirim informasi profil Anda ke orang lain."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensor tubuh (misal: monitor detak jantung)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Memungkinkan aplikasi mengakses data dari sensor yang Anda gunakan untuk mengukur yang terjadi di dalam tubuh, misalnya detak jantung."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"membaca aliran sosial Anda"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Memungkinkan aplikasi mengakses dan menyinkronkan pembaruan sosial dari Anda dan teman. Hati-hati ketika berbagi informasi -- izin ini memungkinkan aplikasi membaca komunikasi antara Anda dan teman di jejaring sosial, terlepas dari kerahasiaan. Catatan: izin ini tidak dapat diberlakukan di semua jejaring sosial."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"menulis ke aliran sosial Anda"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Ubah status WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Memungkinkan aplikasi menyambungkan tablet ke dan memutus tablet dari jaringan WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Memungkinkan aplikasi menyambungkan ponsel ke dan memutus ponsel dari jaringan WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"memberi skor jaringan"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Memungkinkan aplikasi menilai jaringan dan memengaruhi jaringan mana yang sebaiknya dipilih tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Memungkinkan aplikasi menilai jaringan dan memengaruhi jaringan mana yang sebaiknya dipilih ponsel."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"sandingkan dengan perangkat Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di tablet, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Memungkinkan aplikasi melihat konfigurasi Bluetooth di ponsel, dan membuat serta menerima sambungan dengan perangkat yang disandingkan."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Mengizinkan aplikasi mengambil, memeriksa, dan menghapus pemberitahuan, termasuk pemberitahuan yang diposkan oleh aplikasi lain."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mengikat layanan pendengar pemberitahuan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Memungkinkan pemegang mengikat antarmuka tingkat teratas dari suatu layanan pendengar pemberitahuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"mengikat ke layanan penyedia ketentuan"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Memungkinkan pemegang mengikat antarmuka tingkat tinggi dari layanan penyedia ketentuan. Tidak pernah diperlukan oleh aplikasi normal."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"memanggil aplikasi konfigurasi yang disediakan operator"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Memungkinkan pemegang meminta aplikasi konfigurasi yang disediakan operator. Tidak pernah diperlukan aplikasi normal."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"mendengar untuk observasi kondisi jaringan"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ubah wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Penyedia ketentuan"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengelola jaringan."</string>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index 740075f..af8ed3f 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Senza nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizzazione"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Troppe eliminazioni di <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Spazio di archiviazione del tablet esaurito. Elimina alcuni file per liberare spazio."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"La memoria dell\'orologio è piena. Elimina alcuni file per liberare spazio."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Spazio di archiviazione del telefono esaurito. Elimina alcuni file per liberare spazio."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"La rete potrebbe essere monitorata"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Da una terza parte sconosciuta"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Suoneria attiva"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Spegnimento..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Il tablet verrà spento."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"L\'orologio verrà spento."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Il telefono verrà spento."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Spegnere?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Riavvia in modalità provvisoria"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modalità aereo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modalità aereo attiva"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modalità aereo non attiva"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Impostazioni"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modalità provvisoria"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Consente all\'applicazione di recuperare i contenuti della finestra attiva. Le applicazioni dannose potrebbero recuperare l\'intero contenuto della finestra ed esaminare tutto il testo, tranne le password."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"attivazione temporanea dell\'accessibilità"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Consente a un\'applicazione di attivare temporaneamente l\'accessibilità sul dispositivo. Le applicazioni dannose potrebbero attivare l\'accessibilità senza il consenso dell\'utente."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"recupero del token delle finestre"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Consente a un\'applicazione di recuperare il token delle finestre. Le app dannose potrebbero effettuare interazioni non consentite con la finestra dell\'applicazione identificandosi come il sistema."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"recupero di statistiche del frame"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Consente a un\'applicazione di raccogliere statistiche del frame. Le app dannose potrebbero osservare le statistiche del frame relative alle finestre da altre app."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtro eventi"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Consente a un\'applicazione di registrare un filtro di ingresso che filtra lo stream di tutti gli eventi degli utenti prima che vengano inviati. Un\'applicazione dannosa potrebbe controllare l\'interfaccia utente del sistema senza l\'intervento dell\'utente."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"chiusura parziale"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Consente all\'applicazione di trasmettere una notifica che informa della ricezione di un messaggio SMS. Le applicazioni dannose potrebbero farne uso per creare messaggi SMS in arrivo."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"invio broadcast ricevuti tramite WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Consente all\'applicazione di trasmettere una notifica che informa della ricezione di un messaggio WAP PUSH. Le applicazioni dannose potrebbero farne uso per simulare la ricezione di messaggi MMS o per sostituire di nascosto i contenuti di qualsiasi pagina web con varianti dannose."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"invio trasmissione classificazione reti"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Consente all\'app di trasmettere una notifica indicante che le reti devono essere classificate. Opzione non necessaria per le app normali."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"numero limite di processi in esecuzione"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Consente all\'applicazione di controllare il numero massimo di processi che verranno eseguiti. Mai necessaria per le applicazioni normali."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"chiusura forzata applicazioni di background"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Consente l\'associazione all\'interfaccia principale di un servizio VPN. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"associazione a sfondo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Consente l\'associazione di uno sfondo all\'interfaccia principale. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"collegamento a un servizio di interazione vocale"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio di interazione vocale. Non dovrebbe essere mai necessaria per le normali app."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"collega a un display remoto"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un display remoto. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"associazione a un servizio widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Consente l\'associazione all\'interfaccia principale di un servizio widget. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"collegamento a un servizio provider di routing"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Consente al titolare di collegarsi a qualsiasi provider di routing registrato. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interazione con un amministratore dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Consente l\'invio di intent a un amministratore del dispositivo. L\'autorizzazione non dovrebbe mai essere necessaria per le normali applicazioni."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"collegamento a ingresso TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un ingresso TV. Non dovrebbe essere mai necessario per le normali applicazioni."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"aggiungere o rimuovere un amministratore del dispositivo"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Consente al titolare di aggiungere o rimuovere gli amministratori attivi del dispositivo. Non dovrebbe mai essere necessario per le normali applicazioni."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"modifica orientamento dello schermo"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Consente all\'applicazione di leggere informazioni del profilo personale memorizzate sul dispositivo, come il tuo nome e le tue informazioni di contatto. Ciò significa che l\'applicazione può identificarti e inviare le informazioni del tuo profilo ad altri."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modifica scheda contatti"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Consente all\'applicazione di modificare o aggiungere informazioni ai dati del profilo personale memorizzati sul dispositivo, come il tuo nome e le tue informazioni di contatto. Significa che l\'applicazione può identificarti e inviare le informazioni del tuo profilo ad altri."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensori per il corpo (come il cardiofrequenzimetro)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Consente all\'app di accedere a dati derivanti dai sensori utilizzati per rilevare cosa sta accadendo nel tuo corpo, ad esempio la frequenza cardiaca."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lettura del tuo stream sociale"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Consente all\'applicazione di accedere agli aggiornamenti dei social network tra te e i tuoi amici e di sincronizzarli. Fai attenzione quando condividi informazioni: questa autorizzazione consente all\'applicazione di leggere le comunicazioni tra te e i tuoi amici sui social network, indipendentemente dal livello di riservatezza. Nota. È possibile che questa autorizzazione non sia applicabile su tutti i social network."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"scrittura nel tuo stream sociale"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Modifica stato WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Consente all\'applicazione di connettere/disconnettere il tablet dalle reti WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Consente all\'applicazione di connettere/disconnettere il telefono dalle reti WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"valutazione reti"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Consente all\'app di stilare una classifica delle reti e determinare quali di queste il tablet deve prediligere."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Consente all\'app di stilare una classifica delle reti e determinare quali di queste il telefono deve prediligere."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"accoppiamento con dispositivi Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul tablet e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Consente all\'applicazione di visualizzare la configurazione del Bluetooth sul telefono e di stabilire e accettare connessioni con dispositivi accoppiati."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Consente all\'app di recuperare, esaminare e cancellare notifiche, comprese quelle pubblicate da altre app."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincolo a un servizio listener di notifica"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Consente al titolare di vincolarsi all\'interfaccia di primo livello di un servizio listener di notifica. Non dovrebbe mai essere necessaria per le normali applicazioni."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"collegamento a un servizio provider di condizioni"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Consente al titolare di collegarsi all\'interfaccia di primo livello di un servizio provider di condizioni. Non dovrebbe essere mai necessaria per le normali app."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"richiamo dell\'app di configurazione operatore-provider"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Consente al titolare di richiamare l\'app di configurazione dell\'operatore-provider. Non dovrebbe essere mai necessaria per le normali applicazioni."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascolto delle osservazioni sulle condizioni di rete"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Sfondo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Cambia sfondo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener di notifica"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider condizioni"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN attiva"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN attivata da <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tocca per gestire la rete."</string>
diff --git a/core/res/res/values-iw/strings.xml b/core/res/res/values-iw/strings.xml
index 61754c3..0157f74 100644
--- a/core/res/res/values-iw/strings.xml
+++ b/core/res/res/values-iw/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"‏&gt;ללא כותרת&lt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"סינכרון"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"יש מחיקות רבות מדי של <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"שטח האחסון של הטאבלט מלא. מחק קבצים כדי לפנות מקום."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"שטח האחסון של השעון מלא. מחק כמה קבצים כדי לפנות שטח."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"שטח האחסון של הטלפון מלא. מחק חלק מהקבצים כדי לפנות שטח."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ייתכן שהרשת מנוטרת"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"על ידי צד שלישי לא מוכר"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"צלצול מופעל"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"מכבה..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"הטאבלט שלך יכבה."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"השעון יכבה."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"הטלפון שלך יכובה."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"האם ברצונך לבצע כיבוי?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"אתחל למצב בטוח"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"מצב טיסה"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"מצב טיסה מופעל"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"מצב טיסה כבוי"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"הגדרות"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"מצב בטוח"</string>
     <string name="android_system_label" msgid="6577375335728551336">"‏מערכת Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"מאפשר לאפליקציה לאחזר את התוכן של החלון הפעיל. אפליקציות זדוניות עלולות לאחזר את תוכן החלון כולו ולבחון את כל הטקסט שבו, מלבד סיסמאות."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"הפעלת נגישות זמנית"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"מאפשר לאפליקציה להפעיל באופן זמני נגישות במכשיר. אפליקציות זדוניות עלולות לאפשר נגישות ללא הסכמת משתמש."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"אחזור אסימון חלון"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"מאפשרת לאפליקציה לאחזר את אסימון החלון. אפליקציות זדוניות עשויות לבצע אינטראקציה בלתי מורשית עם חלון האפליקציה, ולהעמיד פנים שהן המערכת."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"אחזור סטטיסטיקת מסגרת"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"מאפשרת לאפליקציה לאסוף סטטיסטיקת מסגרת. אפליקציות זדוניות עשויות לבחון את סטטיסטיקת המסגרת של חלונות מאפליקציות אחרות."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"סנן אירועים"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"‏מאפשר לאפליקציה לרשום מסנן קלט שמסנן את הזרם של כל אירועי המשתמש לפני שהם נשלחים. אפליקציה זדונית עשויה לשלוט ב-UI של המערכת ללא התערבות משתמש."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"כיבוי חלקי"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"‏מאפשר לאפליקציה לשדר התראה על כך שהתקבלה הודעת SMS. אפליקציות זדוניות עלולות להשתמש בכך כדי לזייף הודעות SMS נכנסות."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"‏שלח שידור שהתקבל באמצעות WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"‏מאפשר לאפליקציה לשדר התראה על כך שהתקבלה הודעה מסוג WAP PUSH. אפליקציות זדוניות עלולות להשתמש בכך כדי לזייף קבלה של הודעות MMS או כדי להחליף בחשאי את התוכן של דף אינטרנט כלשהו בגירסאות זדוניות."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"שלח שידור לדירוג רשתות"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"מאפשר לאפליקציה לשדר התראה על כדי שיש לדרג את הרשתות. לא בשימוש עבור אפליקציות רגילות."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"הגבל את מספר התהליכים הפועלים"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"מאפשר לאפליקציה לשלוט על המספר המרבי של תהליכים שיפעלו. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"אילוץ סגירה של אפליקציות ברקע"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"‏מאפשר למשתמש לבצע איגוד לממשק ברמה עליונה של שירות VPN. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"קשור לטפט"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של טפט. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"איגוד לשירות אינטראקציה קולית"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות אינטראקציה קולית. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"איגוד לצג מרוחק"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של צג רחוק. לעולם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"‏הכפפה לשירות Widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"‏מאפשר למשתמש לבצע איגוד לממשק הרמה העליונה של שירות Widget. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"איגוד לשירות של ספק ניתוב"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"מאפשרת לבעלים לאגד לספקי ניתוב רשומים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"קיים אינטראקציה עם מנהל המכשיר"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"מאפשר למשתמש לשלוח כוונות למנהל התקנים. הרשאה זו לעולם אינה נחוצה לאפליקציות רגילים."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"איגוד לקלט טלוויזיה"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"הרשאה זו מאפשרת למחזיק בה לבצע איגוד לממשק הרמה העליונה של קלט טלוויזיה. הרשאה זו אף פעם אינה אמורה להיות נחוצה לאפליקציות רגילות."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"הוספה או הסרה של מנהלי מכשיר"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"מאפשרת לבעלים להוסיף או להסיר מנהלי מכשיר פעילים. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"שנה את כיוון המסך"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"מאפשר לאפליקציה לקרוא פרטים מהפרופיל האישי המאוחסנים במכשיר, כגון שמך ופרטי אנשי הקשר שלך. משמעות הדבר שהאפליקציה תוכל לזהות אותך ולשלוח את פרטי הפרופיל שלך לאנשים אחרים."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"שינוי כרטיס איש הקשר שלך"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"מאפשר לאפליקציה לשנות או להוסיף נתונים לפרטי הפרופיל האישי המאוחסנים במכשיר, כגון שמך ופרטי הקשר שלך. משמעות הדבר שהאפליקציה יכולה לזהות אותך ועשוי לשלוח את פרטי הפרופיל שלך לאנשים אחרים."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"חיישני גוף (כמו מוניטורים עבור קצב לב)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"מאפשר לאפליקציה לגשת לנתוני חיישנים שבהם אתה משתמש כדי למדוד פעילות המתרחשת בתוך הגוף, כמו קצב לב."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"קריאת הזרם החברתי שלך"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"מאפשר לאפליקציה גישה ויכולת סנכרון של עדכונים חברתיים שאתה וחבריך מבצעים. היזהר בעת שיתוף מידע -- הדבר מתיר לאפליקציה לקרוא התכתבויות בינך ובין חבריך ברשתות חברתיות, ללא התחשבות בסודיות. שים לב: ייתכן שאישור זה לא נאכף בכל הרשתות החברתיות."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"כתיבה בזרם החברתי שלך"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"‏שנה את מצב WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"‏מאפשר לאפליקציה לחבר את הטאבלט לרשתות WiMAX ולהתנתק מהן."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"‏מאפשר לאפליקציה לחבר את הטלפון לרשתות WiMAX ולהתנתק מהן."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"דרג רשתות"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"מאפשר ליישום לדרג רשתות ולהשפיע על הרשתות שאותן הטאבלט יעדיף."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"מאפשר ליישום לדרג רשתות ולהשפיע על הרשתות שאותן הטלפון יעדיף."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"‏התאמה למכשירי Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"‏מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטאבלט, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"‏מאפשר לאפליקציה להציג את תצורת ה-Bluetooth בטלפון, וכן ליצור ולקבל חיבורים עם מכשירים מותאמים."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"מאפשר לאפליקציה לאחזר, לבדוק ולמחוק התראות, כולל כאלה שפורסמו על ידי אפליקציות אחרות."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"איגוד לשירות של מאזין להתראות"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"הרשאה זו מאפשרת למשתמש לבצע איגוד לממשק הרמה העליונה של שירות מאזין להתראות. הרשאה זו אף פעם אינה נחוצה לאפליקציות רגילים."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"איגוד לשירות ספק תנאי"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"מאפשרת לבעלים לאגד לממשק ברמה העליונה של שירות ספק תנאי. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"הפעלה של אפליקציית תצורה שסופקה על ידי ספק"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ההרשאה הזו מאפשרת לבעלים להפעיל את אפליקציית התצורה שסופקה על ידי ספק. לעולם לא אמורה להיות נחוצה עבור אפליקציות רגילות."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"קליטת מעקב אחר תנאי רשת"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"טפט"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"שנה טפט"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"מאזין להתראות"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ספק תנאי"</string>
     <string name="vpn_title" msgid="19615213552042827">"‏VPN מופעל"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"‏VPN מופעל על ידי <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"גע כדי לנהל את הרשת."</string>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 62ee883..a9c5cfb 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;新規&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同期"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>での削除が多すぎます。"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"タブレットのストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"ウォッチのストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"端末のストレージに空き領域がありません。ファイルを削除して空き領域を確保してください。"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ネットワークが監視される場合があります"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"不明な第三者"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"着信音オン"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"シャットダウン中..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"タブレットの電源をOFFにします。"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ウォッチの電源をOFFにします。"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"携帯電話の電源を切ります。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"シャットダウンしますか?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"再起動してセーフモードに変更"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"機内モード"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"機内モードON"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"機内モードOFF"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"セーフモード"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Androidシステム"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"作業中のウィンドウの内容を取得することをアプリに許可します。この許可を悪意のあるアプリに利用されると、ウィンドウの内容全体が取得されてパスワード以外のテキストがすべてチェックされる恐れがあります。"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ユーザー補助を一時的に有効にする"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"この端末のユーザー補助を一時的に有効にすることをアプリに許可します。悪意のあるアプリはユーザーの同意を得ずにユーザー補助を有効にする場合があります。"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ウィンドウトークンの取得"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"ウィンドウトークンの取得をアプリに許可します。この許可を悪意のあるアプリに利用されると、システムを装ったアプリケーションウィンドウで不正な操作が実行される恐れがあります。"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"フレーム統計情報の取得"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"フレーム統計情報の収集をアプリに許可します。この許可を悪意のあるアプリに利用されると、他のアプリからウィンドウのフレーム統計情報を監視される恐れがあります。"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"イベントのフィルタリング"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"すべてのユーザーイベントが送られる前にストリームをフィルタリングする入力フィルタを登録することをアプリに許可します。悪意のあるアプリがユーザーの操作なしでシステムUIを制御する恐れがあります。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分的にシャットダウンする"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"SMSメッセージの受信通知の配信をアプリに許可します。この許可を悪意のあるアプリケーションに利用されると、受信SMSメッセージが偽造される恐れがあります。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH受信ブロードキャストの送信"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"WAP PUSHメッセージの受信通知を配信することをアプリに許可します。この許可を悪意のあるアプリに利用されると、MMSメッセージの受信確認が偽造されたりウェブページのコンテンツが悪意のあるコンテンツに密かに置き換えられたりする恐れがあります。"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ネットワークスコアのブロードキャスト送信"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ネットワークのスコアリングが必要であるという通知をブロードキャスト送信することをアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"実行中のプロセスの数を制限"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"実行するプロセスの上限数を制御することをアプリに許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"バックグラウンドのアプリの強制終了"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"VPNサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"壁紙にバインド"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"壁紙のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"音声対話サービスへのバインド"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"音声対話サービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"リモートディスプレイへのバインド"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"リモートディスプレイのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ウィジェットサービスにバインド"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ウィジェットサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ルートプロバイダサービスへのバインド"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"登録済みのルートプロバイダにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"デバイス管理者との通信"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"デバイス管理者へのintentの送信を所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"テレビの入力へのバインド"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"テレビの入力のトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"端末の管理者の追加または削除"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"有効な端末の管理者を追加または削除することを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"画面の向きの変更"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"端末に保存されている個人のプロフィール情報(名前、連絡先情報など)の読み取りをアプリに許可します。これにより、アプリがユーザーの身元を特定できるようになり、プロフィール情報を第三者に転送する可能性があります。"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"自分の連絡先カードの変更"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"端末に保存されている個人のプロフィール情報(名前、連絡先情報など)の変更と追加をアプリに許可します。これにより、アプリがユーザーの身元を特定できるようになり、プロフィール情報を第三者に転送する可能性があります。"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"ボディーセンサー(心拍数モニターなど)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"心拍数など、体内の変化の測定に使用するセンサーからのデータにアクセスすることをアプリに許可します。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ソーシャルストリームを読む"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"あなたや友だちのソーシャル更新情報へのアクセスと同期をアプリに許可します。情報の共有は慎重に行ってください。これを許可すると、あなたと友だちがソーシャルネットワークで行ったやり取りを、機密性に関係なくアプリから読み取ることができるようになります。注: この許可は、一部のソーシャルネットワークでは適用されない場合があります。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ソーシャルストリームに書く"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX状態の変更"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"タブレットのWiMAXネットワークへの接続と切断をアプリに許可します。"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"携帯端末のWiMAXネットワークへの接続と切断をアプリに許可します。"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ネットワークスコア"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ネットワークを順位付けし、タブレットでのネットワークの優先順位に反映することをアプリに許可します。"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ネットワークを順位付けし、携帯電話でのネットワークの優先順位に反映することをアプリに許可します。"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetoothデバイスのペアの設定"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"タブレットのBluetooth設定を表示すること、ペアの端末に接続すること/ペアの端末からの接続を受け入れることをアプリに許可します。"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"携帯端末のBluetooth設定を表示すること、ペアの端末に接続すること/ペアの端末からの接続を受け入れることをアプリに許可します。"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"通知(他のアプリから投稿されたものも含む)を取得、調査、クリアすることをアプリに許可します。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"通知リスナーサービスにバインド"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"通知リスナーサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"コンディションプロバイダサービスへのバインド"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"コンディションプロバイダサービスのトップレベルインターフェースにバインドすることを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"携帯通信会社が提供する設定アプリの呼び出し"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"携帯通信会社が提供する設定アプリを呼び出すことを所有者に許可します。通常のアプリでは不要です。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ネットワーク状況監視のためのリッスン"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁紙"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"壁紙を変更"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知リスナー"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"コンディションプロバイダ"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPNが有効になりました"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPNが<xliff:g id="APP">%s</xliff:g>により有効化されました"</string>
     <string name="vpn_text" msgid="3011306607126450322">"タップしてネットワークを管理します。"</string>
diff --git a/core/res/res/values-ka-rGE/strings.xml b/core/res/res/values-ka-rGE/strings.xml
index 4855f27..e5ec81b 100644
--- a/core/res/res/values-ka-rGE/strings.xml
+++ b/core/res/res/values-ka-rGE/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"ტბაიტი"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"უსათაურო"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"სინქრონიზაცია"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g>-ის ძალიან ბევრი წაშლილები."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"ტაბლეტის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"საათის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"ტელეფონის მეხსიერება გავსებულია. ადგილის გასათავისუფლებლად წაშალეთ ფაილების ნაწილი."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"შესაძლოა ქსელი მონიტორინგის ქვეშ იმყოფება"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"უცნობი მესამე მხარის მიერ"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"ზარი ჩართულია"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"გამორთვა…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"თქვენი ტაბლეტი გაითიშება."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"თქვენი საათი გაითიშება."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"თქვენი ტელეფონი გაითიშება."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"გსურთ გამორთვა?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"უსაფრთხო რეჟიმის ჩატვირთვა"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"თვითმფრინავის რეჟიმი"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"თვითმფრინავის რეჟიმი ჩართულია."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"თვითმფრინავის რეჟიმი გამორთულია."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"პარამეტრები"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"უსაფრთხო რეჟიმი"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-ის სისტემა"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"აპს შეეძლება აქტიური ფანჯრიდან კონტენტის მოძიება. მავნე აპებს შეუძლიათ ფანჯრის სრული კონტენტის მოძიება და ყველა ტექსტის წაკითხვა პაროლების გარდა."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"მარტივი წვდომის დროებით გააქტიურება"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"აპს შეეძლება მოწყობილობაზე გამარტივებული რეჟიმის ჩართვა. მავნე აპებს შეეძლებათ ამ რეჟიმის ჩართვა მომხმარებლის გაფრთხილების გარეშე."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ფანჯრის ჟეტონის მოძიება"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"ნებას რთავს აპლიკაციას მოიძიოს ფანჯრის ჟეტონი. მავნე აპებს შეუძლია აპლიკაციის ფანჯარასთან არაავტორიზებული ინტერაქცია განახორციელოს და თავი სისტემად წარმოაჩინოს."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"ჩარჩოს სტატისტიკის მოძიება"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"ნებას რთავს აპლიკაციას შეაგროვოს ჩარჩოს სტატისტიკა. მავნე აპებმა შესაძლოა ფანჯრების ჩარჩოს სტატისტიკის მონიტორინგი განახორციელოს სხვა აპებიდან."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"ღონისძიებების გაფილტვრა"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"აპლიკაციას შეეძლება რეგისტრაცია შეტანის ფილტრებისა, რომლებიც ასუფთავებენ მომხმარებლის ღონისძიების ყველა დინებას. მავნე აპმა შესაძლოა ეს ფუნქცია სისტემის UI კონტროლისთვის გამოიყენოს, მომხმარებლის ინტერვენციის გარეშე."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ნაწილობრივი გამორთვა"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"აპს საშუალებას აძლევს გააგზავნოს შეტყობინება SMS შეტყობინების მიღების თაობაზე. მავნე აპლიკაციებში ეს ფუნქცია შეიძლება გამოყენებული იქნას SMS შეტყობინებების მიღების იმიტაციიისათვის."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-ით მიღებული სამაუწყებლო შეტყობინების გაგზავნა"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"აპს შეეძლება, გაგზავნოს შეტყობინება WAP PUSH შეტყობინების მიღების თაობაზე. მავნე აპებმა ეს შეიძლება გამოიყენონ MMS შეტყობინების მიღების გასაყალბებლად ან ნებისმიერი ვებგვერდის კონტენტის სახიფათო ვარიანტებით ჩუმად ჩასანაცვლებლად."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ქსელის შეფასებების მაუწყებლობის გაგზავნა"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"აპს ნებას რთავს გადასცეს შეტყობინება, რომ ქსელები შეფასებას საჭიროებს. ჩვეულებრივ აპებს ეს არასოდეს ჭირდება."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"მიმდინარე პროცესების რაოდენობის ლიმიტი"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"აპს შეეძლება, გააკონტროლოს მიმდინარე პროცესების მაქსიმალური რაოდენობა. ჩვეულებრივ აპებში არასდროს არის საჭირო."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"უკანა ფონის აპის იძულებით დახურვა"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"აპს შეეძლება Vpn სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ფონზე მიჭედება"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"მფლობელს შეეძლება ფონის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"დისტანციურ მონიტორზე მიბმა"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"მფლობელს შეეძლება მიებას დისტანციურ მონიტორის ზედა დონის ინტერფეისს. ჩვეულებრივ აპს ეს წესით არასოდეს უნდა დაჭირდეს."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ვიჯეტ სერვისთან დაკავშირება"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"აპს შეეძლება ზედა დონის ინტერფეისის ვიჯეტთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"მარშრუტის სერვისის პროვაიდერთან შეკავშირება"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"საშუალებას აძლევს მფლობელს შეკავშირდეს მარშრუტების ნებისმიერ პროვაიდერთან. ჩვეულებრივ აპებს უმეტეს შემთხვევაში არ დაჭირდება."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"მოწყობილობის ადმინთან ინტერაქცია"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"აპს შეეძლება მოწყობილობის ადმინისტრატორისთვის intent ობიექტების გაგზავნა. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"TV შეყვანასთან მიბმა"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"აპს შეეძლება TV შეყვანის ზედა დონის ინტერფეისთან დაკავშირება. არასდროს გამოიყენება ჩვეულებრივ აპებში."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"მოწყობილობის ადმინისტრატორს დამატება ან ამოშლა"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"საშუალებას აძლევს მფლობელს დაამატოს ან ამოშალოს მოწყობილობის აქტიური ადმინისტრატორები. ჩვეულებრივ აპებს, ალბათ, არასოდეს დაჭირდება"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ეკრანის ორიენტაციის შეცვლა"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"აპს შეეძლება მოწყობილობაზე შენახული პირადი პროფილის ინფორმაციის წაკითხვა, მაგალითად, თქვენი სახელისა და საკონტაქტო ინფორმაციის. ეს ნიშნავს, რომ აპს შეუძლია თქვენი იდენტიფიცირება და თქვენი პირადი ინფორმაციის სხვებისთვის გაგზავნა."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"თქვენი საკონტაქტო ინფორმაციის შეცვლა"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"აპს შეეძლება მოწყობილობაზე შენახული პირადი პროფილის ინფორმაციის შეცვლა ან დამატება, მაგალითად, თქვენი სახელისა და საკონტაქტო ინფორმაციის. ეს ნიშნავს, რომ აპს შეუძლია თქვენი იდენტიფიცირება და თქვენი პირადი ინფორმაციის სხვებისთვის გაგზავნა."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"სხეულის სენსორები (მაგ. გულისცემის მონიტორები)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"საშუალებას აძლევს აპს იქონიოს წვდომა თქვენ მიერ გამოყენებული სენსორებიდან, რათა გაზომოთ, რა ხდება თქვენ სხეულში, მაგ. გულის ცემის რითმი."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"სოციალური ნაკადის წაკითხვა"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"აპს შეეძლება თქვენი და თქვენი მეგობრების სოციალური განახლებებთან წვდომა და სინქრონიზაცია. ინფორმაციის გაზიარებისას იყავით ფრთხიად - აპს ექნება შესაძლებლობა, რომ წაიკითხოს სოციალურ ქსელებში კომუნიკაცია თქვენსა და თქვენს მეგობრებს შორის კონფიდენციალურობის მიუხედავად. შენიშვნა: ეს უფლება შესაძლოა ვერ იყოს გამოყენებული ყველა სოციალურ ქსელში."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"თქვენს სოციალურ მაუწყებლობაზე დაწერა"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX მდგომარეობის შეცვლა"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტაბლეტი WiMAX ქსელებიდან."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"აპს შეეძლება, დაუკავშიროს და გამოაერთოს ტელეფონი WiMAX ქსელებიდან."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ქსელების შეფასება"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"აპს ნებას რთავს შეაფასოს ქსელები და იქონიოს ზეგავლენა, თუ რომელი ქსელი ამჯობინოს ტაბლეტმა."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"აპს ნებას რთავს შეაფასოს ქსელები და იქონიოს ზეგავლენა, თუ რომელი ქსელი ამჯობინოს ტელეფონმა."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth მოწყობილობებთან დაწყვილება"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტაბლეტზე, შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"აპს შეეძლება, ნახოს Bluetooth-ის კონფიგურაცია ტელეფონზე და შექმნას და მიიღოს კავშირები დაწყვილებულ მოწყობილობებთან."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"აპს შეეძლება მოიძიოს, გამოიკვლიოს და წაშალოს შეტყობინებები, მათ შორის სხვა აპების მიერ გამოქვეყნებული."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"შეტყობინებების მოსმენის სერვისთან დაკავშირება"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"მფლობელს შეეძლება შეტყობინებების მსმენლის სერვისის ზედა დონის ინტერფეისთან დაკავშირება. არ უნდა მოხდეს მისი გამოყენება ჩვეუელებრივი აპებისთვის.ფ"</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ოპერატორის მიერ მოწოდებული კოფიგურაციის აპის გამოხმობა"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"საშუალებას აძლევს მფლობელს გამოიწვიოს ოპერატორის მიერ მოწოდებული კონფიგურაციის აპი. ჩვეულებრივ აპს ეს წესით არასოდეს არ უნდა დაჭირდეს."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"განხორციელდეს ქსელის მდგომარეობის მონიტორინგი"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ფონი"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ფონის შეცვლა"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"შეტყობინებების მსმენელი"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN გააქტიურებულია"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN გააქტიურებულია <xliff:g id="APP">%s</xliff:g>-ის მიერ"</string>
     <string name="vpn_text" msgid="3011306607126450322">"შეეხეთ ქსელის სამართავად."</string>
diff --git a/core/res/res/values-km-rKH/strings.xml b/core/res/res/values-km-rKH/strings.xml
index 73769fb..e9a021c 100644
--- a/core/res/res/values-km-rKH/strings.xml
+++ b/core/res/res/values-km-rKH/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"តេរ៉ាបៃ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;គ្មាន​ចំណង​ជើង&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ធ្វើ​សម​កាល​កម្ម"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"មាន​ការ​លុប <xliff:g id="CONTENT_TYPE">%s</xliff:g> ច្រើន​ពេក។"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"ឧបករណ៍​ផ្ទុក​នៃ​​កុំព្យូទ័រ​បន្ទះ​ពេញ។ លុប​ឯកសារ​មួយ​ចំនួន​។"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"ឧបករណ៍​របស់​នាឡិកា​ពេញ។ លុប​ឯកសារ​មួយ​ចំនួន​។"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"ឧបករណ៍​ផ្ទុក​ទូរស័ព្ទ​ពេញ! លុប​ឯកសារ​មួយ​ចំនួន​ដើម្បី​បង្កើន​ទំហំ។"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"បណ្ដាញ​អាច​ត្រូវ​បាន​តាមដាន"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ដោយ​ភាគី​ទីបី​ដែល​មិន​ស្គាល់"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"បើក​កម្មវិធី​រោទ៍"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"កំពុង​បិទ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"កុំព្យូទ័រ​បន្ទះ​របស់​អ្នក​នឹង​បិទ។"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"នាឡិកា​របស់​អ្នក​នឹង​បិទ។"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ទូរស័ព្ទ​របស់​អ្នក​នឹង​បិទ។"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"តើ​អ្នក​ចង់​បិទ​?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"ចាប់ផ្ដើម​ឡើងវិញ​ដើម្បី​ចូល​របៀប​សុវត្ថិភាព"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ពេល​ជិះ​យន្តហោះ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"បាន​បើក​របៀប​ពេល​ជិះ​យន្ត​ហោះ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"បាន​បិទ​របៀបពេលជិះ​យន្តហោះ"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"ការ​កំណត់"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"របៀប​​​សុវត្ថិភាព"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ប្រព័ន្ធ​​ Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ឲ្យ​កម្មវិធី​ទៅ​យក​មាតិកា​បង្អួច​សកម្ម។ កម្មវិធី​ព្យាបាទ​អាច​ទៅ​យក​មាតិកា​បង្អួច​ទាំង​មូល និង​ពិនិត្យ​អត្ថបទ​ទាំងអស់ លើកលែង​តែ​ពាក្យ​សម្ងាត់។"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"បើក​មធ្យោបាយ​ងាយស្រួល​ជា​បណ្ដោះ​អាសន្ន"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ឲ្យ​កម្មវិធី​បើក​ភាព​ងាយស្រួល​លើ​ឧបករណ៍​ជា​បណ្ដោះអាសន្ន។ កម្មវិធី​ព្យាបាទ​អាច​បើក​ភាព​ងាយស្រួល​ដោយ​មិន​ឲ្យ​អ្នក​ប្រើ​ដឹង។"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"ទៅ​យក​និមិត្តសញ្ញា​​បង្អួច"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"ឲ្យ​កម្មវិធី​ទៅ​យក​និមិត្តសញ្ញា​បង្អួច។ កម្មវិធី​ព្យាបាទ​អាច​អនុវត្ត​អន្តរកម្ម​ដែល​មិន​បាន​អនុញ្ញាត​ជា​មួយ​​បង្អួច​កម្មវិធី​ដោយ​ក្លែង​ធ្វើ​ជា​ប្រព័ន្ធ។"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"ទៅ​យក​ស្ថិតិ​ស៊ុម"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"ឲ្យ​កម្មវិធី​ប្រមូល​ស្ថិតិ​ស៊ុម​។ កម្មវិធី​ព្យាបាទ​អាច​សង្កេត​មើល​បង្អួច​ស្ថិតិ​ស៊ុម​ពី​កម្មវិធី​ផ្សេង។"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"ច្រោះ​ព្រឹត្តិការណ៍"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"ឲ្យ​កម្មវិធី​ចុះ​ឈ្មោះ​តម្រង​បញ្ចូល​​ដែល​ច្រោះ​​ព្រឹត្តិការណ៍​របស់​អ្នក​ប្រើ​ទាំងអស់​មុន​ពេល​ពួក​វា​ត្រូវ​បាន​ផ្ដាច់។ កម្មវិធី​ព្យាបាទ​អាច​ពិនិត្យ​ចំណុច​ប្រទាក់​ប្រព័ន្ធ​ដោយ​គ្មាន​អំពើ​ពី​អ្នក​ប្រើ។"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"បិទ​​ដោយ​ផ្នែក"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ឲ្យ​កម្មវិធី​ប្រកាស​ការ​ជូន​ដំណឹង​​ការ​ទទួល​សារ​ SMS ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា​​ដើម្បី​​បន្លំ​សារ SMS ចូល។"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ផ្ញើ​ការ​ប្រកាស​បាន​ទទួល​ WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ឲ្យ​កម្មវិធី​ប្រកាស​ការ​ជូន​ដំណឹង​ថា​បាន​ទទួល​សារ WAP PUSH ។ កម្មវិធី​ព្យាបាទ​អាច​ប្រើ​វា​ដើម្បី​​ក្លែង​​បង្កាន់ដៃ​សារ MMS ឬ​ជំនួស​មាតិកា​ទំព័រ​បណ្ដាញ​ណាមួយ​ស្ងាត់​ៗ​​​ដោយ​អ្វី​ដែល​ក្លែងក្លាយ។"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ផ្ញើ​ពិន្ទុ​ការ​ប្រកាស​បណ្ដាញ"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"ឲ្យ​កម្មវិធី​ប្រកាស​ការ​ជូនដំណឹង​ដែល​បណ្ដាញ​តម្រូវ​ឲ្យ​ដាក់​ពិន្ទុ។ មិន​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា។"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"កំណត់​ចំនួន​ដំណើរការ​ដែល​កំពុង​ដំណើរការ"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ឲ្យ​កម្មវិធី​ពិនិត្យ​ចំនួន​ដំណើរការ​អតិបរមា​ដែល​នឹង​ដំណើរការ។ មិន​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"បង្ខំ​​ឲ្យ​បិទ​កម្មវិធី​ក្នុង​ផ្ទៃ​ខាង​ក្រោយ"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម Vpn ។​ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ចង​ទៅ​ផ្ទាំង​រូបភាព"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ឲ្យ​ម្ចាស់​ចង​ចំណុចប្រទាក់​កម្រិត​កំពូល​នៃ​ផ្ទាំង​រូបភាព។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"ភ្ជាប់​ទៅ​​អ្នក​សហការ​សំឡេង"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​អន្តរកម្ម​សំឡេង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ភ្ជាប់​ទៅ​ការ​បង្ហាញ​ពី​ចម្ងាយ"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​ការ​បង្ហាញ​ពី​ចម្ងាយ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ចង​សេវា​កម្ម​ធាតុ​ក្រាហ្វិក"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​ធាតុ​ក្រាហ្វិក។ មិន​គួរ​​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​ច្រក"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ក្រុមហ៊ុន​ផ្ដល់​​ច្រក​ដែល​បាន​ចុះ​ឈ្មោះ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ទាក់ទង​ជា​មួយ​អ្នកគ្រប់គ្រង​ឧបករណ៍"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ឲ្យ​ម្ចាស់​ផ្ញើ​គោលបំណង​​ទៅ​អ្នក​គ្រប់គ្រង​ឧបករណ៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ភ្ជាប់​ទៅ​ការ​បញ្ចូល​ទូរទស្សន៍"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុចប្រទាក់​កម្រិត​ខ្ពស់​នៃ​ការ​បញ្ចូល​ទូរទស្សន៍។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​​​ឧបករណ៍"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"អនុញ្ញាត​​​ឲ្យ​ម្ចាស់​​​បន្ថែម​ ឬ​លុប​កម្មវិធី​គ្រប់គ្រង​ឧបករណ៍​សកម្ម​ចេញ​។ មិន​គួរ​ប្រើ​សម្រាប់​កម្មវិធី​​ធម្មតា​ទេ​។"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ប្ដូរ​ទិស​អេក្រង់"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"ឲ្យ​កម្មវិធី​អាន​ព័ត៌មាន​ប្រវត្តិរូប​ផ្ទាល់ខ្លួន​ដែល​មាន​លើ​ឧបករណ៍​របស់​អ្នក ដូច​ជា ឈ្មោះ និង​ព័ត៌មាន​ទំនាក់ទំនង។ វា​មាន​ន័យ​ថា កម្មវិធី​អាច​កំណត់​អ្នក និង​អាច​ផ្ញើ​ព័ត៌មាន​ប្រវត្តិរូប​របស់​អ្នក​ទៅ​អ្នក​ផ្សេង។"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"កែ​កាត​ទំនាក់ទំនង​ផ្ទាល់​ខ្លួន​របស់​អ្នក"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ឲ្យ​កម្មវិធី​ប្ដូរ ឬ​បន្ថែម​ព័ត៌មាន​ប្រវត្តិរូប​ផ្ទាល់​ខ្លួន​ដែល​បាន​រក្សាទុក​ក្នុង​ឧបករណ៍​របស់​អ្នក ដូចជា ឈ្មោះ និង​ព័ត៌មាន​ទំនាក់ទំនង​របស់​អ្នក។ នេះ​មាន​ន័យ​ថា​កម្មវិធី​អាច​កំណត់​អ្នក និង​ផ្ញើ​ព័ត៌មាន​ប្រវត្តិរូប​របស់​អ្នក​ទៅ​អ្នក​ផ្សេង។"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"ឧបករណ៍ចាប់សញ្ញារាងកាយ(ដូចជាម៉ាស៊ីនវាស់ចង្វាក់បេះដូង)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"​ឲ្យ​​កម្មវិធី​ដើម្បី​ចូល​ដំណើរការ​ទិន្នន័យ​ពី​ឧបករណ៍​ចាប់​សញ្ញា​ដែល​អ្នក​ប្រើ​ ដើម្បី​វាស់​ពី​អ្វី​ដែល​កំពុង​កើត​ឡើង​នៅ​ខាង​ក្នុង​ខ្លួន​របស់​អ្នក​ដូច​ជា​ចង្វាក់​បេះដូង​។"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"អាន​ចរន្ត​​សង្គម​របស់​អ្នក"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ឲ្យ​កម្មវិធី​ចូល​ដំណើរការ និង​ធ្វើ​សម​កាល​កម្ម​បច្ចុប្បន្នភាព​សង្គម​ពី​អ្នក​ និង​មិត្តភ័ក្ដិ។ ប្រយ័ត្ន​ពេល​ចែករំលែក​ព័ត៌មាន វា​អនុញ្ញាត​ឲ្យ​កម្មវិធី​អាន​ការ​ទាក់ទង​រវាង​អ្នក​ និង​មិត្តភ័ក្ដិ​លើ​បណ្ដាញ​សង្គម ទាក់ទង​នឹង​ព័ត៌មាន​សម្ងាត់។ ចំណាំ៖​ សិទ្ធិ​នេះ​មិន​អាច​ត្រូវ​បាន​​អនុវត្ត​លើ​បណ្ដាញ​សង្គម​ទាំង​អស់​បាន​ទេ។"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"សរសេរ​ទៅ​ចរន្ត​សង្គម​របស់​អ្នក"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"ប្ដូរ​ស្ថានភាព WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ឲ្យ​កម្មវិធី​តភ្ជាប់​ និង​ផ្ដាច់​កុំព្យូទ័រ​បន្ទះ​ពី​បណ្ដាញ WiMAX ។"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ឲ្យ​កម្មវិធី​ភ្ជាប់​ទូរស័ព្ទ​ និង​ផ្ដាច់​ពី​បណ្ដាញ WiMAX ។"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ដាក់​ពិន្ទុ​បណ្ដាញ"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ឲ្យ​កម្មវិធី​ចាត់​ថ្នាក់​បណ្ដាញ និង​​មាន​ឥទ្ធិពល​លើ​បណ្ដាញ​ណា​មួយ​ដែល​​កុំព្យូទ័រ​បន្ទះ​ប្រើ។"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ឲ្យ​កម្មវិធី​ចាត់​ថ្នាក់​បណ្ដាញ និង​​មាន​ឥទ្ធិពល​លើ​បណ្ដាញ​ណា​មួយ​ដែល​ទូរស័ព្ទ​គួរ​ប្រើ។"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ផ្គូផ្គង​ជា​មួយ​ឧបករណ៍​ប៊្លូធូស"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ឲ្យ​កម្មវិធី​មើល​ការ​កំណត់​រចនាសម្ព័ន្ធ​​ប៊្លូធូស​លើ​​កុំព្យូទ័រ​បន្ទះ ព្រម​ទាំង​ធ្វើ​ការ​តភ្ជាប់ និង​ទទួល​​ជា​មួយ​ឧបករណ៍​បាន​ផ្គូផ្គង។"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ឲ្យ​កម្មវិធី​មើល​​ការ​កំណត់​រចនាសម្ព័ន្ធ​ប៊្លូធូស​ក្នុង​ទូរស័ព្ទ ដើម្បី​ទទួល និង​តភ្ជាប់​ជា​មួយ​ឧបករណ៍​បាន​ផ្គូផ្គង។"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ឲ្យ​កម្មវិធី​ទៅ​យក ពិនិត្យ និង​សម្អាត​ការ​ជូន​ដំណឹង រួមមាន​​ប្រកាស​ដោយ​កម្មវិធី​ផ្សេងៗ។"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ចង​ទៅ​សេវាកម្ម​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ឲ្យ​ម្ចាស់​ចង​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​នៃ​សេវាកម្ម​កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​​ទេ។"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"ភ្ជាប់​ទៅ​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ភ្ជាប់​ទៅ​ចំណុច​ប្រទាក់​កម្រិត​កំពូល​​របស់​សេវាកម្ម​ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ដកហូត​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ដែល​បាន​ផ្ដល់​ដោយ​ក្រុមហ៊ុន​បញ្ជូន"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"អនុញ្ញាត​ឲ្យ​ម្ចាស់​ដក​ហូត​កម្មវិធី​កំណត់​រចនាសម្ព័ន្ធ​ដែល​បាន​ផ្ដល់​ដោយ​ក្រុមហ៊ុន​បញ្ជូន។ មិន​គួរ​ចាំបាច់​សម្រាប់​កម្មវិធី​ធម្មតា​ទេ។"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"សង្កេត​មើល​លើ​លក្ខខណ្ឌ​បណ្ដាញ"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ផ្ទាំង​រូបភាព"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ប្ដូរ​ផ្ទាំង​រូបភាព"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"កម្មវិធី​ស្ដាប់​ការ​ជូន​ដំណឹង"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ក្រុមហ៊ុន​ផ្ដល់​លក្ខខណ្ឌ"</string>
     <string name="vpn_title" msgid="19615213552042827">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"បាន​ធ្វើ​ឲ្យ VPN សកម្ម​ដោយ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ប៉ះ ដើម្បី​គ្រប់គ្រង​បណ្ដាញ។"</string>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index bb26d4f..7c6feba 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;제목 없음&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"동기화"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"<xliff:g id="CONTENT_TYPE">%s</xliff:g> 삭제가 너무 많습니다."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"태블릿 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"시계 저장공간이 가득 찼습니다. 일부 파일을 삭제하여 저장 여유 공간을 늘리세요."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"휴대전화 저장공간이 꽉 찼습니다. 일부 파일을 삭제하여 저장공간을 늘리세요."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"네트워크가 모니터링될 수 있음"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"알 수 없는 제3자의 모니터링"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"벨소리가 켜져 있습니다."</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"종료 중..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"태블릿이 종료됩니다."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"시계가 종료됩니다."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"휴대전화가 종료됩니다."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"종료하시겠습니까?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"안전 모드로 다시 부팅"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"비행기 모드"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"비행기 모드 사용중"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"비행기 모드 사용중이 아님"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"설정"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"안전 모드"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 시스템"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"앱이 활성 창의 콘텐츠를 검색할 수 있도록 허용합니다. 이 경우 악성 앱이 전체 창의 콘텐츠를 검색하여 비밀번호를 제외한 모든 텍스트를 살펴볼 수 있습니다."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"일시적인 접근성 사용"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"애플리케이션이 기기에서 일시적으로 접근성을 사용하도록 허용합니다. 이 경우 악성 앱이 사용자의 동의 없이 접근성을 사용할 수 있습니다."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"창 토큰 검색"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"애플리케이션이 창 토큰을 검색하도록 허용합니다. 악성 앱이 시스템을 가장하여 애플리케이션 창과 무단으로 상호작용할 수 있습니다."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"프레임 통계 검색"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"애플리케이션이 프레임 통계를 수집하도록 허용합니다. 악성 앱이 다른 앱에서 창의 프레임 통계를 볼 수 있습니다."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"일정 필터링"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"애플리케이션에 입력 필터를 등록할 수 있도록 하여 모든 사용자 일정 스트림을 전달하기 전에 필터링합니다. 이 경우 사용자의 개입 없이 악성 앱이 시스템 UI를 제어할 수 있습니다."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"부분 종료"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"앱이 SMS 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 허용합니다. 이 경우 악성 앱이 수신된 SMS 메시지를 위조할 수 있습니다."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-수신 브로드캐스트 보내기"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"앱이 WAP PUSH 메시지를 받았다는 알림을 브로드캐스트할 수 있도록 허용합니다. 이 경우 악성 앱이 MMS 메시지를 받은 것처럼 위장하거나 웹페이지의 콘텐츠를 악성 콘텐츠로 몰래 바꿀 수 있습니다."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"네트워크 점수화 브로드캐스트 전송"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"네트워크를 점수화할 필요가 있다는 알림을 앱이 브로드캐스트할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"실행 중인 프로세스 수 제한"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"앱이 실행할 최대 프로세스 수를 제어할 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"백그라운드 앱 강제 종료"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"권한을 가진 프로그램이 VPN 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"배경화면 연결"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"권한을 가진 프로그램이 배경화면에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"음성 상호작용 서비스 사용"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"권한을 가진 프로그램이 음성 상호작용 서비스의 최상위 인터페이스를 사용하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"원격 디스플레이에 연결"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"권한을 가진 프로그램이 원격 디스플레이에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"위젯 서비스와 연결"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"권한을 가진 프로그램이 위젯 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"경로 제공업체 서비스 사용"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"권한을 가진 프로그램이 등록된 경로 제공업체를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"기기 관리자와 상호 작용"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"권한을 가진 프로그램이 기기 관리자에게 인텐트를 보낼 수 있도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"TV 입력 사용"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"권한을 가진 프로그램이 TV 입력에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"기기 관리자 추가 또는 삭제"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"권한을 가진 프로그램이 활성화된 기기의 관리자를 추가 또는 삭제하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"화면 방향 변경"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"앱이 기기에 저장된 개인 프로필 정보(예: 사용자 이름, 연락처 정보 등)를 읽을 수 있도록 허용합니다. 이는 앱이 사용자를 확인할 수 있으며 다른 사용자에게 해당 프로필 정보를 전송할 수도 있다는 것을 의미합니다."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"나만의 연락처 카드 수정"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"앱이 기기에 저장된 개인 프로필 정보(예: 사용자 이름, 연락처 정보 등)를 변경 또는 추가할 수 있도록 허용합니다. 이는 앱이 사용자를 확인하고 다른 사용자에게 해당 프로필 정보를 전송할 수 있다는 것을 의미합니다."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"신체 센서(예: 심박수 모니터)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"앱이 신체 변화(예: 심박수) 측정을 위해 사용하는 센서의 데이터에 액세스하도록 허용합니다."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"소셜 스트림 읽기"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"앱이 사용자와 친구의 최신 소셜 소식에 액세스하고 동기화할 수 있도록 허용합니다. 이 경우 앱이 비밀유지와 관계 없이 소셜 네트워크에서 사용자와 친구가 주고받는 내용을 읽을 수 있으므로, 정보를 공유할 때 주의해야 합니다. 참고: 이 권한이 적용되지 않는 소셜 네트워크도 있습니다."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"소셜 스트림에 쓰기"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX 상태 변경"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"앱이 태블릿을 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"앱이 휴대전화를 WiMAX 네트워크에 연결하거나 연결을 끊을 수 있도록 허용합니다."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"네트워크 점수화"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"앱이 네트워크 순위를 정하고 태블릿에서 어떤 네트워크를 선호할지 영향을 주도록 허용합니다."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"앱이 네트워크 순위를 정하고 휴대전화에서 어떤 네트워크를 선호할지 영향을 주도록 허용합니다."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"블루투스 기기와 페어링"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"앱이 태블릿의 블루투스 설정을 확인하고 페어링된 기기에 연결하며 연결을 수락할 수 있도록 허용합니다."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"앱이 휴대전화의 블루투스 설정을 확인하고 페어링된 기기에 연결하며 연결을 수락할 수 있도록 허용합니다."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"앱이 다른 앱에서 게시한 알림을 비롯하여 알림을 검색하고 살펴보며 삭제할 수 있도록 허용합니다."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"알림 수신기 서비스 사용"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"권한을 가진 프로그램이 알림 수신기 서비스에 대한 최상위 인터페이스를 사용하도록 허용합니다. 일반 앱에는 필요하지 않습니다."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"조건 제공자 서비스 사용"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"권한을 가진 프로그램이 조건 제공자 서비스의 최상위 인터페이스를 사용하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"이동통신사에서 제공한 구성 앱 호출"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"권한을 가진 프로그램이 이동통신사에서 제공한 구성 앱을 호출하도록 합니다. 일반 앱에는 필요하지 않습니다."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"네트워크 상태에 대한 관측 보고 수신"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"배경화면"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"배경화면 변경"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"알림 수신기"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"조건 제공자"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN이 활성화됨"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN이 <xliff:g id="APP">%s</xliff:g>에 의해 활성화됨"</string>
     <string name="vpn_text" msgid="3011306607126450322">"네트워크를 관리하려면 터치하세요."</string>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/core/res/res/values-land/dimens_quantum.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to core/res/res/values-land/dimens_quantum.xml
index 15d0890..7789219 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/core/res/res/values-land/dimens_quantum.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+<resources>
+
+    <!-- Default height of an action bar. -->
+    <dimen name="action_bar_default_height_quantum">48dp</dimen>
+    <!-- Default padding of an action bar. -->
+    <dimen name="action_bar_default_padding_quantum">0dp</dimen>
+
+</resources>
diff --git a/core/res/res/values-lo-rLA/strings.xml b/core/res/res/values-lo-rLA/strings.xml
index 60b7da4..b31fbff 100644
--- a/core/res/res/values-lo-rLA/strings.xml
+++ b/core/res/res/values-lo-rLA/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ບໍ່ມີຊື່&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ຊິ້ງຂໍ້ມູນ"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"ມີການລຶບ <xliff:g id="CONTENT_TYPE">%s</xliff:g> ຫຼາຍເກີນໄປ."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"ພື້ນທີ່ຈັດເກັບຂໍ້ມູນໃນແທັບເລັດເຕັມ. ລຶບບາງໄຟລ໌ອອກເພື່ອເພີ່ມພື້ນທີ່ຫວ່າງ."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"ບ່ອນ​ຈັດ​ເກັບ​ຂໍ້​ມູນ​ໃນ​ໂມງ​ເຕັມ​ແລ້ວ. ໃຫ້​ລຶບ​ໄຟ​ລ໌​ບາງ​ອັນ​ທີ່ບໍ່​ໄດ້​ໃຊ້​ອອກ​ເພື່ອ​ເພີ່ມ​ເນື້ອ​ທີ່​ຫວ່າງ."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"ພື້ນທີ່ໃນໂທລະສັບເຕັມແລ້ວ. ກະລຸນາລຶບບາງໄຟລ໌ອອກເພື່ອເພີ່ມພື້ນທີ່ຫວ່າງ."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"ການນຳໃຊ້ເຄືອຂ່າຍອາດມີການກວດສອບຕິດຕາມ"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"ໂດຍບຸກຄົນທີສາມທີ່ບໍ່ຮູ້ຈັກ"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"ເປີດສຽງໂທເຂົ້າແລ້ວ"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"ກຳລັງປິດລະບົບລົງ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"ແທັບເລັດຂອງທ່ານຈະຖືກປິດ."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"ໂມງ​ຂອງ​ທ່ານ​ຈະ​ຖືກ​ປິດ​ໄວ້."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"ໂທລະສັບຂອງທ່ານຈະຖືກປິດ."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"ທ່ານຕ້ອງການທີ່ຈະປິດບໍ່?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"ຣີບູດເຂົ້າ safe mode"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"ໂໝດໃນຍົນ"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ເປີດໂໝດຢູ່ໃນຍົນແລ້ວ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"ປິດໂໝດໃນຍົນແລ້ວ"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"​ການ​ຕັ້ງ​ຄ່າ"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ລະບົບ Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນເນື້ອຫາຂອງໜ້າຈໍທີ່ໃຊ້ຢູ່ໄດ້. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດດຶງຂໍ້ມູນທັງໝົດໃນໜ້າຈໍ ແລະກວດສອບຂໍ້ຄວາມທັງໝົດໃນນັ້ນໄດ້ ຍົກເວັ້ນລະຫັດຜ່ານ."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ປິດການຊ່ວຍການເຂົ້າເຖິງຊົ່ວຄາວ"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ເປີດໃຊ້ການຊ່ວຍເຂົ້າເຖິງແບບຊົ່ວຄາວໃນອຸປະກອນ. ແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດເປີດໃຊ້ການຊ່ວຍເຂົ້າເຖິງ ໂດຍບໍ່ໄດ້ຮັບການຍິນຍອມຈາກຜູ່ໃຊ້."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"​ດຶງ​ຂໍ້​ມູນ​ໂທ​ເຄນ​ໜ້າ​ຈໍ"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ດຶງ​ຂໍ້​ມູນ​ໂທ​ເຄນ​ຂອງ​ໜ້າ​ຈໍ​ໄດ້. ແອັບຯ​ທີ່​ເປັນ​ອັນ​ຕະ​ລາຍ​ອາດ​ດຳ​ເນີນ​ການ​ຕິດ​ຕໍ່​ທີ່ບໍ່​ໄດ້​ຮັບ​ອະ​ນຸ​ຍາດ​ກັບ​ໜ້າ​ຈໍ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ເພື່ອ​ຮຽນ​ແບບ​ລະ​ບົບ."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"ດຶງ​ຂໍ້​ມູນ​ສະ​ຖິ​ຕິ​ເຟ​ຣມ"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບ​ພ​ລິ​ເຄ​ຊັນ​ສາ​ມາດ​ສະ​ສົມ​ສະ​ຖິ​ຕິ​ເຟ​ຣມ​ໄດ້. ແອັບຯ​ທີ່​ເປັນ​ອັນ​ຕະ​ລາຍ​ອາດ​ສັງ​ເກດ​ສະ​ຖິ​ຕິ​ເຟ​ຣມ​ຂອງ​ໜ້າ​ຈໍ​ຕ່າງໆ​ຈາກ​ແອັບຯ​ອື່ນ​ໄດ້."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"ກັ່ນຕອງເຫດການ"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"ອະນຸຍາດໃຫ້ແອັບພລິເຄຊັນ ລົງທະບຽນການກັ່ນຕອງຂາເຂົ້າ ທີ່ກັ່ນຕອງການສົ່ງຂໍ້ມູນເຫດການຜູ່ໃຊ້ທັງໝົດ ກ່ອນທີ່ພວກມັນຈະຖືກເຜີຍແຜ່. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດຄວບຄຸມ UI ຂອງລະບົບໂດຍບໍ່ຕ້ອງໃຫ້ຜູ່ໃຊ້ຈັດການໄດ້."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ປິດລົງບາງສ່ວນ"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"ອະນຸຍາດໃຫ້ແອັບຯ ກະຈາຍສັນຍານການແຈ້ງເຕືອນວ່າຂໍ້ຄວາມ SMS ໄດ້ຮັບແລ້ວ. ແອັບຯທີ່ເປັນອັນຕະລາຍອາດຈະໃຊ້ສິ່ງນີ້ໃນການປອມແປງຂໍ້ຄວາມ SMS ຂາເຂົ້າ."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ສົ່ງການກະຈາຍ WAP-PUSH ທີ່ໄດ້ຮັບ"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"ອະນຸຍາດໃຫ້ແອັບຯສົ່ງການແຈ້ງເຕືອນໃນເວລາທີ່ໄດ້ຮັບຂໍ້ມຄວາມ WAP PUSH. ແອັບຯທີ່ເປັນອັນຕະລາຍ ອາດໃຊ້ການກະທຳນີ້ເພື່ອປອມການໄດ້ຮັບຂໍ້ຄວາມ MMS ຫຼືລັກປ່ຽນເນື້ອຫາຂອງໜ້າເວັບຕ່າງໆ ດ້ວຍສິ່ງອັນຕະລາຍທັງຫຼາຍຢ່າງງຽບໆ."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"​ສົ່ງ​ການ​ກະ​ຈາຍ​ຄະແນນ​ເຄືອ​ຂ່າຍ"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ກະ​ຈາຍ​ການ​ແຈ້ງ​ເຕືອນທີ່​ເຄືອ​ຂ່າຍຕ່າງໆ​ຈຳ​ເປັນ​ຖືກໃຊ້​ນັບ​​ຄະ​ແນນ. ບໍ່​ມີຄວາມ​ຈຳ​ເປັນ​ໃນ​ແອັບຯ​ທົ່ວ​ໄປ."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ຈຳກັດຈຳນວນຂອງໂປຣເຊສທີ່ເຮັດວຽກຢູ່"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"ອະນຸຍາດໃຫ້ແອັບຯຄວບຄຸມຈຳນວນສູງສຸດ ຂອງໂປຣເຊສທີ່ຈະເຮັດວຽກ. ບໍ່ຄວນຖືກໃຊ້ກັບແອັບພລິເຄຊັນທົ່ວໄປ."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"ບັງຄັບໃຫ້ແອັບຯທີ່ເຮັດວຽກຢູ່ພື້ນຫຼັງປິດໂຕລົງ"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງບໍລິການ VPN. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ເຊື່ອມໂຍງກັບພາບພື້ນຫຼັງ"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"ອະນຸຍາດໃຫ້ຜູ່ໃຊ້ເຊື່ອມໂຍງກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງພາບພື້ນຫຼັງໃດນຶ່ງ. ແອັບຯທຳມະດາບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ຜູກກັນເພື່ອສະແດງຜົນທາງໄກ."</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບສ່ວນຕິດຕໍ່ລະດັບສູງສຸດ ຂອງການສະແດງຜົນທາງໄກ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"ເຊື່ອມໂຍງໄປຫາບໍລິການວິດເຈັດ"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"ອະນຸຍາດໃຫ້ຜູ່ຖືຜູກກັບອິນເຕີເຟດລະດັບສູງສຸດ ຂອງບໍລິການວິເຈັດ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"ເຊື່ອມ​ໂຍງ​ກັບ​ການ​ບໍ​ລິ​ການ​ຂອງ​ຜູ່​ໃຫ້​ບໍ​ລິ​ການ​ເສັ້ນ​ທາງ"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"ອະ​ນຸ​ຍາດ​ໃຫ້​ເຈົ້າ​ຂອງ​ສາ​ມາດ​ເຊື່ອມ​ໂຍງກັບ​ທຸກໆ​ຜູ່​ໃຫ້​ບໍ​ລິ​ການເສັ້ນ​ທາງ​ທີ່​ລົງ​ທະ​ບຽນ. ບໍ່​ຄວນ​ຈະ​ໄດ້​ໃຊ້​ໃນ​ແອັບຯ​ທົ່ວ​ໄປ."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ຕິດຕໍ່ກັບຜູ່ເບິ່ງແຍງອຸປະກອນ"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສົ່ງເຈດຕະນາຫາຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ. ແອັບຯທົ່ວໄປບໍ່ຄວນຈຳເປັນຕ້ອງໃຊ້."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ຜູກ​ກັບ​ການ​ປ້ອນ​ຂໍ້​ມູນ​ເຂົ້າ​ໂທ​ລະ​ທັດ"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"​ອະ​ນຸ​ຍາດ​ໃຫ້​ຜູ່​ຖື​ຜູກ​ຕິດ​ກັບ​ສ່ວ​ນ​ຕິດ​ຕໍ່​ລະ​ດັບ​ສູງ​ສຸດ​ຂອງ​ການ​ປ້ອນ​ຂໍ້​ມູນ​ເຂົ້າ​ໂທ​ລະ​ທັດ. ແອັບຯ​ທົ່ວ​ໄປ​ບໍ່​ຄວນ​ຈຳ​ເປັນ​ຕ້ອງ​ໃຊ້."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ເພີ່ມ ຫຼືລຶບຜູ່ເບິ່ງແຍງລະບົບອຸປະກອນ"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງສາມາດລຶບ ຫຼືລຶບຂໍ້ມູນອຸປະກອນທີ່ນຳໃຊ້ໄດ້. ແອັບຯທົ່ວໄປບໍ່ຈຳເປັນຕ້ອງໃຊ້."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ປ່ຽນລວງຂອງໜ້າຈໍ"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"ອະນຸຍາດໃຫ້ແອັບຯ ອ່ານຂໍ້ມູນໂປໄຟລ໌ສ່ວນໂຕໃນອຸປະກອນຂອງທ່ານເຊັ່ນ: ຊື່ຂອງທ່ານ ແລະຂໍ້ມູນການຕິດຕໍ່ຂອງທ່ານ. ນີ້ໝາຍຄວາມວ່າແອັບຯຈະສາມາດລະບຸໂຕຕົນຂອງທ່ານ ແລະສົ່ງຂໍ້ມູນໂປຣໄຟລ໌ຂອງທ່ານໃຫ້ຜູ່ອື່ນໄດ້."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"ແກ້ໄຂບັດລາຍຊື່ຜູ່ຕິດຕໍ່ຂອງທ່ານເອງ"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"ອະນຸຍາດໃຫ້ແອັບຯ ປ່ຽນແປງ ຫຼືເພີ່ມຂໍ້ມູນໃສ່ໂປຣໄຟລ໌ສ່ວນບຸກຄົນທີ່ເກັບໄວ້ໃນອຸປະກອນຂອງທ່ານ, ເຊັ່ນ: ຊື່ ແລະຂໍ້ມູນຕິດຕໍ່ທ່ານ. ນີ້ໝາຍຄວາມວ່າແອັບຯສາມາດບົ່ງບອກໂຕທ່ານ ແລະອາດສົ່ງຂໍ້ມູນໂປຣໄຟລ໌ຂອງທ່ານໃຫ້ຜູ່ອື່ນໄດ້."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"ເຊັນ​ເຊີ​​ຮ່າງ​ກາຍ (ເຊັ່ນ: ​ຕິດ​ຕາມ​ອັດ​ຕາ​ການ​ເຕັ້ນ​ຂອງ​ຫົວ​ໃຈ)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ເຂົ້າ​ເຖິງ​ຂໍ້​ມູນ​ຈາກ​ເຊັນ​ເຊີ​ທີ່​ທ່ານ​ໃຊ້​ເພື່ອ​ວັດ​ແທກ​ສິ່ງ​ທີ່​ເກີດ​ຂຶ້ນ​ໃນ​ຮ່າງ​ກາຍ​ຂອງ​ທ່ານ ເຊັ່ນ: ອັດ​ຕາ​ການ​ເຕັ້ນ​ຂອງ​ຫົວ​ໃຈ."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ອ່ານການອັບເດດສັງຄົມອອນລາຍຂອງທ່ານ"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"ອະນຸຍາດໃຫ້ແອັບຯ ເຂົ້າເຖິງ ແລະຊິ້ງຂໍ້ມູນຂ່າວສານສັງຄົມຈາກທ່ານ ແລະໝູ່ຂອງທ່ານ. ຄວນລະມັດລະວັງໃນເວລາທີ່ແລກປ່ຽນຂໍ້ມູນ -- ນີ້ຈະເປັນການອະນຸຍາດໃຫ້ແອັບຯ ອ່ານການສື່ສານລະຫວ່າງທ່ານ ກັບໝູ່ຂອງທ່ານເທິງເຄືອຂ່າຍສັງຄົມ ໂດຍບໍ່ຄຳນຶງເຖິງຄວາມລັບ. ໝາຍເຫດ: ການກຳນົດສິດນີ້ອາດບໍ່ໄດ້ບັງຄັບໃຊ້ໃນທຸກເຄືອຂ່າຍສັງຄົມ."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ຂຽນໃສ່ເຄືອຂ່າຍສັງຄົມຂອງທ່ານ"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"ປ່ຽນສະຖານະ WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ແທັບເລັດຈາກເຄືອຂ່າຍ WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"ອະນຸຍາດໃຫ້ແອັບຯເຊື່ອມຕໍ່ ແລະຕັດການເຊື່ອມຕໍ່ຂອງໂທລະສັບຈາກເຄືອຂ່າຍ WiMax ໄດ້."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ຄະແນນ​ເຄືອ​ຂ່າຍ"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ຈັດ​ລຳ​ດັບ​ເຄືອ​ຂ່າຍ ແລະ ຊ່ວຍ​ຕັດ​ສິນ​ໃຈ​ວ່າ​ເຄືອ​ຂ່າຍ​ໃດ​ທີ່​​ແທັບ​ເລັດ​ຄວນ​ນຳ​ໃຊ້."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"ອະ​ນຸ​ຍາດ​ໃຫ້​ແອັບຯ​ຈັດ​ລຳ​ດັບ​ເຄືອ​ຂ່າຍ ແລະ ຊ່ວຍ​ຕັດ​ສິນ​ໃຈ​ວ່າ​ເຄືອ​ຂ່າຍ​ໃດ​ທີ່​ໂທ​ລະ​ສັບ​ຄວນ​ນຳ​ໃຊ້."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ຈັບຄູ່ກັບອຸປະກອນ Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນແທັບເລັດ ຕະຫຼອດຈົນເຊື່ອມຕໍ່ ແລະຍອມຮັບການເຊື່ອມຕໍ່ກັບອຸປະກອນທີ່ຈັບຄູ່ກັນແລ້ວ."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"ອະນຸຍາດໃຫ້ແອັບຯເບິ່ງການຕັ້ງຄ່າຂອງ Bluetooth ໃນໂທລະສັບ, ຮວມທັງໃຫ້ສ້າງ ແລະຮັບການເຊື່ອມຕໍ່ຈາກອຸປະກອນທີ່ຈັບຄູ່ກັນ."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ອະນຸຍາດໃຫ້ແອັບຯດຶງຂໍ້ມູນ, ກວດສອບ ແລະລຶບລ້າງການແຈ້ງເຕືອນ ຮວມທັງພວກທີ່ໂພສໂດຍແອັບຯອື່ນໆນຳ."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ເຊື່ອມໂຍງກັບບໍລິການໂຕຟັງການແຈ້ງເຕືອນ"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"ອະນຸຍາດໃຫ້ເຈົ້າຂອງເຊື່ອມໂຍງສ່ວນຕິດຕໍ່ລະດັບເທິງສຸດ ຂອງຜູ່ຟັງບໍລິການການແຈ້ງເຕືອນ. ບໍ່ຈຳເປັນສຳລັບແອັບຯທົ່ວໄປ."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"ຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"ອະ​ນຸ​ຍາດ​ໃຫ້​ເຈົ້າຂອງຮ້ອງຂໍແອັບຯປັບຄ່າທີ່ສະໜອງໂດຍຜູ່ໃຫ້ບໍລິການ. ບໍ່ໜ້າຈະຕ້ອງການສຳລັບແອັບຯທົ່ວໄປ."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ຕິດຕາມເພື່ອສັງເກດສະພາບຂອງເຄືອຂ່າຍ"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"ພາບພື້ນຫຼັງ"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"ປ່ຽນພາບພື້ນຫຼັງ"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ໂຕຟັງການແຈ້ງເຕືອນ"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"ເປີດນຳໃຊ້ VPN ແລ້ວ"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"ເປີດໃຊ້ VPN ໂດຍ <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"ແຕະເພື່ອຈັດການເຄືອຂ່າຍ."</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index b40e10b..62b6c7a 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Be pavadinimo&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinchronizuoti"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Per daug <xliff:g id="CONTENT_TYPE">%s</xliff:g> trynimo."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Planšetinio kompiuterio atmintis pilna. Kad atlaisvintumėte vietos, ištrinkite kelis failus."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Laikrodžio saugykla pilna. Ištrinkite kelis failus, kad atlaisvintumėte vietos."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefono atmintis pilna. Ištrinkite kai kuriuos failus, kad atlaisvintumėte vietos."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Tinklas gali būti stebimas"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Nežinoma trečioji šalis"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Skambutis įjungtas"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Išsijungia..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetinio kompiuterio veikimas bus sustabdytas."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Laikrodis išsijungs."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonas bus išjungtas."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Ar norite išjungti?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Iš naujo įkelti operacinę sistemą saugos režimu"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"ĮJUNGTAS lėktuvo režimas"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"lėktuvo režimas IŠJUNGTAS"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Nustatymai"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Saugos režimas"</string>
     <string name="android_system_label" msgid="6577375335728551336">"„Android“ sistema"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Leidžiama programai nuskaityti aktyvaus lango turinį. Kenkėjiškos programos gali bandyti išgauti viso lango turinį ir tirti visą jo tekstą, išskyrus slaptažodžius."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"laikinai įgalinti pritaikymą neįgaliesiems"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Leidžiama programai laikinai įgalinti pritaikymą neįgaliesiems įrenginyje. Kenkėjiškos programos pritaikymą neįgaliesiems gali įgalinti be naudotojo sutikimo."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"gauti lango prieigos raktą"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Programai leidžiama gauti lango prieigos raktą. Kenkėjiškos programos gali vykdyti neteisėtą sąveiką su programos langu mėgdžiodamos sistemą."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"gauti kadrų statistinius duomenis"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Programai leidžiama rinkti kadrų statistinius duomenis. Kenkėjiškos programos gali stebėti kadrų statistinius duomenis iš kitų programų langų."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrų įvykiai"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Leidžiama programai registruoti įvesties filtrą, kuriuo filtruojamas visų naudotojo įvykių srautas prieš juos išsiunčiant. Kenkėjiška programa gali kontroliuoti sistemos naudotojo sąsają be naudotojo įsikišimo."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"dalinis išjungimas"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Leidžiama programai pateikti pranešimą, kad buvo gautas SMS pranešimas. Kenkėjiškos programos gali tai naudoti, kad klastotų gaunamuosius SMS pranešimus."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"siųsti „WAP-PUSH-received“ perdavimą"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Leidžiama programai pateikti pranešimą, kai gaunamas WAP PUSH pranešimas. Kenkėjiškos programos gali tai naudoti, kad klastotų MMS pranešimo gavimą ar kad nepastebimai pakeistų bet kurio tinklalapio turinį kenkėjiškais variantais."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"siųsti tinklų transliavimo įvertinimą"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Programai leidžiama transliuoti pranešimą, kad reikia įvertinti tinklus. Niekada nereikia įprastoms programoms."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"riboti vykdomų procesų skaičių"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Leidžiama programai valdyti didžiausią vykdomų procesų skaičių. Nereikalinga įprastoms programoms."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"priverstinai uždaryti fonines programas"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Leidžiama savininkui susisaistyti su aukščiausio lygio VPN paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"susaistyti su darbalaukio fonu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Leidžiama savininką susaistyti su aukščiausio lygio darbalaukio fono sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"susaistyti su sąveikos balsu priemone"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Turėtojui leidžiama susaistyti programą su sąveikos balsu paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to niekada neturėtų prireikti."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"susisaistyti su nuotoliniu ekranu"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Leidžiama savininkui susisaistyti su aukščiausiojo lygio nuotolinio ekrano sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"susaistyti su valdiklio paslauga"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Leidžiama savininkui susisaistyti su aukščiausio lygio valdiklio paslaugos sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"susisaistyti su maršruto parinkimo paslauga"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Savininkui leidžiama susisaistyti su bet kokiomis registruotomis maršrutų parinkimo paslaugomis. To niekada neturėtų prireikti naudojant įprastas programas."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"sąveikauti su įrenginio administratoriumi"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Leidžiama savininkui siųsti tikslus įrenginio administratoriui. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"susisaistyti su TV įvestimi"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Leidžiama savininkui susisaistyti su aukščiausio lygio TV įvesties sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridėti arba pašalinti įrenginio administratorių"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Savininkui leidžiama pridėti aktyvių įrenginio administratorių arba juos pašalinti. Neturėtų reikėti įprastoms programoms."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"keisti ekrano padėtį"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Programai leidžiama skaityti įrenginyje saugomą asmeninę profilio informaciją, pvz., vardą, pavardę ir kontaktinę informaciją. Tai reiškia, kad programa gali nustatyti tapatybę ir siųsti profilio informaciją kitiems."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"keisti jūsų kontaktinę kortelę"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Leidžiama programai keisti įrenginyje saugomą asmeninę profilio informaciją, pvz., vardą, pavardę ir kontaktinę informaciją, arba jos pridėti. Tai reiškia, kad programa gali nustatyti tapatybę ir siųsti profilio informaciją kitiems."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kūno jut. (pvz., pulso d. t.)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Programai leidžiama pasiekti naudojamų jutiklių duomenis, siekiant įvertinti, kas vyksta jūsų kūne, pvz., pulso dažnį."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"skaityti socialinį srautą"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Leidžiama programai pasiekti ir sinchronizuoti viešas naujienas iš jūsų ir jūsų draugų. Būkite atidūs bendrindami informaciją – programai leidžiama skaityti korespondenciją tarp jūsų ir draugų viešuosiuose tinkluose, neatsižvelgiant į konfidencialumą. Pastaba: šis leidimas negali būti taikomas visuose viešuosiuose tinkluose."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"rašyti į socialinį srautą"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Keisti „WiMAX“ būseną"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Leidžia programai prijungti planšetinį kompiuterį prie „WiMAX“ ryšio tinklų ir nuo jų atjungti."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Leidžia programai prijungti telefoną prie „WiMAX“ ryšio tinklų ir nuo jų atjungti."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"įvertinti tinklus"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Programai leidžiama įvertinti tinklus ir nustatyti, kuriems tinklams planšetiniame kompiuteryje turėtų būti taikoma pirmenybė."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Programai leidžiama įvertinti tinklus ir nustatyti, kuriems tinklams telefone turėtų būti taikoma pirmenybė."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"susieti su „Bluetooth“ įrenginiais"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją planšetiniame kompiuteryje ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Leidžiama programai peržiūrėti „Bluetooth“ konfigūraciją telefone ir užmegzti bei priimti ryšius iš susietų įrenginių."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Programai leidžiama gauti, patikrinti ir išvalyti pranešimus, įskaitant pranešimus, kuriuos paskelbė kitos programos."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"susisaistyti su pranešimų skaitymo priemonės paslauga"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Leidžiama turėtojui susisaistyti su pranešimų skaitymo priemonės paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to neturėtų prireikti."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"susaistyti su sąlygos teikėjo paslauga"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Turėtojui leidžiama susaistyti programą su sąlygos teikėjo paslaugos aukščiausio lygio sąsaja. Įprastoms programoms to niekada neturėtų prireikti."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"iškviesti operatoriaus pateiktą konfigūravimo programą"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Turėtojui leidžiama iškviesti operatoriaus pateiktą konfigūravimo programą. Įprastoms programoms to neturėtų prireikti."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"vykdyti tinklo sąlygų stebėjimą"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Darbalaukio fonas"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Keisti darbalaukio foną"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pranešimų skaitymo priemonė"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Sąlygos teikėjas"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN suaktyvintas"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN suaktyvino „<xliff:g id="APP">%s</xliff:g>“"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Palieskite, kad valdytumėte tinklą."</string>
diff --git a/core/res/res/values-lv/strings.xml b/core/res/res/values-lv/strings.xml
index 6b91a6d..b803e61 100644
--- a/core/res/res/values-lv/strings.xml
+++ b/core/res/res/values-lv/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nosaukuma&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizācija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Pārāk daudz <xliff:g id="CONTENT_TYPE">%s</xliff:g> dzēsto vienumu."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Planšetdatora atmiņa ir pilna. Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Pulksteņa atmiņa ir pilna. Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Tālruņa atmiņa ir pilna! Dzēsiet dažus failus, lai atbrīvotu vietu."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Iespējams, tīklā veiktās darbības tiek pārraudzītas."</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Nezināma trešā puse"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Zvanītājs ieslēgts"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Notiek izslēgšana..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Planšetdators tiks beidzēts."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Pulkstenis tiks izslēgts."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Tālrunis tiks izslēgts."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vai vēlaties izslēgt?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Atsāknēšana drošajā režīmā"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Lidojuma režīms"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Lidojuma režīms ir IESLĒGTS."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Lidojuma režīms ir IZSLĒGTS."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Iestatījumi"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"Pārsniedz"</string>
     <string name="safeMode" msgid="2788228061547930246">"Drošais režīms"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android sistēma"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ļauj lietotnei izgūt aktīva loga saturu. Ļaunprātīgas lietotnes var izgūt visu loga saturu un pārbaudīt visu tā tekstu, izņemot paroles."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Īslaicīga pieejamības režīma iespējošana"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ļauj lietojumprogrammai īslaicīgi ierīcē iespējot pieejamības režīmu. Ļaunprātīgas lietotnes var iespējot pieejamības režīmu bez lietotāja atļaujas."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"Loga marķiera izgūšana"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Ļauj lietojumprogrammai izgūt loga marķieri. Ļaunprātīgas lietotnes var veikt neautorizētas darbības ar lietojumprogrammas logu, izliekoties par attiecīgo sistēmu."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"Ietvaru statistikas izgūšana"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Ļauj lietojumprogrammai apkopot ietvaru statistiku. Ļaunprātīgas lietotnes var iegūt logu ietvaru statistiku no citām lietotnēm."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"Filtrēt notikumus"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Ļauj lietojumprogrammai reģistrēt ieejas filtru, kas filtrē visu lietotāja notikumu straumi, pirms notikumi tiek nosūtīti. Ļaunprātīga lietotne var kontrolēt sistēmas lietotāja saskarni, nejautājot lietotājam."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"daļēja izslēgšana"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ļauj lietotnei pārraidīt paziņojumu par saņemtu īsziņu. Ļaunprātīgas lietotnes to var izmantot, lai viltotu ienākošas īsziņas."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"sūtīt WAP-PUSH-saņemto apraidi"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ļauj lietotnei pārraidīt paziņojumu par to, ka ir saņemts WAP PUSH ziņojums. Ļaunprātīgas lietotnes to var izmantot, lai viltotu multiziņas saņemšanu vai jebkuras tīmekļa lapas saturu nemanāmi nomainītu ar ļaunprātīgiem variantiem."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"apraidīt ziņojumu par tīklu vērtēšanu"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ļauj lietotnei apraidīt paziņojumu, ka tīkli ir jānovērtē. Parastām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ierobežot aktīvo procesu skaitu"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ļauj lietotnei kontrolēt izpildāmo procesu maksimālo skaitu. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"veikt fonā darbojošos lietotņu piespiedu aizvēršanu"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ļauj īpašniekam izveidot saiti ar VPN pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"saistīt ar tapeti"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ļauj īpašniekam piesaistīt tapetes augstākā līmeņa lietotāja saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"Saistīšana ar balss mijiedarbības elementu"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ļauj īpašniekam izveidot savienojumu ar balss mijiedarbības pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Saites izveide ar attālu displeju"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ļauj īpašniekam izveidot saiti ar attāla displeja augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"saistīt ar logrīka pakalpojumu"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ļauj īpašniekam izveidot saiti ar logrīka pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Saistīšana ar maršruta nodrošinātāja pakalpojumu"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ļauj īpašniekam saistīt jebkādus reģistrētus maršrutēšanas nodrošinātājus. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"mijiedarboties ar ierīces administratoru"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ļauj īpašniekam nosūtīt informāciju par nodomiem ierīces administratoram. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"Izveidot saiti ar TV ieeju"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ļauj īpašniekam izveidot saiti ar TV ieejas augšējā līmeņa saskarni. Parastām lietotnēm šī atļauja nekad nav nepieciešama."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pievienot vai noņemt ierīces administratoru"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ļauj īpašniekam pievienot vai noņemt aktīvos ierīces administratorus. Nekad nav nepieciešama parastām lietotnēm."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"mainīt ekrāna orientāciju"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Ļauj lietotnei lasīt ierīcē saglabāto personīgā profila informāciju, piemēram, jūsu vārdu un kontaktinformāciju. Tas nozīmē, ka lietotne var jūs identificēt un var nosūtīt jūsu profila informāciju citām personām."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"mainīt manu vizītkarti"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ļauj lietotnei mainīt ierīcē saglabāto personīgā profila informāciju, piemēram, jūsu vārdu un kontaktinformāciju, vai pievienot tai citu informāciju. Tas nozīmē, ka lietotne var jūs identificēt un var nosūtīt jūsu profila informāciju citām personām."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"ķermeņa sensori (piemēram, sirdsdarbības monitori)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ļauj lietotnei piekļūt to sensoru datiem, kurus izmantojat, lai novērtētu ķermeņa procesus, piemēram, sirdsdarbību."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lasīt jūsu soc. tīklu straumi"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ļauj lietotnei piekļūt sociālajiem atjauninājumiem no jums un jūsu draugiem un sinhronizēt tos. Esiet piesardzīgs, kad kopīgojat informāciju, — šādi lietotne var lasīt sociālajos tīklos ar draugiem veikto saziņu, neraugoties uz konfidencialitāti. Piezīme: šo atļauju nedrīkst piemērot visiem sociālajiem tīkliem."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"rakstīt sociālo tīklu straumē"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX statusa mainīšana"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ļauj lietotnei izveidot un pārtraukt planšetdatora savienojumu ar WiMAX tīkliem."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ļauj lietotnei izveidot un pārtraukt tālruņa savienojumu ar WiMAX tīkliem."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"vērtēt tīklus"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ļauj lietotnei ranžēt tīklus un ietekmēt to, kuriem tīkliem planšetdators dos priekšroku."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ļauj lietotnei ranžēt tīklus un ietekmēt to, kuriem tīkliem tālrunis dos priekšroku."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"savienot pārī ar Bluetooth ierīcēm"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ļauj lietotnei skatīt Bluetooth konfigurāciju planšetdatorā, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ļauj lietotnei skatīt Bluetooth konfigurāciju tālrunī, kā arī veidot un pieņemt savienojumus ar pārī savienotām ierīcēm."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ļauj lietotnei izgūt, pārbaudīt un dzēst paziņojumus, tostarp lietotņu publicētos paziņojumus."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"saites izveidošana ar paziņojumu uztvērēja pakalpojumu"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ļauj īpašniekam izveidot saiti ar paziņojumu uztvērēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Saistīšana ar nosacījumu sniedzēja pakalpojumu"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ļauj īpašniekam izveidot savienojumu ar drukas nosacījumu sniedzēja pakalpojuma augšējā līmeņa saskarni. Parastajām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Operatora nodrošinātas konfigurācijas lietotnes izsaukšana"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ļauj īpašniekam izsaukt operatora nodrošināto konfigurācijas lietotni. Parastām lietotnēm tas nekad nav nepieciešams."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"iegūt informāciju par tīkla stāvokļa novērojumiem"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Fona tapete"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tapetes maiņa"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Paziņojumu uztvērējs"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nosacījumu sniedzējs"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ir aktivizēts."</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Lietojumprogramma <xliff:g id="APP">%s</xliff:g> aktivizēja VPN."</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pieskarieties, lai pārvaldītu tīklu."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index ea1baa1..cc0fa7f 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Гарчиггүй&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синк"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Хэт олон <xliff:g id="CONTENT_TYPE">%s</xliff:g> устгах."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Таблетийн сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Цагны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Утасны сан дүүрсэн. Зай чөлөөлөх бол зарим файлыг устгана уу."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Сүлжээ хянагдаж байж болзошгүй"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Тодорхойгүй гуравдагч талаас"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Хонх ассан"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Унтрааж байна…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таны таблет унтрах болно."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Таны цаг унтрах болно."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Таны утас унтрах болно."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Та унтраах уу?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Аюулгүй горимоор дахин асаах"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Нислэгийн горим"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Нислэгийн горим асав"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Нислэгийн горим унтарсан"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Тохиргоо"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Аюулгүй горим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Андройд систем"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Апп нь идэвхтэй цонхны контентыг авах боломжтой. Хортой апп нь цонхны контентыг бүхэлд авах болон нууц үгнээс бусад бүх текстийг шалгаж болзошгүй"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Хялбар байдлыг түр идэвхтэй болгох"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Аппликешн нь төхөөрөмжийн хялбар байдлыг түр зуур идэвхжүүлэх боломжтой. Хортой апп нь хэрэглэгчийн зөвшөөрөлгүйгээр хялбар байдлыг идэвхжүүлж болзошгүй."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"цонхны токен авах"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Аппликешнд цонхны токен авах боломж олгоно. Хорлонтой апп-ууд системийн өмнөөс аппликешны цонхтой зөвшөөрөлгүйгээр харилцах боломжтой."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"фреймын статистик авах"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Аппликешнд фреймын статистикыг цуглуулах боломж олгоно. Хорлонтой апп-ууд виндовсын фреймын статистикыг өөр апп-с хянах боломжтой."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"үйл явдлыг шүүх"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Аппликешн нь хэрэглэгчийн бүх үйл явдалын илгээгдэхээс өмнөх урсгалыг шүүж байгаа оролтын шүүлтйиг бүртгэх боломжтой. Хортой апп нь хэрэглэгчийн интервэшнгүйгээр системийн UI-г удирдах боломжтой."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"хэсэгчилсэн унтраалт"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Апп нь SMS мессеж хүлээн авсан талаарх мэдэгдлийг өргөн дамжуулах боломжтой. Хортой апп энийг ашиглан ирсэн SMS мессежийг хуурамчаар хийх боломжтой."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH-хүлээн авав өргөн дамжууллыг илгээх"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Аппликешн нь WAP PUSH мессеж хүлээж авсан мэдэгдлийг өргөн дамжуулах боломжтой. Хортой апп нь энийг ашиглан MMS мессеж хүлээн авсан гэж хуурамчаар мэдэгдэх эсвэл хортой хувьсагч агуулсан веб хуудасны контентыг чимээгүй орлуулах боломжтой."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"бүртгэгдсэн сүлжээнүүд рүү түгээх"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Апп-д сүлжээнүүдэд бүртгэгдсэн байх шаардлагатай мэдэгдлийг түгээх боломжийг олгоно. Энгийн апп-д хэзээ ч шаардагдахгүй."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ажиллаж байгаа процессийн тоог хязгаарлах"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Апп нь нэг зэрэг ажиллах процессийн тооны дээд утгыг удирдах боломжтой. Энгийн апп-д хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"арын апп-г хүчээр хаах"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Эзэмшигч нь VPN үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"ханын зурагтай холбох"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Эзэмшигч нь ханын зурагны дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-уудад шаардлагагүй."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"дуугаар харьцагчтай холбох"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Эзэмшигчид дуугаар харьцах үйлчилгээний дээд-түвшний интерфейстэй холбох боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"алсын дэлгэцтэй холбогдох"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Эзэмшигчид алсын дэлгэц дэх дээд давхаргын интерфэйстэй холбогдох боломж олгоно. Энгийн апп-д шаардагдахгүй."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"виджет үйлчилгээтэй холбох"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Эзэмшигч нь виджет үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"маршрут нийлүүлэгчийн үйлчилгээтэй холбогдох"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Эзэмшигчид бүртгэгдсэн маршрут нийлүүлэгчтэй холбогдох  боломж олгоно. Энгийн апп-уудад хэзээ ч шаардагдахгүй."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"төхөөрөмжийн админтай харилцан үйлчлэх"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Эзэмшигч нь төхөөрөмжийн админруу интент илгээх боломжтой. Энгийн апп-д шаардлагагүй."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ТВ оролт холбох"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Эзэмшигч нь ТВ оролтын дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"төхөөрөмжийн админ нэмэх, хасах"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Эзэмшигч нь идэвхтэй төхөөрөмжийн администраторыг нэмэх, хасах боломжтой. Энгийн апп-д шаардлагагүй."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"дэлгэцний чиглэлийг солих"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Апп нь таны нэр болон холбоо барих мэдээлэл зэрэг таны утсан дээр хадгалагдсан хувийн профайл мэдээллийг унших боломжтой. Ингэснээр апп нь танийг таньж чадах ба таны профайл мэдээллийг бусдад илгээх боломжтой."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"та өөрийн харилцагчийн картыг өөрчлөх"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Апп нь таны нэр болон холбоо барих мэдээлэл зэрэг таны төхөөрөмж дээр хадгалагдсан хувийн профайл мэдээллийг солих эсвэл нэмэх боломжтой. Ингэснээр апп нь танийг таньж чадах ба таны профайл мэдээллийг бусдад илгээх боломжтой."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"биеийн сенсор (зүрхний цохилт хянагч гэх мэт)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Зүрхний цохилт гэх мэт биеийн үзүүлэлт хэмждэг сенсоруудын дата-д хандалт хийх боломжийг апп-д олгоно."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"таны нийтийн урсгалаас унших"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Апп нь та болон таны найзуудын нийтийн шинэчлэлтэд хандах болон синк хийх боломжтой. Мэдээлэл хуваалцахдаа болгоомжтой байна уу - энэ нь апп-д нийтийн сүлжээндэх та болон таны найзууд хоорондын холбоог нууц эсэхээс үл хамааран унших боломжтой. Анхаар: энэ зөвшөөрөл нь бүх нийтийн сүлжээнд ашиглаж боломжгүй."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Таны нийтийн урсгалруу бичих"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX статусыг өөрчлөх"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Апп нь WiMAX сүлжээнд таблетыг холбох болон салгах боломжтой."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Апп нь WiMAX сүлжээнд утсыг холбох болон салгах боломжтой."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"бүртгэгдсэн сүлжээ"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Апп-д сүлжээнүүдийг эрэмбэлж, аль сүлжээнд таблетыг холбоход нөлөөлөх боломж олгоно."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Апп-д сүлжээнүүдийг эрэмбэлж, аль сүлжээнд утсыг холбоход нөлөөлөх боломж олгоно."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Блютүүт төхөөрөмжтэй хос үүсгэх"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Апп нь таблет дээрх блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Апп нь утсан дээрх Блютүүт тохиргоог харах боломжтой ба хос болох төхөөрөмжтэй холболтыг зөвшөөрөх болон хийх боломжтой."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Апп нь бусад апп-уудын илгээсэн мэдэгдлүүдийг дуудах, шалгах, болон цэвэрлэх боломжтой."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"мэдэгдэл сонсогч үйлчилгээтэй холбох"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Эзэмшигч нь мэдэгдэл сонсох үйлчилгээний дээд-төвшиний интерфейстэй холбох боломжтой. Энгийн апп-д шаардлагагүй."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"нөхцөл нийлүүлэгч үйлчилгээнд холбох"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Эзэмшигчид нөхцөл нийлүүлэгч үйлчилгээний дээд-түвшний интерфейстэй холбох боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"үүрэн компанийн нийлүүлсэн тохируулгын апп-г өдөөх"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Эзэмшигчид үүрэн компанийн нийлүүлсэн тохируулах апп-г өдөөх боломж олгоно. Энгийн апп-уудад хэзээ ч ашиглагдахгүй."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Сүлжээний байдлын талаар ажиглалтуудыг хүлээн авах"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ханын зураг"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ханын зураг солих"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Мэдэгдэл сонсогч"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Нөхцөл нийлүүлэгч"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN идэвхтэй болов"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN-г <xliff:g id="APP">%s</xliff:g> идэвхтэй болгов"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Сүлжээг удирдах бол хүрнэ үү."</string>
diff --git a/core/res/res/values-ms-rMY/strings.xml b/core/res/res/values-ms-rMY/strings.xml
index 219e47b..53c9b94 100644
--- a/core/res/res/values-ms-rMY/strings.xml
+++ b/core/res/res/values-ms-rMY/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Tidak bertajuk&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Penyegerakan"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Terlalu banyak pemadaman <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Storan tablet penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Storan tontonan penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Storan telefon penuh. Padamkan beberapa fail untuk mengosongkan ruang."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rangkaian mungkin dipantau"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Oleh pihak ketiga yang tidak diketahui"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Pendering dihidupkan"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Mematikan..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet anda akan dimatikan."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Tontonan anda akan dimatikan."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon anda akan dimatikan."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Adakah anda mahu menutup?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"But semula ke mod selamat"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod pesawat"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Mod Pesawat DIHIDUPKAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Mod Pesawat DIMATIKAN"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Tetapan"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod selamat"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Membenarkan apl untuk mendapatkan kandungan tetingkap aktif. Apl hasad boleh mengambil keseluruhan kandungan tetingkap dan memeriksa semua teks kecuali kata laluan."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dayakan kebolehcapaian untuk sementara"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Membenarkan aplikasi untuk mendayakan kebolehcapaian untuk sementara pada peranti. Apl hasad mungkin mendayakan kebolehcapaian tanpa izin pengguna."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"dapatkan kembali token tetingkap"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Membenarkan apl mendapatkan kembali token tetingkap. Apl hasad mungkin meniru sistem dan menjalankan interaksi yang tidak dibenarkan dengan tetingkap aplikasi."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"dapatkan kembali statistik bingkai"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Membenarkan aplikasi mengumpul statistik bingkai. Apl hasad mungkin memerhatikan statistik bingkai tetingkap dari apl lain."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"tapis acara"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Membenarkan aplikasi mendaftarkan penapis input yang menapis strim semua acara pengguna sebelum dihantar. Apl hasad mungkin mengawal UI sistem tanpa campur tangan pengguna."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"penutupan separa"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Membenarkan apl untuk menyiarkan pemberitahuan bahawa mesej SMS telah diterima. Apl hasad boleh menggunakannya untuk memalsukan mesej SMS masuk."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"hantar siaran WAP-TOLAK-diterima"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Membenarkan apl untuk menyiarkan pemberitahuan bahawa mesej WAP PUSH telah diterima. Apl hasad boleh menggunakannya untuk memalsukan penerimaan mesej MMS atau secara diam-diam menggantikan kandungan mana-mana laman web dengan varian hasad."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"hantar siaran markah rangkaian"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Membenarkan apl menyiarkan pemberitahuan bahawa rangkaian perlu diberi markah. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"hadkan bilangan proses yang dijalankan"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Membenarkan apl untuk mengawal bilangan maksimum proses yang akan berlangsung. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"memaksa apl latar belakang untuk menutup"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan Vpn. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"terikat pada kertas dinding"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi kertas dinding. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"terikat kepada paparan jauh"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi paparan jauh. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"terikat kepada perkhidmatan widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan widget. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"terikat kepada perkhidmatan pembekal laluan"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Membenarkan pemegang untuk terikat kepada mana-mana pembekal laluan yang berdaftar. Tidak sekali-kali diperlukan untuk apl normal."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"berinteraksi dengan pentadbir peranti"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Membenarkan pemegang menghantar tujuan kepada pentadbir peranti. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"ikat kepada input TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi input TV. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"tambah atau alih keluar pentadbir peranti"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Membenarkan pemegang menambah atau mengalih keluar pentadbir peranti aktif. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"tukar orientasi skrin"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Membenarkan apl membaca maklumat profil peribadi yang disimpan dalam peranti anda, seperti nama dan maklumat kenalan anda. Ini bermakna apl lain boleh mengenal pasti anda dan menghantar maklumat profil anda kepada orang lain."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"ubah suai kad kenalan sendiri"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Membenarkan apl menukar atau menambah maklumat profil peribadi yang disimpan pada peranti anda, seperti nama dan maklumat kenalan anda. Ini bermakna apl boleh mengenal pasti anda dan menghantar maklumat profil anda kepada orang lain."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"penderia (spt. denyut jantung)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Membenarkan apl mengakses data dari penderia yang anda gunakan untuk mengukur perkara yang berlaku dalam tubuh anda, seperti kadar denyutan jantung."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"baca aliran sosial anda"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Membenarkan apl mengakses dan menyegerakkan kemas kini sosial daripada anda dan rakan anda. Berhati-hati semasa berkongsi maklumat - ini membenarkan apl untuk membaca komunikasi di antara anda dan rakan anda pada rangkaian sosial tanpa mengira kerahsiaan. Nota: kebenaran ini tidak boleh dikuatkuasakan pada semua rangkaian sosial."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"tulis ke aliran sosial anda"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Tukar keadaan WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Membenarkan apl untuk menyambungkan tablet ke dan menyahsambungkan tablet dari rangkaian WiMaX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Membenarkan apl untuk menyambungkan telefon ke dan menyahsambung telefon dari rangkaian WiMaX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"beri markah kepada rangkaian"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Membenarkan apl menilai rangkaian dan mempengaruhi rangkaian yang harus dipilih oleh tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Membenarkan apl menilai rangkaian dan mempengaruhi rangkaian yang harus dipilih oleh telefon."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"berpasangan dengan peranti Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Membenarkan apl melihat konfigurasi Bluetooth pada tablet dan untuk membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Membenarkan apl melihat konfigurasi Bluetooth pada telefon dan membuat serta menerima sambungan dengan peranti yang dipasangkan."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Membenarkan apl untuk mendapatkan semula, memeriksa dan memadam bersih pemberitahuan, termasuk yang disiarkan oleh apl lain."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"ikat kepada perkhidmatan pendengar pemberitahuan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Membenarkan pemegang terikat dengan antara muka peringkat tertinggi bagi perkhidmatan pendengar pemberitahuan. Tidak sekali-kali diperlukan untuk apl biasa."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gunakan apl konfigurasi yang disediakan oleh pembawa"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Membenarkan pemegang menggunakan apl konfigurasi yang diberikan oleh pembawa. Tidak sekali-kali diperlukan untuk apl biasa."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"dengar pemerhatian mengenai keadaan rangkaian"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Kertas dinding"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Tukar kertas dinding"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Pendengar pemberitahuan"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN diaktifkan"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN diaktifkan oleh <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Sentuh untuk mengurus rangkaian."</string>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index 593d260..a67cb28 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Uten navn&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkronisering"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"For mange slettinger av <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Nettbrettlageret er fullt. Slett noen filer for å frigjøre lagringsplass."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Klokkens lagringsplass er full. Slett filer for å frigjøre plass."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefonlageret er fullt. Slett noen filer for å frigjøre lagringsplass."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Nettverket blir muligens overvåket"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Av en ukjent tredjepart"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringelyd på"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Avslutter…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Nettbrettet slås av."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Klokken slås av."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonen kommer til å slås av."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vil du slå av?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Start på nytt i sikker modus"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flymodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flymodus er på"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flymodus er av"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Innstillinger"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Sikkermodus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Lar appen hente ut innholdet i det aktive vinduet. Ondsinnede apper kan hente ut hele vindusinnholdet og undersøke all teksten, med unntak av passord."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivere tilgjengelighet midlertidig"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Lar en app midlertidig aktivere tilgjengelighet på enheten. Skadelige apper kan aktivere tilgjengelighet uten bekreftelse fra brukeren."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"hente vindustoken"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Gir appen tillatelse til å hente vindustokenet. Skadelige apper kan sette igang uautorisert samhandling med appvinduet ved å imitere systemet."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"hente bildestatistikk"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Gir appen tillatelse til å samle inn bildestatistikk. Skadelige apper kan observere bildestatistikken til vinduer i andre apper."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrere hendelser"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Lar appen registrere et inndatafilter som filtrerer strømmen for alle brukerhendelser før de sendes ut. Skadelige apper kan kontrollere brukergrensesnittet for systemet uten at brukeren gjør noe."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delvis avslutning"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Lar appen kringkaste et varsel om at en SMS-melding er mottatt. Ondsinnede apper kan bruke dette til å forfalske innkommende SMS-meldinger."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"kringkaste melding om mottatt WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Lar appen kringkaste et varsel om at en WAP-PUSH-melding er mottatt. Ondsinnede apper kan bruke dette til å forfalske MMS-meldingskvitteringer, eller ubemerket erstatte innholdet av alle slags nettsider med ondsinnede varianter."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"sende kringkasting om nettverksvurdering"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Gir appen tillatelse til å kringkaste et varsel om at nettverk må vurderes. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"begrense antallet kjørende prosesser"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Lar appen kontrollere det maksimale antallet prosesser som kjører. Aldri nødvendig for vanlige apper."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinge bakgrunnsapper til å lukkes"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en VPN-tjeneste. Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binde til bakgrunnsbilde"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Lar innehaveren binde det øverste nivået av grensesnittet til en bakgrunn. Skal aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"binde seg til en tjeneste for talehandlinger"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en tjeneste for talehandlinger. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"binde til ekstern skjerm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Lar innehaveren binde seg til det øverste grensesnittnivået for ekstern skjerm. Skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"binde til modultjenste"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lar innehaveren binde seg til det øverste nivået av grensesnittet for en modultjeneste. Skal aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"binde seg til en ruteleverandørtjeneste"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Innehaveren av tillatelsen kan binde seg til ruteleverandører. Dette er ikke nødvendig for vanlige apper."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"kommunisere med enhetsadministrator"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Lar innehaveren sende hensikter til en enhetsadministrator. Skal aldri være nødvendig for normale apper."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"binde appen til en TV-inngang"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Lar innehaveren binde appen til det øverste grensesnittnivået for en TV-inngang. Dette skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"legge til eller fjerne en enhetsadministrator"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Tillater innehaveren å legge til eller fjerne aktive enhetsadministratorer. Dette skal aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"snu skjermen"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Lar appen lese personlig profilinformasjon som er lagret på enheten, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"endre ditt eget kontaktkort"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Lar appen endre eller legge til personlig profilinformasjon som er lagret på enheten din, som for eksempel navn og kontaktinformasjon. Dette betyr at appen kan identifisere deg og sende profilinformasjonen din til andre."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kroppssensorer (som pulsmålere)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Gir appen tillatelse til å bruke data fra sensorer du bruker til å måle det som skjer i kroppen din, som f.eks. pulsen."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"lese din sosiale strøm"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Lar appen lese og synkronisere sosiale oppdateringer fra deg selv og vennene dine. Vær forsiktig når du deler informasjon - med denne tillatelsen kan appen lese kommunikasjon mellom deg og vennene dine på sosiale nettverk, uavhengig av konfidensialitet. Vær oppmerksom på at denne tillatelsen kanskje ikke gjelder for alle sosiale nettverk."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skrive i din sosiale strøm"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Endre WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Lar appen koble nettbrettet til og fra WiMAX-nettverk."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Lar appen koble telefonen til og fra WiMAX-nettverk."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"vurdere nettverk"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Gir appen tillatelse til å rangere nettverk, og påvirke hvilket nettverk nettbrettet skal foretrekke."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Gir appen tillatelse til å rangere nettverk, og påvirke hvilket nettverk telefonen skal foretrekke."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"koble til Bluetooth-enheter"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Lar appen se Bluetooth-konfigurasjonen på nettbrettet, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Lar appen se Bluetooth-konfigurasjonen på telefonen, samt opprette og godta tilkoblinger med sammenkoblede enheter."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Lar appen hente, gjennomgå og fjerne varsler, inkludert de som sendes fra andre apper."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binding til en varsellyttertjeneste"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lar innehaveren binde seg til det øverste grensesnittnivået for en varsellyttertjeneste. Skal aldri være nødvendig for vanlige apper."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binde seg til en leverandørtjeneste for betingelser"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Gir innehaveren tillatelse til å binde til toppnivået av brukergrensesnittet for en leverandørtjeneste for betingelser. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"starte konfigurasjonsappen som ble levert av operatøren"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Gir innehaveren tillatelse til å kalle opp den konfigurasjonsappen som ble levert av operatøren. Dette skal ikke være nødvendig for vanlige apper."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lytte etter observasjoner om nettverksforhold"</string>
@@ -688,7 +732,7 @@
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"endre kalibreringen av inndataenheter"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Lar appen endre kalibrasjonsparametrene for berøringsskjermen. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
     <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"tilgang til DRM-sertifikater"</string>
-    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Lar en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
+    <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Tillater at en app klargjøre og bruke DRM-sertifikater. Denne tillatelsen bør aldri være nødvendig for vanlige apper."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Angi passordregler"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kontroller tillatt lengde og tillatte tegn i passord for opplåsing av skjerm."</string>
     <string name="policylab_watchLogin" msgid="914130646942199503">"Overvåk forsøk på opplåsing av skjerm"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrunnsbilde"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Velg bakgrunnsbilde"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Varsellytteren"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Betingelsesleverandør"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN er aktivert"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN er aktivert av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Trykk for å administrere nettverket."</string>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 9225c23..3b2391f 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Zonder titel&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchroniseren"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Te veel verwijderen voor <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tabletgeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Horlogegeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefoongeheugen is vol. Verwijder enkele bestanden om ruimte vrij te maken."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Netwerk kan worden gecontroleerd"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Door een onbekende derde partij"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Belsoftware aan"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Uitschakelen..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Uw tablet wordt uitgeschakeld."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Uw horloge wordt uitgeschakeld."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Uw telefoon wordt uitgeschakeld."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Wilt u afsluiten?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Opnieuw opstarten in veilige modus"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Vliegmodus"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Vliegmodus is AAN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Vliegmodus is UIT"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Instellingen"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Veilige modus"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-systeem"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Hiermee kan de app de inhoud van het actieve venster ophalen. Schadelijke apps kunnen de volledige inhoud van het venster ophalen en alle tekst bekijken, behalve wachtwoorden."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"toegankelijkheid tijdelijk inschakelen"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Een app toestaan toegankelijkheid tijdelijk in te schakelen op het apparaat. Schadelijke apps kunnen toegankelijkheid inschakelen zonder toestemming van de gebruiker."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"venstertoken ophalen"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Hiermee kan een app de venstertoken ophalen. Schadelijke apps kunnen niet-geautoriseerde interactie met het appvenster uitvoeren en het systeem nabootsen."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"framestatistieken ophalen"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Hiermee kan een app framestatistieken verzamelen. Schadelijke apps kunnen de framestatistieken voor vensters van andere apps bekijken."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"evenementen filteren"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Toestaan dat een app een invoerfilter registreert waarmee de streams van alle gebruikersgebeurtenissen worden gefilterd voordat deze worden verzonden. Schadelijke apps kunnen de gebruikersinterface van het systeem beheren zonder tussenkomst van de gebruiker."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"gedeeltelijke uitschakeling"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Hiermee kan de app een melding verzenden dat een sms\'je is ontvangen. Schadelijke apps kunnen dit gebruiken om inkomende sms\'jes te vervalsen."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"melding over ontvangen WAP-PUSH-bericht verzenden"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Hiermee kan de app een melding verzenden dat een WAP PUSH-bericht is ontvangen. Schadelijke apps kunnen dit gebruiken om de ontvangst van MMS-berichten te vervalsen of de inhoud van een webpagina ongemerkt te vervangen door schadelijke varianten."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"melding verzenden dat netwerken een score moeten krijgen"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Hiermee kan de app een melding uitzenden dat netwerken een score moeten krijgen. Nooit vereist voor normale apps."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"aantal actieve processen beperken"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Hiermee kan de app het maximale aantal processen beheren dat kan worden uitgevoerd. Nooit nodig voor normale apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"achtergrondapps gedwongen stoppen"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Staat de houder toe verbinding te maken met de hoofdinterface van een VPN-service. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"verbinden met een achtergrond"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Hiermee wordt de houder toegestaan zich te verbinden met de hoofdinterface van een achtergrond. Nooit vereist voor normale apps."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"binden aan een service voor spraakinteractie"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Hiermee kan de houder binden aan de hoofdinterface van een service voor spraakinteractie. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"verbinding maken met een extern display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een extern display. Nooit vereist voor normale apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"verbinden met een widgetservice"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Hiermee wordt de houder toegestaan verbinding te maken met de hoofdinterface van een widgetservice. Nooit vereist voor normale apps."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"binden aan de service van een routeprovider"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Hiermee kan de houder binden aan geregistreerde routeproviders. Nooit gebruikt voor normale apps."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interactie met apparaatbeheer"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Hiermee kan de houder intenties verzenden naar een apparaatbeheerder. Nooit vereist voor normale apps."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"binden aan een tv-ingang"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Hiermee wordt de houder toegestaan te binden aan de hoofdinterface van een tv-ingang. Nooit vereist voor normale apps."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"een apparaatbeheerder toevoegen of verwijderen"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Hiermee kan de rechtenhouder actieve apparaatbeheerders toevoegen of verwijderen. Nooit vereist voor normale apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"schermstand wijzigen"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Hiermee kan de app persoonlijke profielgegevens lezen die op uw apparaat zijn opgeslagen, zoals uw naam en contactgegevens. Dit betekent dat de app u kan identificeren en uw profielgegevens naar anderen kan verzenden."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"uw eigen contactkaart aanpassen"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Hiermee kan de app persoonlijke profielgegevens wijzigen of toevoegen die op uw apparaat zijn opgeslagen, zoals uw naam en contactgegevens. Dit betekent dat de app u kan identificeren en uw profielgegevens naar anderen kan verzenden."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"lichaamssensoren (zoals hartslagmeters)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Toestaan dat de app toegang krijgt tot gegevens van sensoren die u gebruikt om te meten wat er gebeurt in uw lichaam, zoals de hartslag."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"uw sociale stream lezen"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Hiermee kan de app toegang krijgen tot sociale updates van u en uw vrienden en deze synchroniseren. Wees voorzichtig bij het delen van informatie: hiermee kan de app communicatie lezen tussen u en uw vrienden op sociale netwerken, ongeacht de vertrouwelijkheid. Opmerking: deze toestemming kan niet worden afgedwongen voor alle sociale netwerken."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"schrijven naar sociale streams"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX-status wijzigen"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Hiermee kan de app de tablet verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Hiermee kan de app de telefoon verbinden met WiMAX-netwerken en de verbinding daarmee verbreken."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"score toekennen aan netwerken"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Hiermee kan de app netwerken rangschikken en beïnvloeden aan welke netwerken de tablet de voorkeur moet geven."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Hiermee kan de app netwerken rangschikken en beïnvloeden aan welke netwerken de telefoon de voorkeur moet geven."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"koppelen met Bluetooth-apparaten"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Hiermee kan de app de Bluetooth-configuratie van de tablet bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Hiermee kan de app de Bluetooth-configuratie van de telefoon bekijken en verbindingen met gekoppelde apparaten maken en accepteren."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Hiermee kan de app meldingen ophalen, onderzoeken en wissen, waaronder meldingen die zijn verzonden door andere apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"koppelen aan een listener-service voor meldingen"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Hiermee kan de houder koppelen aan de hoofdinterface van een listener-service voor meldingen. Nooit vereist voor normale apps."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"binden aan de service van een provider van voorwaarden"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Hiermee kan de houder binden aan de hoofdinterface van de service van een provider van voorwaarden. Nooit vereist voor normale apps."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"de door de provider geleverde configuratie-app aanroepen"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Hiermee kan de houder de door de provider geleverde configuratie-app aanroepen. Nooit vereist voor normale apps."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"controleren op waarnemingen met betrekking tot netwerkomstandigheden"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Achtergrond"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Achtergrond wijzigen"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Listener voor meldingen"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Provider van voorwaarden"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN is geactiveerd"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN wordt geactiveerd door <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Raak aan om het netwerk te beheren."</string>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 931c24c..b80c1fd 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez nazwy&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronizuj"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Zbyt wiele usuwanych <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Pamięć tabletu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Pamięć w zegarku jest pełna. Usuń niektóre pliki, by zwolnić miejsce."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Pamięć telefonu jest pełna. Usuń niektóre pliki, aby zwolnić miejsce."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Sieć może być monitorowana"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Przez nieznany podmiot zewnętrzny"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Dzwonek włączony"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Wyłączanie..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablet zostanie wyłączony."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Zegarek zostanie wyłączony."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon zostanie wyłączony"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Czy chcesz wyłączyć?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Uruchom w trybie awaryjnym"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Tryb samolotowy"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Tryb samolotowy jest włączony"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Tryb samolotowy jest wyłączony"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Ustawienia"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Tryb awaryjny"</string>
     <string name="android_system_label" msgid="6577375335728551336">"System Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pozwala aplikacji na pobieranie zawartości aktywnego okna. Złośliwe aplikacje mogą pobrać całą zawartość okna i przeanalizować znajdujący się w nim tekst z wyjątkiem haseł."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tymczasowo włącz ułatwienia dostępu"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umożliwia aplikacji tymczasowe włączanie ułatwień dostępu na urządzeniu. Złośliwe aplikacje mogą je włączać bez zgody użytkownika."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"pobieranie tokenu okna"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Zezwala aplikacji na pobieranie tokenu okna. Złośliwe aplikacje mogą podszywać się pod system i bez autoryzacji wchodzić w interakcję z oknem aplikacji."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"pobieranie statystyk klatek"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Zezwala aplikacji na zbieranie statystyk klatek. Złośliwe aplikacje mogą śledzić statystyki klatek wyświetlanych w oknach innych aplikacji."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrowanie zdarzeń"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Zezwala aplikacji na zarejestrowanie filtra wejściowego, który filtruje strumień wszystkich zdarzeń z udziałem użytkownika przed ich rozesłaniem. Złośliwe aplikacje mogą kontrolować interfejs systemu niezależnie od działań użytkownika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"częściowe wyłączenie"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Pozwala aplikacji na wysyłanie powiadomienia, że została odebrana wiadomość SMS. Złośliwe aplikacje mogą to wykorzystać do fałszowania przychodzących wiadomości SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"wysyłanie transmisji informującej o otrzymaniu wiadomości WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Pozwala aplikacji na nadanie powiadomienia o odebraniu wiadomości WAP PUSH. Złośliwe aplikacje mogą to wykorzystać do fałszowania potwierdzenia odbioru wiadomości MMS lub do niezauważalnego podmieniania zawartości dowolnej strony internetowej jej szkodliwymi wariantami."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"rozsyłanie informacji o ocenie sieci"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Pozwala aplikacji na wysłanie powiadomienia, że sieci wymagają oceny. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ograniczanie liczby uruchomionych procesów"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pozwala aplikacji na kontrolowanie maksymalnej liczby uruchamianych procesów. Nigdy niewykorzystywane przez normalne aplikacje."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"wymuszanie zamknięcia aplikacji w tle"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi VPN. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"powiązanie z tapetą"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pozwala na tworzenie powiązania z interfejsem najwyższego poziomu tapety. Nieprzeznaczone dla zwykłych aplikacji."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"powiąż z interaktorem głosowym"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi interakcji głosowej. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"powiązanie z wyświetlaczem zdalnym"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu wyświetlacza zdalnego. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"powiązanie z usługą widżetów"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi widżetów. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"powiązanie z usługą dostawcy tras"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umożliwia właścicielowi powiązanie z dowolnymi zarejestrowanymi dostawcami tras. Nie powinno być nigdy potrzebne w normalnych aplikacjach."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcja z administratorem urządzenia"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Zezwala na wysyłanie intencji do administratora urządzenia. Nie powinno być nigdy potrzebne w przypadku zwykłych aplikacji."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"powiązanie z wejściem TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Zezwala na utworzenie powiązania z głównym interfejsem wejścia TV. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodaj lub usuń administratora urządzenia"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umożliwia właścicielowi dodawanie i usuwanie aktywnych administratorów urządzenia. Ta opcja nie jest wykorzystywana w przypadku standardowych aplikacji."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"zmienianie orientacji ekranu"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Pozwala aplikacji na odczyt osobistych informacji przechowywanych w Twoim profilu na urządzeniu (np. imienia i nazwiska lub adresu). Oznacza to, że aplikacja może Cię zidentyfikować i wysłać informacje z Twojego profilu do innych osób."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"zmiana własnej karty kontaktu"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Pozwala aplikacji na zmianę lub dodanie osobistych informacji przechowywanych w Twoim profilu na urządzeniu (np. imienia i nazwiska lub adresu). Oznacza to, że aplikacja może Cię zidentyfikować i wysłać informacje z Twojego profilu do innych osób."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"czujniki ciała (np. monitorujące tętno)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Zezwala aplikacji na dostęp do danych z czujników mierzących procesy zachodzące w ciele, np. bicie serca (tętno)."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"odczyt sieci społecznościowych"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Pozwala aplikacji na odczyt i synchronizację informacji publikowanych przez Ciebie i Twoich znajomych w sieciach społecznościowych. Zachowaj ostrożność, udostępniając informacje. Aplikacja z tym uprawnieniem może odczytać całą komunikację, którą prowadzisz ze swoimi znajomymi w sieciach społecznościowych, niezależnie od jej poufności. Uwaga: to uprawnienie może nie być egzekwowane we wszystkich sieciach społecznościowych."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"zapis sieci społecznościowych"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"zmienianie stanu WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w tablecie."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Pozwala aplikacji na nawiązywanie i kończenie połączeń z sieciami WiMAX w telefonie."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocenianie sieci"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Pozwala aplikacji na ocenę sieci i wybieranie sieci preferowanych przez tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Pozwala aplikacji na ocenę sieci i wybieranie sieci preferowanych przez telefon."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"parowanie z urządzeniami Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na tablecie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Pozwala aplikacji na dostęp do konfiguracji Bluetooth na telefonie oraz na nawiązywanie i akceptowanie połączeń ze sparowanych urządzeń."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umożliwia aplikacji pobieranie, sprawdzanie i usuwanie powiadomień, także tych, które pochodzą z innych aplikacji."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"utwórz połączenie z usługą odbiornika powiadomień"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi odbiornika powiadomień. Nie powinno być nigdy potrzebne dla zwykłych aplikacji."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"powiąż z usługą dostawcy warunków"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Zezwala na tworzenie powiązania z interfejsem najwyższego poziomu usługi dostawcy warunków. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Zezwala na wywoływanie aplikacji konfiguracyjnej udostępnionej przez operatora. Nieprzeznaczone dla zwykłych aplikacji."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"śledź stan sieci"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmień tapetę"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Odbiornik powiadomień"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Dostawca warunków"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktywny"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Obsługa sieci VPN została włączona przez aplikację <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotknij, aby zarządzać siecią."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index 9eb7512..668f9ef 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem nome&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronização"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Demasiadas eliminações de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"O armazenamento do tablet está cheio. Elimine alguns ficheiros para libertar espaço."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"O armazenamento de visualizações está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"A rede pode ser monitorizada"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por um terceiro desconhecido"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Campainha ativada"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"A encerrar..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"O seu tablet irá encerrar."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"As suas visualizações vão ser encerradas."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será encerrado."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Pretende encerrar?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo de avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"O modo de voo está ativado"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"O modo de voo está desativado"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Definições"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo seguro"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que a aplicação obtenha o conteúdo da janela ativa. As aplicações maliciosas podem obter todo o conteúdo da janela e examinar todo o texto, exceto as palavras-passe."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"acessibilidade ativada temporariamente"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que uma aplicação ative temporariamente a acessibilidade no dispositivo. As aplicações maliciosas podem ativar a acessibilidade sem o consentimento do utilizador."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"obter token da janela"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permite que uma aplicação obtenha o token da janela. As aplicações maliciosas podem interagir de forma não autorizada com a janela da aplicação, roubando a identidade do sistema."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"obter estatísticas de fotograma"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permite que uma aplicação recolha estatísticas de fotograma. As aplicações maliciosas podem observar as estatísticas de fotograma de janelas de outras aplicações."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que uma aplicação registe um filtro de entrada que filtra a transmissão em fluxo contínuo para todos os eventos de utilizador antes de serem entregues. Uma aplicação maliciosa pode controlar a IU do sistema sem intervenção do utilizador."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"encerramento parcial"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que a aplicação difunda uma notificação de que foi recebida uma mensagem SMS. As aplicações maliciosas podem utilizar este recurso para forjar mensagens SMS recebidas."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar difusão recebida através de PUSH WAP"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que a aplicação difunda uma notificação de que foi recebida uma mensagens PUSH WAP. As aplicações maliciosas podem utilizar isto para forjar um recibo de mensagem MMS ou substituir, de forma silenciosa, o conteúdo de qualquer página Web por variantes maliciosas."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmissão de pontuação de redes"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite à aplicação transmitir uma notificação de que é necessário pontuar as redes. Nunca é necessário para aplicações normais."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"número limite de processos em execução"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite a uma aplicação controlar o número máximo de processos que será executado. Nunca é necessário para aplicações normais."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar as aplicações em segundo plano a fechar"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que o titular se vincule à interface de nível superior de um serviço de VPN. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"vincular a uma imagem de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite ao titular vincular-se à interface de nível superior de uma imagem de fundo. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"vincular a um interlocutor de voz"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Permite que o titular vincule a interface de nível superior de um serviço de interação de voz. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"associar a um ecrã remoto"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite ao detentor associar a interface de nível superior a um ecrã remoto. Nunca deve ser necessário para aplicações normais."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"vincular a um serviço de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o titular vincule a interface de nível superior de um serviço de widget. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"vincular a serviço de fornecedor de trajeto"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite ao titular vincular a quaisquer fornecedores de trajeto registado. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com um administrador do dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite ao titular enviar intenções para um administrador do aparelho. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"vincular a uma entrada de TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite ao titular vincular à interface de nível superior de uma entrada de TV. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador de dispositivos"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o titular adicione ou remova administradores de dispositivos ativos. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"mudar orientação do ecrã"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que a aplicação leia dados de perfil pessoais guardados no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modificar o próprio cartão de contacto"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que a aplicação altere ou adicione dados de perfil pessoais guardados no dispositivo, tais como o seu nome e informações de contacto. Isto significa que outras aplicações podem identificá-lo e enviar os seus dados de perfil a terceiros."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporais (como monitores do ritmo cardíaco)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite à aplicação aceder a dados de sensores que o utilizador usa para medir o que está a acontecer no seu corpo, por exemplo o ritmo cardíaco."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler o seu fluxo social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que a aplicação aceda e sincronize atualizações de redes sociais suas e dos seus amigos. Tenha cuidado ao partilhar informações, pois esta ação permite que a aplicação leia comunicações entre si e os seus amigos nas redes sociais, independentemente do grau de confidencialidade. Nota: esta autorização pode não ser aplicada a todas as redes sociais."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever para o seu fluxo social"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que a aplicação ligue e desligue o tablet de redes WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que a aplicação ligue e desligue o telemóvel de redes WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"pontuar redes"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite à aplicação classificar redes e influenciar as redes que o tablet deve preferir."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite à aplicação classificar redes e influenciar as redes que o telemóvel deve preferir."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"sincronizar com dispositivos Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que a aplicação visualize a configuração do Bluetooth no tablet e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que a aplicação visualize a configuração do Bluetooth no telemóvel e que estabeleça e aceite ligações com dispositivos emparelhados."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que a aplicação obtenha, examine e limpe notificações, incluindo as que foram publicadas por outras aplicações."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"vincular a um serviço de escuta de notificações"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o titular vincule a interface de nível superior de um serviço de escuta de notificações. Nunca deverá ser necessário para aplicações normais."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"vincular a um serviço de fornecedor de condição"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Permite que o titular vincule a interface de nível superior de um serviço de fornecedor de condição. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar a aplicação de configuração fornecida pela operadora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o titular invoque a aplicação de configuração fornecida pela operadora. Nunca deverá ser necessário para aplicações normais."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ouvir observações sobre as condições da rede"</string>
@@ -1105,7 +1149,7 @@
     <string name="Midnight" msgid="5630806906897892201">"Meia-noite"</string>
     <string name="elapsed_time_short_format_mm_ss" msgid="4431555943828711473">"<xliff:g id="MINUTES">%1$02d</xliff:g>:<xliff:g id="SECONDS">%2$02d</xliff:g>"</string>
     <string name="elapsed_time_short_format_h_mm_ss" msgid="1846071997616654124">"<xliff:g id="HOURS">%1$d</xliff:g>:<xliff:g id="MINUTES">%2$02d</xliff:g>:<xliff:g id="SECONDS">%3$02d</xliff:g>"</string>
-    <string name="selectAll" msgid="6876518925844129331">"Seleccionar tudo"</string>
+    <string name="selectAll" msgid="6876518925844129331">"Selecionar tudo"</string>
     <string name="cut" msgid="3092569408438626261">"Cortar"</string>
     <string name="copy" msgid="2681946229533511987">"Copiar"</string>
     <string name="paste" msgid="5629880836805036433">"Colar"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagem de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar imagem de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviço de escuta de notificações"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Fornecedor de condição"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN foi ativada pelo <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerir a rede."</string>
diff --git a/core/res/res/values-pt/strings.xml b/core/res/res/values-pt/strings.xml
index fd75660..db493e0 100644
--- a/core/res/res/values-pt/strings.xml
+++ b/core/res/res/values-pt/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Sem título&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizar"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Muitas exclusões de <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"O armazenamento do tablet está cheio. Exclua alguns arquivos para liberar espaço."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Armazenamento do relógio cheio. Exclua alguns arquivos para liberar espaço."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telefone está cheio. Exclua alguns arquivos para liberar espaço."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"A rede pode ser monitorada"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por terceiros desconhecidos"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Campainha ligada"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Encerrando…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Seu tablet será desligado."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Seu relógio será desligado."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"O seu telefone será desligado."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Deseja desligar?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reiniciar no modo de segurança"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modo avião"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modo avião ATIVADO"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modo avião DESATIVADO"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Configurações"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Modo de segurança"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistema Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite que o aplicativo recupere o conteúdo da janela ativa. Aplicativos maliciosos podem recuperar o conteúdo da janela inteira e examinar todo o texto, exceto as senhas."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"ativar temporariamente a acessibilidade"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite que um aplicativo ative temporariamente a acessibilidade no dispositivo. Aplicativos maliciosos podem ativar a acessibilidade sem o consentimento do usuário."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"recuperar token da janela"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permite que o aplicativo recupere o token da janela. Aplicativos maliciosos podem realizar interações não autorizadas com a janela do aplicativo em nome do sistema."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"recuperar estatísticas de quadros"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permite que o aplicativo colete estatísticas de quadros. Aplicativos maliciosos podem observar as estatísticas de quadros de janelas de outros aplicativos."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrar eventos"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite que o aplicativo registre um filtro de entrada que filtra o fluxo de todos os eventos do usuário antes que sejam enviados. Aplicativos mal-intencionados podem controlar a interface do sistema sem a intervenção do usuário."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"desligamento parcial"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite que o aplicativo transmita uma notificação quando uma mensagem SMS foi recebida. Aplicativos maliciosos podem usar esse recurso para forjar mensagens SMS recebidas."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"enviar transmissão WAP-PUSH recebida"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite que o aplicativo transmita uma notificação quando uma mensagem WAP PUSH for recebida. Aplicativos maliciosos podem usar esse recurso para forjar o recebimento de mensagens MMS ou substituir o conteúdo de qualquer página da web com variantes maliciosas."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"enviar transmissão de avaliação de redes"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite que o aplicativo transmita uma notificação informando que as redes devem ser avaliadas. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar número de processos em execução"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite que o aplicativo controle o máximo de processos que serão executados. Nunca é necessário para aplicativos normais."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forçar encerramento de aplicativos em segundo plano"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite que seu proprietário sujeite a interface de alto nível de um serviço de VPN. Nunca deve ser necessário para aplicativos normais."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sujeitar-se a um plano de fundo"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite que o proprietário utilize interface de nível superior de um plano de fundo. Nunca deve ser necessário para aplicativos normais."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"usar uma tela remota"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite que o proprietário use a interface de nível superior de uma tela remota. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"sujeitar-se a um serviço de widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite que o proprietário utilize a interface de nível superior de um serviço de widget. Nunca deve ser necessário para aplicativos normais."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"usar um serviço provedor de rotas"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite que o proprietário use qualquer provedor de rotas registrado. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interagir com o administrador de um dispositivo"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite que o proprietário envie tentativas ao administrador de um aparelho. Nunca deve ser necessário para aplicativos normais."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"associar a uma entrada de TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite que o proprietário use a interface de nível superior de uma entrada de TV. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adicionar ou remover um administrador do dispositivo"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite que o proprietário adicione ou remova administradores do dispositivo ativos. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"alterar orientação da tela"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite que o aplicativo leia informações de perfil pessoal armazenadas no dispositivo, como seu nome e dados de contato. Isso significa que o aplicativo poderá identificá-lo e enviar suas informações de perfil para terceiros."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"mod. próprio cartão contato"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite que o aplicativo altere ou adicione informações pessoais de perfil armazenadas em seu dispositivo, como seu nome e informações de contato. Isso significa que o aplicativo pode identificá-lo e enviar as informações de seus perfil para terceiros."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"sensores corporais"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite que o aplicativo acesse dados de sensores usados para medir o que acontece em seu corpo, como seus batimentos cardíacos."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"ler suas transmissões sociais"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite que o aplicativo acesse e sincronize suas atualizações sociais e as de seus amigos. Tenha cuidado ao compartilhar informações: isto permite que o aplicativo leia as mensagens trocadas por você e seus amigos em redes sociais, independentemente de sua confidencialidade. Obsservaç: pode não ser aplicável a todas as redes sociais."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"escrever p/ suas transm. soc."</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Alterar estado do WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite que o aplicativo conecte e desconecte o tablet de redes WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite que o aplicativo conecte e desconecte o telefone de redes WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"avaliar redes"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite que o aplicativo classifique as redes e influencie a escolha de redes pelo tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite que o aplicativo classifique as redes e influencie a escolha de redes pelo smartphone."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"parear com dispositivos Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite que o aplicativo acesse a configuração do Bluetooth no tablet, além de fazer e aceitar conexões com dispositivos pareados."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite que o aplicativo acesse a configuração do Bluetooth no telefone, além de fazer e aceitar conexões com dispositivos pareados."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite que o aplicativo recupere, examine e limpe notificações, inclusive as postadas por outros aplicativos."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"sujeitar a um serviço ouvinte de notificações"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite que o proprietário sujeite a interface de nível superior a um serviço ouvinte de notificações. Não deve ser necessário para aplicativos comuns."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"invocar o aplicativo de configuração fornecido pela operadora"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite que o proprietário invoque o aplicativo de configuração fornecido pela operadora. Não deve ser necessário para aplicativos comuns."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"detectar observações nas condições da rede"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Plano de fundo"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Alterar plano de fundo"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Ouvinte de notificações"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN ativada"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"A VPN está ativada por <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Toque para gerenciar a rede."</string>
diff --git a/core/res/res/values-rm/strings.xml b/core/res/res/values-rm/strings.xml
index 4e9806b..3103b1f 100644
--- a/core/res/res/values-rm/strings.xml
+++ b/core/res/res/values-rm/strings.xml
@@ -28,6 +28,28 @@
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <!-- no translation found for fileSizeSuffix (9164292791500531949) -->
     <skip />
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <!-- no translation found for untitled (4638956954852782576) -->
     <skip />
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
@@ -160,6 +182,8 @@
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Memia blers cuntegns stizzads (<xliff:g id="CONTENT_TYPE">%s</xliff:g>)."</string>
     <!-- no translation found for low_memory (6494019234102154896) -->
     <skip />
+    <!-- no translation found for low_memory (4415914910770005166) -->
+    <skip />
     <!-- no translation found for low_memory (3475999286680000541) -->
     <skip />
     <!-- no translation found for ssl_ca_cert_warning (5848402127455021714) -->
@@ -186,6 +210,8 @@
     <string name="shutdown_progress" msgid="2281079257329981203">"Vegn serrà..."</string>
     <!-- no translation found for shutdown_confirm (3385745179555731470) -->
     <skip />
+    <!-- no translation found for shutdown_confirm (3490275567476369184) -->
+    <skip />
     <!-- no translation found for shutdown_confirm (649792175242821353) -->
     <skip />
     <!-- no translation found for shutdown_confirm_question (2906544768881136183) -->
@@ -214,6 +240,8 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Modus d\'aviun"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Il modus d\'aviun è activà"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Il modus d\'aviun è deactivà."</string>
+    <!-- no translation found for global_action_settings (1756531602592545966) -->
+    <skip />
     <!-- no translation found for status_bar_notification_info_overflow (5301981741705354993) -->
     <skip />
     <string name="safeMode" msgid="2788228061547930246">"Modus segirà"</string>
@@ -478,6 +506,14 @@
     <skip />
     <!-- no translation found for permdesc_temporary_enable_accessibility (8079456293182975464) -->
     <skip />
+    <!-- no translation found for permlab_retrieveWindowToken (7154762602367758602) -->
+    <skip />
+    <!-- no translation found for permdesc_retrieveWindowToken (668173747687795074) -->
+    <skip />
+    <!-- no translation found for permlab_frameStats (7056374987314361639) -->
+    <skip />
+    <!-- no translation found for permdesc_frameStats (4758001089491284919) -->
+    <skip />
     <!-- no translation found for permlab_filter_events (8675535648807427389) -->
     <skip />
     <!-- no translation found for permdesc_filter_events (8006236315888347680) -->
@@ -504,6 +540,10 @@
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"trametter in broadcast retschavì da WAP-PUSH"</string>
     <!-- no translation found for permdesc_broadcastWapPush (4783402525039442729) -->
     <skip />
+    <!-- no translation found for permlab_broadcastScoreNetworks (6432008366605475024) -->
+    <skip />
+    <!-- no translation found for permdesc_broadcastScoreNetworks (7652980974435077828) -->
+    <skip />
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitar il dumber maximal da process exequids"</string>
     <!-- no translation found for permdesc_setProcessLimit (7318061314040879542) -->
     <skip />
@@ -590,6 +630,10 @@
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sa fixar vid in fund davos"</string>
     <!-- no translation found for permdesc_bindWallpaper (7108428692595491668) -->
     <skip />
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <!-- no translation found for permlab_bindRemoteDisplay (1782923938029941960) -->
     <skip />
     <!-- no translation found for permdesc_bindRemoteDisplay (1261242718727295981) -->
@@ -598,9 +642,17 @@
     <skip />
     <!-- no translation found for permdesc_bindRemoteViews (4717987810137692572) -->
     <skip />
+    <!-- no translation found for permlab_bindRouteProvider (4869394607915096847) -->
+    <skip />
+    <!-- no translation found for permdesc_bindRouteProvider (4703804520859960329) -->
+    <skip />
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacziun cun in administratur dad apparats"</string>
     <!-- no translation found for permdesc_bindDeviceAdmin (569715419543907930) -->
     <skip />
+    <!-- no translation found for permlab_bindTvInput (5601264742478168987) -->
+    <skip />
+    <!-- no translation found for permdesc_bindTvInput (2371008331852001924) -->
+    <skip />
     <!-- no translation found for permlab_manageDeviceAdmins (4248828900045808722) -->
     <skip />
     <!-- no translation found for permdesc_manageDeviceAdmins (5025608167709942485) -->
@@ -744,6 +796,10 @@
     <skip />
     <!-- no translation found for permdesc_writeProfile (5552084294598465899) -->
     <skip />
+    <!-- no translation found for permlab_bodySensors (4871091374767171066) -->
+    <skip />
+    <!-- no translation found for permdesc_bodySensors (2998865085124153531) -->
+    <skip />
     <!-- no translation found for permlab_readSocialStream (1268920956152419170) -->
     <skip />
     <!-- no translation found for permdesc_readSocialStream (4255706027172050872) -->
@@ -1053,6 +1109,12 @@
     <skip />
     <!-- no translation found for permdesc_changeWimaxState (697025043004923798) -->
     <skip />
+    <!-- no translation found for permlab_scoreNetworks (6445777779383587181) -->
+    <skip />
+    <!-- no translation found for permdesc_scoreNetworks (1304304745850215556) -->
+    <skip />
+    <!-- no translation found for permdesc_scoreNetworks (1831501848178651379) -->
+    <skip />
     <!-- no translation found for permlab_bluetooth (6127769336339276828) -->
     <skip />
     <!-- no translation found for permdesc_bluetooth (3480722181852438628) -->
@@ -1154,6 +1216,10 @@
     <skip />
     <!-- no translation found for permdesc_bindNotificationListenerService (985697918576902986) -->
     <skip />
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <!-- no translation found for permlab_invokeCarrierSetup (3699600833975117478) -->
     <skip />
     <!-- no translation found for permdesc_invokeCarrierSetup (4159549152529111920) -->
@@ -2152,6 +2218,8 @@
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Midar il fund davos"</string>
     <!-- no translation found for notification_listener_binding_label (2014162835481906429) -->
     <skip />
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <!-- no translation found for vpn_title (19615213552042827) -->
     <skip />
     <!-- no translation found for vpn_title_long (6400714798049252294) -->
diff --git a/core/res/res/values-ro/strings.xml b/core/res/res/values-ro/strings.xml
index a8a75a5..3ee0b8a 100644
--- a/core/res/res/values-ro/strings.xml
+++ b/core/res/res/values-ro/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TO"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PO"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Fără titlu&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sincronizare"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Prea multe ştergeri <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Stocarea pe tabletă este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Spațiul de stocare de pe ceas este plin! Ștergeți câteva fișiere pentru a elibera spațiu."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Stocarea pe telefon este plină. Ștergeţi câteva fişiere pentru a elibera spaţiu."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Rețeaua poate fi monitorizată"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"De o terță parte necunoscută"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Sonerie activată"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Se închide..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Computerul dvs. tablet PC se va închide."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ceasul dvs. se va închide."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonul dvs. se va închide."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Doriţi să închideţi?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reporniţi în modul sigur"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Mod Avion"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Modul Avion este ACTIVAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Modul avion este DEZACTIVAT"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Setări"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"˃999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mod sigur"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistemul Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Permite aplicaţiei să preia conţinutul ferestrei active. Aplicaţiile rău intenţionate pot să preia întregul conţinut al ferestrei şi să examineze integral textul acesteia, cu excepţia parolelor."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"activare temporară a accesibilității"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Permite unei aplicaţii să activeze temporar accesibilitatea pe gadget. Aplicaţiile rău intenţionate o pot activa fără consimţământul utilizatorului."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"preluarea indicativului ferestrei"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Permite unei aplicații să preia indicativul ferestrei. Aplicațiile dăunătoare pot interacționa neautorizat cu fereastra aplicației substituindu-se sistemului."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"preluarea statisticilor de referință"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Permite unei aplicații să culeagă statistici de referință. Aplicațiile dăunătoare ar putea urmări statisticile de referință ale ferestrelor din alte aplicații."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrare evenimente"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Permite unei aplicaţii să înregistreze un filtru de intrare, care filtrează transmiterea în flux a tuturor evenimentelor utilizatorilor înainte ca acestea să fie expediate. Aplicaţiile rău intenţionate pot controla interfaţa de utilizare a sistemului fără intervenţia utilizatorului."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"închidere parţială"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Permite aplicaţiei să difuzeze o notificare de primire a unui mesaj SMS. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a deturna primirea mesajelor SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"trimitere mesaj difuzat primit prin WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Permite aplicaţiei să difuzeze o notificare de primire a unui mesaj WAP PUSH. Aplicaţiile rău intenţionate pot să utilizeze această permisiune pentru a deturna primirea mesajelor MMS sau pentru a înlocui fără a vă înştiinţa conţinutul oricărei pagini web cu variante rău intenţionate."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"trimiteți transmisia cu rețelele punctate"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Permite aplicației să transmită o notificare de care rețelele au nevoie pentru a fi punctate. Nu este necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitare număr de procese în derulare"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Permite aplicaţiei să controleze numărul maxim de procese care vor rula. Nu este niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"forţează închiderea aplicaţiilor de fundal"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu VPN. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"conectare la o imagine de fundal"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unei imagini de fundal. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"conectare la un ecran la distanță"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Permite proprietarului să se conecteze la interfața de nivel superior a unui ecran la distanță. Nu ar trebui să fie niciodată necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"conectare la un serviciu widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Permite proprietarului să se conecteze la interfaţa de nivel superior a unui serviciu widget. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"se conectează la un serviciu de furnizare a traseelor"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Permite titularului să se conecteze la furnizorii de trasee înregistrați. Nu este necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interacţionare cu administratorul unui dispozitiv"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Permite proprietarului să trimită intenţii către un administrator al dispozitivului. Nu ar trebui să fie niciodată necesară pentru aplicaţiile obişnuite."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"se conectează la o intrare TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Permite proprietarului să se conecteze la interfața de nivel superior a unei intrări TV. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"adăugarea sau eliminarea unui administrator de dispozitiv"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Permite proprietarului să adauge sau să elimine administratorii activi ai dispozitivului. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"modificare orientare ecran"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Permite aplicaţiei să citească informaţiile personale din profil stocate pe dispozitiv, cum ar fi numele şi informaţiile de contact, ceea ce înseamnă că aplicaţia vă poate identifica şi poate trimite informaţiile dvs. de profil altor utilizatori."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"modifică cartea dvs. de vizită"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Permite aplicaţiei să schimbe sau să adauge conţinut în informaţiile personale din profil stocate pe dispozitivul dvs., cum ar fi numele şi informaţiile dvs. de contact. Aceasta înseamnă că aplicaţia vă poate identifica şi poate trimite informaţiile din profilul dvs. altor persoane."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"senzori (ex.: senzori de ritm cardiac)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Permite aplicației să acceseze datele de la senzorii pe care îi utilizați pentru a măsura funcțiile corpului, cum ar fi ritmul cardiac."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"citeşte fluxul social"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Permite aplicaţiei să acceseze şi să sincronizeze actualizările sociale de la dvs. şi de la prietenii dvs. Daţi dovadă de precauţie când distribuiţi informaţii - cu această permisiune aplicaţia citeşte comunicările realizate între dvs. şi prietenii dvs. în reţelele sociale, indiferent de gradul de confidenţialitate a acestora. Notă: această permisiune nu poate fi aplicată pentru toate reţelele sociale."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"scrie în fluxul social"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Schimbaţi starea WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Permite aplicaţiei să conecteze şi să deconecteze tableta la şi de la reţelele WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Permite aplicaţiei să conecteze şi să deconecteze telefonul la şi de la reţelele WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"rețele punctate"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Permite aplicației să clasifice rețelele și să stabilească ce rețele preferă tableta."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Permite aplicației să clasifice rețelele și să stabilească ce rețele preferă telefonul."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"conectează dispozitive Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Permite aplicaţiei să vadă configuraţia tabletei Bluetooth, să efectueze şi să accepte conexiuni cu dispozitive împerecheate."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Permite aplicaţiei să vadă configuraţia telefonului Bluetooth, să efectueze şi să accepte conexiuni cu dispozitive împerecheate."</string>
@@ -681,13 +725,17 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Permite aplicației să recupereze, să examineze și să șteargă notificări, inclusiv pe cele postate de alte aplicații."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"conectare la un serviciu de citire a notificărilor"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Permite proprietarului să se conecteze la interfața de nivel superior a unui serviciu de citire a notificărilor. În mod normal aplicațiile nu ar trebui să aibă nevoie de această permisiune."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"apelarea aplicației de configurare furnizată de operator"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Permite proprietarului să apeleze aplicația de configurare furnizată de operator. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ascultă observații despre starea rețelei"</string>
     <string name="permdesc_accessNetworkConditions" msgid="6899102075825272211">"Permite unei aplicații să asculte observații despre starea rețelei. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="permlab_setInputCalibration" msgid="4902620118878467615">"schimbați calibrarea dispozitivului de intrare"</string>
     <string name="permdesc_setInputCalibration" msgid="4527511047549456929">"Permite aplicației să modifice parametrii de calibrare a ecranului tactil. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
-    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesați certificatele DRM"</string>
+    <string name="permlab_accessDrmCertificates" msgid="7436886640723203615">"accesează certificatele DRM"</string>
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Permite unei aplicații să furnizeze și să utilizeze certificate DRM. Nu ar trebui să fie necesară pentru aplicațiile obișnuite."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Setaţi reguli pentru parolă"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Stabiliţi lungimea şi tipul de caractere permise în parolele pentru deblocarea ecranului."</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Imagine de fundal"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Modificaţi imaginea de fundal"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Serviciu de citire a notificărilor"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN activat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN este activată de <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Atingeţi pentru a gestiona reţeaua."</string>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index d142e9a..8c7a566 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"ПБ"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без названия&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"..."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхр."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Слишком много удалений <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Память планшетного ПК заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Память устройства заполнена. Удалите файлы, чтобы освободить место."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Память телефона заполнена. Удалите какие-нибудь файлы, чтобы освободить место."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Сеть может отслеживаться"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"администратором"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Звонок включен"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Выключение..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Планшетный ПК будет отключен."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Устройство будет отключено."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон будет выключен."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Завершить работу?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Переход в безопасный режим"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим полета"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Выключить"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Включить"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Настройки"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"&gt;999"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безопасный режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Приложение сможет получать контент активного окна. Вредоносные программы смогут перехватывать такой контент и анализировать любой текст, кроме паролей."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"Включение специальных возможностей"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Приложение сможет временно включать на устройстве специальные возможности. Вредоносные приложения смогут включать их без вашего ведома."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"получение токена окна"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Приложение может получать токен окна. Вредоносные программы могут взаимодействовать с окном приложения под видом системы."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"получение статистики по фреймам"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Приложение может собирать статистику по фреймам. Вредоносные приложения могут получать доступ к такой статистике у других программ."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"Фильтрация событий"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Разрешает приложению зарегистрировать входной фильтр, который анализирует весь поток пользовательских событий. Обратите внимание, что вредоносное ПО может получить доступ к управлению интерфейсом без ведома пользователя."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Частичное завершение работы"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Приложение сможет уведомлять о получении SMS. Вредоносные программы смогут таким образом подделывать входящие SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"Отправка уведомлений о доставке SMS с ссылкой на WAP-страницу"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Приложение сможет уведомлять о получении сообщений WAP PUSH. Вредоносные программы смогут таким образом фальсифицировать получение MMS или незаметно подменять содержание любой страницы вредоносными данными."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"Отправка уведомлений о рейтинге сетей"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Приложение сможет отправлять уведомления о том, что сети необходимо присвоить рейтинг. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"Ограничение количества запущенных процессов"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Приложение сможет управлять максимальным количеством процессов, которые могут быть запущены. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"Закрытие фоновых приложений"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Приложение сможет подключаться к базовому интерфейсу службы VPN. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"Привязка к фоновому рисунку"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Приложение сможет подключаться к базовому интерфейсу службы обоев. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"Подключение к службам голосового взаимодействия"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Приложение сможет подключаться к базовому интерфейсу служб голосового взаимодействия. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"Подключение к удаленному дисплею"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Приложение сможет подключаться к базовому интерфейсу удаленного дисплея. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"Подключение к службе виджетов"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Приложение сможет подключаться к базовому интерфейсу службы виджетов. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Подключение к серверам поставщиков маршрутов"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Приложение сможет подключаться к серверам зарегистрированных поставщиков маршрутов. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"Взаимодействие с администратором устройства"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Приложение сможет отправлять объекты intent администратору устройства. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"Подключение к ТВ-входу"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Приложение сможет подключаться к базовому интерфейсу ТВ-входа. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"Добавление/удаление администратора устройства"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Владелец сможет добавлять и удалять администраторов устройства (используется лишь в некоторых приложениях)."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"Изменение ориентации экрана"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Приложение сможет просматривать вашу личную информацию (например, имя и контактные данные), сохраненную на устройстве. Получив эти данные, приложение сможет отправить их другим пользователям."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"Изменение ваших контактных данных"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Приложение сможет изменять вашу личную информацию (например, имя и контактные данные), сохраненную на устройстве. Получив эти данные, приложение сможет отправить их другим пользователям."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"датчики (например, пульсометр)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Приложение получит доступ к данным приборов, используемых для измерения ваших физиологических показателей (например, пульса)."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"Просмотр записей в вашей социальной ленте"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Приложение сможет просматривать и синхронизировать записи, публикуемые вами и вашими друзьями в социальных сетях. Будьте осторожны при передаче информации! С этим разрешением приложение сможет просматривать вашу переписку с друзьями в социальных сетях независимо от настроек конфиденциальности. Примечание. Это разрешение может применяться не во всех социальных сетях."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"Добавление записей в вашу социальную ленту"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Изменение статуса WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Приложение сможет подключать устройство к сетям WiMAX и отключать его от них."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Приложение сможет подключать устройство к сетям WiMAX и отключать его от них."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"Определение рейтинга сетей"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Приложение сможет присваивать сетям рейтинг и решать, к каким из них устройство должно подключаться в первую очередь."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Приложение сможет присваивать сетям рейтинг и решать, к каким из них устройство должно подключаться в первую очередь."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Установление связи с устройствами Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Приложение сможет просматривать конфигурацию Bluetooth на планшетном ПК, а также запрашивать и подтверждать соединение с другими устройствами."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Приложение сможет просматривать конфигурацию Bluetooth на телефоне, а также запрашивать и подтверждать соединение с другими устройствами."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Приложение сможет получать, проверять и удалять уведомления, включая те, что опубликованы другими приложениями."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"Подключение к службе просмотра уведомлений"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Приложение сможет подключаться к базовому интерфейсу службы просмотра уведомлений. Это разрешение не используется обычными приложениями."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"Подключение к серверам поставщиков условий"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Приложение сможет подключаться к базовому интерфейсу поставщиков условий. Это разрешение обычно используется только специальными приложениями."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"Запуск приложения настроек, предоставленного оператором"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Владелец сможет запускать приложение настроек, предоставленное оператором. Это разрешение не используется обычными приложениями."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Использование данных о состоянии сети"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновый рисунок"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Сменить обои"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба просмотра уведомлений"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Поставщик условий"</string>
     <string name="vpn_title" msgid="19615213552042827">"Сеть VPN активна"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Сеть VPN активирована приложением <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Нажмите, чтобы открыть настройки."</string>
diff --git a/core/res/res/values-sk/strings.xml b/core/res/res/values-sk/strings.xml
index 707bdf1..c96c661 100644
--- a/core/res/res/values-sk/strings.xml
+++ b/core/res/res/values-sk/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Bez mena&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synchronizovať"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Príliš veľa odstránených položiek služby <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Ukladací priestor tabletu je plný. Odstráňte niektoré súbory a uvoľnite miesto."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Ukladací priestor hodiniek je plný. Uvoľnite miesto odstránením niektorých súborov."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Pamäť telefónu je plná. Odstráňte niektoré súbory a uvoľnite miesto."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Sieť môže byť monitorovaná"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Neznámou treťou stranou"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Zvonenie je zapnuté"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Prebieha vypínanie..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Váš tablet bude vypnutý."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Hodinky sa vypnú."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Váš telefón bude vypnutý."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Chcete zariadenie vypnúť?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Reštartovať do núdzového režimu"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Režim V lietadle"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Režim V lietadle je ZAPNUTÝ"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Režim V lietadle je VYPNUTÝ"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Nastavenia"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Núdzový režim"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Systém Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Umožňuje aplikácii načítať obsah aktívneho okna. Škodlivé aplikácie môžu získať celý obsah okna a preskúmať celý jeho text okrem hesiel."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"dočasné povolenie zjednodušenia ovládania"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Umožňuje aplikácii dočasne povoliť zjednodušenie ovládania v zariadení. Škodlivé aplikáciu môžu zjednodušenie ovládania povoliť bez súhlasu používateľa."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"získať token okna"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Umožňuje aplikácii získať token okna. Škodlivé aplikácie sa môžu správať ako systém a vykonať neautorizovanú interakciu s oknom aplikácie."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"získať štatistiky rámcov"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Umožňuje aplikácii zhromažďovať štatistiky rámcov. Škodlivé aplikácie môžu sledovať štatistiky rámcov okien z iných aplikácií."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrovanie udalostí"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Umožňuje aplikácii zaregistrovať vstupný filter, ktorý filtruje stream všetkých prenosov používateľa pred ich odvysielaním. Škodlivá aplikácia môže bez zásahu používateľa ovládať používateľské rozhranie systému."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Čiastočné vypnutie"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Umožňuje aplikácii vysielať oznámenie, že správa SMS bola doručená. Škodlivé aplikácie môžu toto nastavenie použiť na falšovanie prichádzajúcich správ SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"odoslanie vysielania typu WAP-PUSH-received"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Umožňuje aplikácii vysielať oznámenie, že správa WAP PUSH bola doručená. Škodlivé aplikácie môžu použiť toto nastavenie na vytvorenie potvrdenia o doručení správy MMS alebo na utajené nahradenie obsahu akejkoľvek stránky škodlivými variantmi."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"odoslanie skóre vysielaných sieťami"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Umožňuje aplikácii vysielať upozornenie, že je potrebné zadať skóre sietí. Bežné aplikácie toto povolenie nepotrebujú."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"obmedzenie počtu spustených procesov"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Umožňuje aplikácii kontrolovať maximálny počet spustených procesov. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vynútiť zavretie aplikácií na pozadí"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby VPN. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"väzba na tapetu"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania tapety. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"viazať na vzdialený displej"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania vzdialeného displeja. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"viazať sa k službe miniaplikácie"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania služby miniaplikácií. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"viazanie na službu poskytovateľa cesty"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Umožňuje držiteľovi viazať sa na akýchkoľvek registrovaných poskytovateľov cesty. Normálne aplikácie by toto povolenie nemali nikdy nepotrebovať."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"komunikovať so správcom zariadenia"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Umožňuje držiteľovi odosielať informácie správcovi zariadenia. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"viazanie na televízny vstup"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Umožňuje držiteľovi viazať sa na najvyššiu úroveň rozhrania televízneho vstupu. Bežné aplikácie by toto nastavenie nemali nikdy potrebovať."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"pridanie alebo odstránenie správcu zariadenia"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Umožňuje držiteľovi pridať alebo odstrániť správcov aktívnych zariadení. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"zmena orientácie obrazovky"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Umožňuje aplikácii čítať informácie v osobnom profile uložené v zariadení, ako je vaše meno a kontaktné informácie. Znamená to, že vás ostatné aplikácie môžu identifikovať a odoslať informácie o vašom profile iným aplikáciám."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"upraviť vlastnú kartu kontaktu"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Umožňuje aplikácii zmeniť alebo pridať do osobného profilu informácie uložené vo vašom zariadení, ako je vaše meno a kontaktné informácie. Znamená to, že vás aplikácia môže identifikovať a odoslať informácie o vašom profile ostatným aplikáciám."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"telesné senzory (napr. snímače tepu)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Umožňuje aplikácii pristupovať k údajom zo senzorov, pomocou ktorých meriate činnosť svojho tela, napríklad tep."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"čítať váš sociálny stream"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Umožňuje aplikácii pristupovať k sociálnym aktualizáciám od vás a vašich priateľov a synchronizovať ich. Pri zdieľaní informácií dávajte pozor – toto povolenie umožňuje aplikácii čítať komunikáciu medzi vami a vašimi priateľmi v sociálnych sieťach, a to bez ohľadu na jej dôvernosť. Poznámka: Toto povolenie nie je možné vynucovať v prípade všetkých sociálnych sietí."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"písať do vášho sociálneho streamu"</string>
@@ -542,9 +583,9 @@
     <string name="permdesc_accessMtp" msgid="6532961200486791570">"Povoľuje prístup k ovládaču kernel MTP na implementáciu protokolu MTP USB."</string>
     <string name="permlab_hardware_test" msgid="4148290860400659146">"testovanie hardvéru"</string>
     <string name="permdesc_hardware_test" msgid="6597964191208016605">"Umožňuje aplikácii ovládať rôzne periférie na účely testovania hardvéru."</string>
-    <string name="permlab_callPhone" msgid="3925836347681847954">"priame volanie na telefónne čísla"</string>
+    <string name="permlab_callPhone" msgid="3925836347681847954">"priamo volať na telefónne čísla"</string>
     <string name="permdesc_callPhone" msgid="3740797576113760827">"Umožňuje aplikácii volať telefónne čísla bez vášho zásahu. V dôsledku toho sa môžu účtovať neočakávané poplatky alebo sa môžu uskutočniť neočakávané hovory. Toto povolenie neumožňuje aplikácii volať na čísla tiesňového volania."</string>
-    <string name="permlab_callPrivileged" msgid="4198349211108497879">"priame volanie na ľubovoľné telefónne čísla"</string>
+    <string name="permlab_callPrivileged" msgid="4198349211108497879">"priamo volať na ľubovoľné telefónne čísla"</string>
     <string name="permdesc_callPrivileged" msgid="1689024901509996810">"Umožňuje aplikácii volať na akékoľvek telefónne číslo (bez vášho zásahu) vrátane čísiel tiesňového volania. Škodlivé aplikácie môžu uskutočňovať zbytočné a nezákonné volania na tiesňové linky."</string>
     <string name="permlab_performCdmaProvisioning" product="tablet" msgid="4842576994144604821">"priamo spustiť nastavenie tabletu CDMA"</string>
     <string name="permlab_performCdmaProvisioning" product="default" msgid="5604848095315421425">"priamo spustiť nastavenie telefónu CDMA"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Zmeniť stav siete WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Umožňuje aplikácii pripojiť tablet k sieťam WiMAX a odpojiť ho od nich."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Umožňuje aplikácii pripojiť telefón k sieťam WiMAX a odpojiť ho od nich."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"zadanie skóre sietí"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Umožňuje aplikácii hodnotiť siete a ovplyvňovať, ktoré siete by mal tablet preferovať."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Umožňuje aplikácii hodnotiť siete a ovplyvňovať, ktoré siete by mal telefón preferovať."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"párovať so zariadeniami Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na tablete. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Umožňuje aplikácii zobraziť informácie o konfigurácii Bluetooth na telefóne. Taktiež jej umožňuje nadväzovať a akceptovať spojenia so spárovanými zariadeniami."</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Umožňuje aplikácii načítať, zobrazovať a mazať upozornenia vrátane tých, ktoré boli uverejnené inými aplikáciami."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"naviazanie sa na službu na počúvanie upozornení"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Umožňuje držiteľovi naviazať sa na najvyššiu úroveň služby na počúvanie upozornení. Bežné aplikácie by toto nastavenie nemali nikdy požadovať."</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"vyvolanie aplikácie pre konfiguráciu poskytnutú operátorom"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Umožňuje držiteľovi vyvolať aplikáciu pre konfiguráciu poskytnutú operátorom. Bežné aplikácie by toto povolenie nemali nikdy potrebovať."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"zachytávať informácie o stave siete"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Tapeta"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Zmeniť tapetu"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Aplikácia na počúvanie upozornení"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"Sieť VPN je aktivovaná"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Aplikáciu <xliff:g id="APP">%s</xliff:g> aktivovala sieť VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotykom môžete spravovať sieť."</string>
diff --git a/core/res/res/values-sl/strings.xml b/core/res/res/values-sl/strings.xml
index e93b128..ef5d872 100644
--- a/core/res/res/values-sl/strings.xml
+++ b/core/res/res/values-sl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Brez naslova&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sinhronizacija"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Preveč izbrisov vsebine <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Pomnilnik tabličnega računalnika je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Shramba ure je polna. Izbrišite nekaj datotek, da sprostite prostor."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Pomnilnik telefona je poln. Izbrišite nekaj datotek, da sprostite prostor."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Omrežje je lahko nadzorovano"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Neznana tretja oseba"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Vklopi zvonjenje"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Se zaustavlja ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tablični računalnik se bo zaustavil."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ura se bo izklopila."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefon bo zaustavljen."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Ali želite izklopiti napravo?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Vnovičen zagon v varnem načinu"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Način za letalo"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Način za letalo je VKLOPLJEN"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Način za letalo je IZKLOPLJEN"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Nastavitve"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999 +"</string>
     <string name="safeMode" msgid="2788228061547930246">"Varni način"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Sistem Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Programu omogoča dostop do vsebine aktivnega okna. Zlonamerni programi lahko dobijo vso vsebino okna in pregledajo njeno besedilo razen gesel."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"začasno omogoči pripomočke za ljudi s posebnimi potrebami"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Aplikaciji omogoča, da v napravi začasno omogoči pripomočke za ljudi s posebnimi potrebami. Zlonamerne aplikacije jih lahko omogočijo brez soglasja uporabnika."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"pridobivanje žetona okna"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Aplikaciji dovoli, da pridobi žeton okna. Zlonamerne aplikacije lahko z oknom aplikacije vzpostavijo stik brez pooblastila in se lažno predstavljajo kot sistem."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"pridobivanje statističnih podatkov o okvirjih"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Aplikaciji dovoli, da zbira statistične podatke o okvirjih. Zlonamerne aplikacije lahko vidijo statistične podatke o okvirjih oken iz drugih aplikacij."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtriranje dogodkov"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Omogoča, da aplikacija registrira vhodni filter, ki pred razpošiljanjem filtrira tok vseh uporabniških dogodkov. Zlonamerne aplikacije lahko nadzirajo uporabniški vmesnik sistema brez posega uporabnika."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"delna zaustavitev"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Programu omogoča oddajo obvestila o prejetih sporočilih SMS. Zlonamerni programi lahko to uporabijo za ponarejanje dohodnih SMS-ov."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"pošiljanje oddaje, prejete s potisnim sporočilom WAP"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Programu omogoča oddajo obvestila, da je bilo potisno sporočilo WAP prejeto. Zlonamerni programi lahko to uporabijo za ponarejanje potrdila o prejemu sporočila MMS ali za neopazno menjavo vsebine poljubne spletne strani z zlonamernimi različicami."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"pošiljanje oddaj o ocenjevanju omrežij"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Aplikaciji dovoli oddajo obvestila, da je treba omrežja oceniti. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"omejevanje števila izvajajočih se procesov"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Programu omogoča nadzor največjega števila postopkov, ki se bodo izvajali. Tega nikoli ni treba uporabiti za navadne programe."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"vsiljeno zapiranje aplikacij v ozadju"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Lastniku omogoča povezovanje z vmesnikom storitve navideznega zasebnega omrežja najvišje ravni. Ne uporabljajte za navadne programe."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"povezovanje z ozadjem"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Imetniku omogoča povezavo z vmesnikom ozadja najvišje ravni. Tega nikoli ni treba uporabiti za navadne programe."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"povezovanje z glasovnim interaktorjem"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Imetniku omogoča povezovanje z vmesnikom storitve glasovne interakcije najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"povezava z oddaljenim prikazom"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Imetniku omogoča povezovanje z vmesnikom oddaljenega prikaza najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"poveži s storitvijo pripomočka"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Lastniku omogoča povezovanje z vmesnikom storitve pripomočka najvišje ravni. Tega ni treba nikoli uporabiti za navadne programe."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"Povezava s storitvijo ponudnika poti"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Omogoča imetniku, da se povezuje z registriranimi ponudniki poti. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"interakcija s skrbnikom naprave"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Omogoča lastniku, da pošlje namere skrbniku naprave. Nikoli se ne uporablja za navadne programe."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"povezava s TV-vhodom"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Imetniku omogoča povezovanje z vmesnikom TV-vhoda najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"dodajanje ali odstranjevanje skrbnikov naprave"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Imetniku omogoča, da doda ali odstrani aktivne skrbnike naprave. Normalne aplikacije tega načeloma ne potrebujejo."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"spreminjanje usmerjenosti zaslona"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Aplikaciji omogoča branje osebnih podatkov v profilu, ki so shranjeni v napravi, na primer ime in podatki za stik. To pomeni, da vas lahko aplikacija prepozna in vaše podatke v profilu pošlje drugim."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"spreminj. vaše osebne vizitke"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Aplikaciji omogoča spreminjanje ali dodajanje osebnih podatkov v profilu, ki so shranjeni v napravi, na primer ime in podatki za stik. To pomeni, da vas lahko aplikacija prepozna in vaše podatke v profilu pošlje drugim."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"tipala telesnih funkcij (npr. merilniki srčnega utripa)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Aplikaciji dovoli dostop do podatkov tipal, ki jih uporabljate za merjenje procesov v telesu, kot je srčni utrip."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"branje vašega družabnega toka"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Aplikaciji omogoča dostop do vaših objav in objav vaših prijateljev v družabnih omrežjih ter njihovo sinhronizacijo. Previdno pri objavljanju informacij – aplikacija lahko s tem bere komunikacijo med vami in prijatelji v družabnih omrežjih, ne glede na zasebnost. Opomba: Tega dovoljenja ni mogoče uveljaviti v vseh družabnih omrežjih."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"pisanje v vaš družabni tok"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Sprememba stanja omrežja WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Aplikaciji omogoča, da vzpostavi povezavo med tabličnim računalnikom in omrežjem WiMAX ter jo prekine."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Aplikaciji omogoča, da vzpostavi povezavo med telefonom in omrežjem WiMAX ter jo prekine."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ocenjevanje omrežij"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Aplikaciji dovoli, da omrežja razvršča in vpliva na to, katera naj tablični računalnik prednostno izbere."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Aplikaciji dovoli, da omrežja razvršča in vpliva na to, katera naj telefon prednostno izbere."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"seznanitev z napravami Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Aplikaciji omogoča ogled konfiguracije Bluetootha tabličnega računalnika ter vzpostavljanje in sprejemanje povezave s seznanjenimi napravami."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Aplikaciji omogoča ogled konfiguracije Bluetootha telefona ter ustvarjanje in sprejemanje povezave s seznanjenimi napravami."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Dovoli aplikaciji, da prenese, razišče in izbriše obvestila, tudi tista, ki so jih objavile druge aplikacije."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"poveži se s storitvijo poslušalca obvestil"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Lastniku omogoča povezovanje z vmesnikom storitve poslušalca obvestil najvišje ravni. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"povezovanje s storitvijo ponudnika pogojev"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Imetniku omogoča povezovanje z vmesnikom storitve ponudnika pogojev najvišje ravni. Tega ni treba nikoli uporabiti za navadne aplikacije."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"sprožitev operaterjeve aplikacije za konfiguracijo"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Lastniku omogoča sproženje operaterjeve aplikacije za konfiguracijo. Tega nikoli ni treba uporabiti za navadne aplikacije."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"spremljanje razmer v omrežju"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Ozadje"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Spreminjanje ozadja"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Poslušalec obvestil"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Ponudnik pogojev"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN aktiviran"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN je aktiviral program <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Dotaknite se, če želite upravljati omrežje."</string>
diff --git a/core/res/res/values-sr/strings.xml b/core/res/res/values-sr/strings.xml
index b2928e4..b87bd89 100644
--- a/core/res/res/values-sr/strings.xml
+++ b/core/res/res/values-sr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без наслова&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхронизација"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Превише <xliff:g id="CONTENT_TYPE">%s</xliff:g> избрисаних ставки."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Меморија таблета је пуна! Избришите неке датотеке да бисте ослободили простор."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Меморија сата је пуна. Избришите неке датотеке да бисте ослободили простор."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Складиште телефона је пуно! Избришите неке датотеке како бисте ослободили простор."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мрежа се можда надгледа"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Од стране непознате треће стране"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Звоно је укључено"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Искључивање…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Таблет ће се искључити."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Сат ће се угасити."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Телефон ће се искључити."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Да ли желите да искључите телефон?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Поново покрени систем у безбедном режиму"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим рада у авиону"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим рада у авиону је УКЉУЧЕН"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим рада у авиону је ИСКЉУЧЕН"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Подешавања"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безбедни режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android систем"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозвољава апликацији да преузме садржај активног прозора. Злонамерне апликације могу да преузму цео садржај прозора и прегледају целокупан текст, осим лозинки."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"привремено омогућавање приступачности"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозвољава апликацији да привремено омогући приступачност на уређају. Злонамерне апликације могу да омогуће приступачност без дозволе корисника."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"преузимање токена прозора"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Дозвољава апликацији да преузима токен прозора. Злонамерне апликације могу да ступе у неовлашћену интеракцију са прозором апликације лажно се представљајући као систем."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"преузимње статистике оквира"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Дозвољава апликацији да прикупља статистику о оквиру. Злонамерне апликације могу да прате статистику оквира прозора из других апликација."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"филтрирање догађаја"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Омогућава апликацији да региструје филтер улазног садржаја који филтрира стрим свих догађаја корисника пре њиховог слања. Злонамерна апликација може да контролише кориснички интерфејс система без интервенције корисника."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"делимично искључивање"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Дозвољава апликацији да емитује обавештење да је SMS порука примљена. Злонамерне апликације на тај начин могу да фалсификују долазне SMS поруке."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"слање примљених PUSH емитовања преко WAP-а"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозвољава апликацији да емитује обавештење да је примљена PUSH порука преко WAP-а. Злонамерне апликације то могу да искористе да фалсификују пријем MMS порука или да кришом замене садржај било које веб-странице уносом злонамерног садржаја."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"шаљи обавештења о тестирању мрежа"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Омогућава апликацији да емитује обавештење да је потребно тестирање мрежа. Никада није потребно за стандардне апликације."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"ограничење броја покренутих процеса"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозвољава апликацији да управља максималним бројем процеса који ће моћи да се покрену. Никада није потребна уобичајеним апликацијама."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"принудно затварање позадинских апликација"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозвољава власнику да се повеже са интерфејсом VPN услуге највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"обавезивање на позадину"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозвољава власнику да се повеже са интерфејсом позадине највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"повежи са гласовним интерактором"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа услуге гласовне интеракције. Не би требало никада да буде потребно за уобичајене апликације."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"повезивање са удаљеним екраном"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозвољава власнику да се повеже са интерфејсом удаљеног екрана највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"обавезивање на услугу виџета"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозвољава власнику да се обавеже на интерфејс услуге виџета највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"повежи са услугом добављача путања"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Дозвољава власнику да се повеже са добављачима путања. Никада не би требало да буде потребно за обичне апликације."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"интеракција са администратором уређаја"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Омогућава да власник шаље своје намере администратору уређаја. Уобичајене апликације никада не би требало да је користе."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"повезивање са ТВ улазом"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Дозвољава власнику да се повеже са интерфејсом ТВ улаза највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавање или уклањање администратора уређаја"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозвољава власнику да додаје или уклања активне администраторе уређаја. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"промена положаја екрана"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Дозвољава апликацији да чита личне информације о профилу ускладиштене на уређају, као што су име и контакт информације. То значи да апликација може да вас идентификује и шаље другима информације о профилу."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"измена ваше контакт картице"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Дозвољава апликацији да мења или додаје нове личне информације о профилу ускладиштене на уређају, као што су име и контакт информације. То значи да апликација може да вас идентификује и шаље другима информације о профилу."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"телесни сензори (нпр. срчани монитор)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Дозвољава апликацији да приступа подацима сензора које користите за мерење телесних функција, као што је срчани пулс."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"читање друштвеног стрима"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Дозвољава апликацији да приступа вашим друштвеним ажурирањима и друштвеним ажурирањима пријатеља и да их синхронизује. Будите опрезни када делите информације – ово омогућава апликацији да чита преписке између вас и пријатеља на друштвеним мрежама, без обзира на поверљивост. Напомена: Ова дозвола се можда не примењује на све друштвене мреже."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писање у друштвени стрим"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Промени WiMAX статус"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозвољава апликацији да повезује таблет са WiMAX мрежама и прекида везе са њима."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Дозвољава апликацији да повезује телефон са WiMAX мрежама и прекида везе са њима."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"тестирај мреже"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Омогућава апликацији да рангира мреже и утиче на то које су мреже примарне на таблету."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Омогућава апликацији да рангира мреже и утиче на то које су мреже примарне на телефону."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"упаривање са Bluetooth уређајима"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на таблету, као и да успоставља и прихвата везе са упареним уређајима."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Дозвољава апликацији да прегледа конфигурацију Bluetooth-а на телефону, као и да успоставља и прихвата везе са упареним уређајима."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозвољава апликацији да преузима, испитује и брише обавештења, укључујући она која постављају друге апликације."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"повезивање са услугом монитора обавештења"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозвољава власнику да се повеже са интерфејсом услуге монитора обавештења највишег нивоа. Уобичајене апликације никада не би требало да је користе."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"повежи са услугом добављача услова"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Дозвољава власнику да се повеже са интерфејсом највишег нивоа услуге добављача услова. Не би требало никада да буде потребно за уобичајене апликације."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"позивање апликације са конфигурацијом коју одређује оператер"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозвољава власнику да позива апликацију са конфигурацијом коју одређује оператер. Уобичајене апликације никада не би требало да је користе."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"праћење података о условима на мрежи"</string>
@@ -882,7 +926,7 @@
     <string name="lockscreen_glogin_forgot_pattern" msgid="2588521501166032747">"Откључавање налога"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="2751368605287288808">"Превише покушаја уноса шаблона"</string>
     <string name="lockscreen_glogin_instructions" msgid="3931816256100707784">"Да бисте откључали, пријавите се помоћу Google налога."</string>
-    <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Корисничко име (адреса е-поште)"</string>
+    <string name="lockscreen_glogin_username_hint" msgid="8846881424106484447">"Корисничко име (имејл адреса)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="5958028383954738528">"Лозинка"</string>
     <string name="lockscreen_glogin_submit_button" msgid="7130893694795786300">"Пријави ме"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="1364051473347485908">"Неважеће корисничко име или лозинка."</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Позадина"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Промена позадине"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Монитор обавештења"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Добављач услова"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN је активиран"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Апликација <xliff:g id="APP">%s</xliff:g> је активирала VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Додирните да бисте управљали мрежом."</string>
@@ -1539,7 +1584,7 @@
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN кодови се не подударају"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Превише покушаја уноса шаблона"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"Да бисте откључали, пријавите се помоћу Google налога."</string>
-    <string name="kg_login_username_hint" msgid="5718534272070920364">"Корисничко име (адреса е-поште)"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Корисничко име (имејл адреса)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"Лозинка"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"Пријави ме"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неважеће корисничко име или лозинка."</string>
diff --git a/core/res/res/values-sv/strings.xml b/core/res/res/values-sv/strings.xml
index b134a85..9b4dae3 100644
--- a/core/res/res/values-sv/strings.xml
+++ b/core/res/res/values-sv/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Okänd&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Synkronisera"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"För många <xliff:g id="CONTENT_TYPE">%s</xliff:g>-borttagningar."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Pekdatorns lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Klockans lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Mobilens lagringsutrymme är fullt. Ta bort några filer för att frigöra utrymme."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Nätverket kan vara övervakat"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Av en okänd tredje part"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Ringsignal på"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Avslutar…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Din surfplatta stängs av."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Klockan stängs av."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Din telefon stängs av."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Vill du stänga av?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Starta om i felsäkert läge"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Flygplansläge"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Flygplansläge är AKTIVERAT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Flygplansläge är INAKTIVERAT"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Inställningar"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Säkert läge"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android-system"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Tillåter att appen hämtar innehållet i det aktiva fönstret. Skadliga appar kan hämta allt innehåll i fönstret och läsa all text utom lösenord."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"aktivera tillgänglighetsläget tillfälligt"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Tillåt att en app tillfälligt aktiverar tillgänglighetsläget på enheten. Skadliga appar kan aktivera tillgänglighetsläget utan användarens medgivande."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"hämta fönstrets token"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Appen tillåts hämta fönstrets token. Skadliga appar kan interagera med appens fönster på ett otillåtet sätt och efterlikna systemet."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"hämta ramstatistik"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Appen tillåts samla in ramstatistik. Skadliga appar kan registrera statistik om ramar i andra appars fönster."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"filtrera händelser"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Tillåter att appen registrerar indatafilter som filtrerar flödet med användarhändelser innan de skickas. Skadliga appar kan styra systemets användargränssnitt utan att användaren gör något."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"avsluta delvis"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Tillåter att appen sänder ut en avisering när SMS tas emot. Skadliga appar kan använda detta för att förfalska inkommande SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"skicka WAP-PUSH-mottagen sändning"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Tillåter att appen skickar ett meddelande om att ett WAP PUSH-meddelande har tagits emot. Skadliga appar kan använda detta för att förfalska mottagning av MMS eller för att obemärkt byta ut innehållet på en webbsida mot skadligt innehåll."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"skicka betyg som nätverk skickar"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Tillåter att appen skickar ett meddelande om att nätverket måste betygsättas. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"begränsa antalet processer som körs"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Tillåter att appen styr högsta antalet processer som körs. Behövs inte för vanliga appar."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"tvinga bakgrundsappar att avslutas"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en VPN-tjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"binda till en bakgrund"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Innehavaren kan binda till den översta nivåns gränssnitt för en bakgrund. Ska inte behövas för vanliga appar."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bind till en röstkomponent"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en rösttjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bind till en fjärrskärm"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en fjärrskärm. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bind till en widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en widget. Ska inte behövas för vanliga appar."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bind till en ruttleverantörstjänst"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Tillåter att innehavaren binds till en registrerad ruttleverantör. Detta ska inte behövas för vanliga appar."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"arbeta med en enhetsadministratör"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Tillåter att innehavaren skickar avsikter till en enhetsadministratör. Vanliga appar behöver aldrig göra detta."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"binda till en tv-insignal"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en tv-insignal. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"lägga till eller ta bort en enhetsadministratör"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Innehavaren får lägga till eller ta bort aktiva enhetsadministratörer. Detta ska normalt inte behövas för vanliga appar."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ändra bildskärmens rikting"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Tillåter att appen läser personliga profiluppgifter som sparats på din enhet, t.ex. ditt namn och kontaktuppgifter. Det innebär att appen kan identifiera dig och skicka profiluppgifter till andra."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"ändra ditt eget kontaktkort"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Tillåter att appen ändrar eller lägger till personliga profiluppgifter som sparats på din enhet, till exempel ditt namn och dina kontaktuppgifter. Det innebär att appen kan identifiera dig och skicka profiluppgifter till andra."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"kroppssens. (för hjärtat m.m.)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Tillåter att appen får åtkomst till data från sensorer som används för att mäta vad som sker inuti kroppen, till exempel hjärtfrekvens."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"läs mitt sociala flöde"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Tillåter att appen kommer åt och synkroniserar sociala uppdateringar från dig och dina vänner. Var försiktig när du delar information – med den här behörigheten tillåts appen att läsa kommunikation mellan dig och dina vänner på sociala nätverk oavsett sekretessnivå. Observera att den här behörigheten kanske inte är tillämplig på alla sociala nätverk."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"skriv till mitt sociala flöde"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"ändra WiMAX-status"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Tillåter att appen ansluter surfplattan till eller kopplar från WiMAX-nätverk."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Tillåter att appen ansluter mobilen till eller kopplar från WiMAX-nätverk."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"betygsätt nätverk"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Tillåter att appen betygsätter nätverk och påverkar vilka nätverk som ska användas i första hand av surfplattan."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Tillåter att appen betygsätter nätverk och påverkar vilka nätverk som ska användas i första hand av mobilen."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"koppla till Bluetooth-enheter"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Tillåter att appen kommer åt pekdatorns Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Tillåter att appen kommer åt mobilens Bluetooth-konfiguration och upprättar och godkänner anslutningar till parkopplade enheter."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Tillåter att appen hämtar, granskar och raderar meddelanden, även sådana som skickats av andra appar."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"binda till en meddelandelyssnare"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en meddelandelyssnare. Ska inte behövas för vanliga appar."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bind till en leverantörstjänst"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Innehavaren tillåts att binda till den översta nivåns gränssnitt för en leverantörstjänst. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"anropa konfigurationsappen från operatören"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Innehavaren tillåts att anropa konfigurationsappen från operatören. Ska inte behövas för vanliga appar."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"lyssna efter information om nätverksförhållanden"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Bakgrund"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Ändra bakgrund"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Meddelandelyssnare"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Leverantör"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN är aktiverat"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN aktiveras av <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Tryck om du vill hantera nätverket."</string>
diff --git a/core/res/res/values-sw/strings.xml b/core/res/res/values-sw/strings.xml
index 8f319f3..558cae2 100644
--- a/core/res/res/values-sw/strings.xml
+++ b/core/res/res/values-sw/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Haina jina&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Sawazisha"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Ufutaji mwingi sana <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Hifadhi ya kompyuta kibao imejaa. Futa baadhi ya faili ili kupata nafasi."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Hifadhi ya saa imejaa. Futa baadhi ya faili ili uweze kupata nafasi."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Hifadhi ya simu imejaa. Futa baadhi ya faili ili uweze kupata nafasi."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Huenda mtandao unafuatiliwa"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Na mtu mwingine asiyejulikana"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Programu ya milio imewashwa"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Inafunga..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Kompyuta kibao yako itazima."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Saa yako itajizima."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Simu yako itazima."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Unataka kuzima?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Washa upya kwa hali salama"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Hali ya ndege"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Hali ya ndege IMEWASHWA"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Hali ya ndege IMEZIMWA"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Mipangilio"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Mtindo salama"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Mfumo wa Android"</string>
@@ -251,7 +276,7 @@
     <string name="permdesc_statusBarService" msgid="716113660795976060">"Inaruhusu programu kuwa upau wa hali."</string>
     <string name="permlab_expandStatusBar" msgid="1148198785937489264">"panua/kunja mwambaa hali"</string>
     <string name="permdesc_expandStatusBar" msgid="6917549437129401132">"Inaruhusu programu kupanua au kukunja upau wa hali."</string>
-    <string name="permlab_install_shortcut" msgid="4279070216371564234">"sakinisha njia za mkato"</string>
+    <string name="permlab_install_shortcut" msgid="4279070216371564234">"kuweka njia za mkato"</string>
     <string name="permdesc_install_shortcut" msgid="8341295916286736996">"Huruhusu programu kuongeza njia za mkato za Skrini ya kwanza bila mtumiaji kuingilia."</string>
     <string name="permlab_uninstall_shortcut" msgid="4729634524044003699">"ondoa njia za mikato"</string>
     <string name="permdesc_uninstall_shortcut" msgid="6745743474265057975">"Huruhusu programu kuondoa njia za mkato za Skrini ya kwanza bila mtumiaji kuingilia."</string>
@@ -279,7 +304,7 @@
     <string name="permdesc_receiveWapPush" msgid="748232190220583385">"Inaruhusu programu kupokea na kuchakata ujumbe wa WAP. Idhini hii inajumuisha uwezo wa kuchunguza na kufuta ujumbe uliotumwa kwako bila ya kukuonyesha."</string>
     <string name="permlab_getTasks" msgid="6466095396623933906">"rudisha programu zinazoendeshwa"</string>
     <string name="permdesc_getTasks" msgid="7454215995847658102">"Inaruhusu programu kurudisha taarifa kuhusu kazi zinazoendeshwa sasa na hivi karibuni. Hii inaweza kuruhusu programu kugundua taarifa kuhusu ni programu zipi zinazotumika kwenye kifaa."</string>
-    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"Tagusana na watumiaji"</string>
+    <string name="permlab_interactAcrossUsers" msgid="7114255281944211682">"kuwasiliana na watumiaji wengine"</string>
     <string name="permdesc_interactAcrossUsers" msgid="364670963623385786">"Inaruhusu programu kutenda vitendo kwa watumiaji tofauti kwenye kifaa. Programu hasidi huenda zikatumia hii ili kukiuka ulinzi kati ya watumiaji."</string>
     <string name="permlab_interactAcrossUsersFull" msgid="2567734285545074105">"leseni kamili ili kushirikiana na watumiaji"</string>
     <string name="permdesc_interactAcrossUsersFull" msgid="376841368395502366">"Inaruhusu miingialiano yote inayowezekana kwa watumiaji."</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Inaruhusu programu kutoa maudhui ya dirisha amilifu. Programu hasidi zinaweza kutoa maudhui yote ya dirisha na kuchunguza maandishi yake yote isipokuwa nenosiri."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"wezesha ufikivu kwa muda"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Inaruhusu programu kuwezesha kwa muda ufikivu kwenye kifaa. Huenda programu hasidi zikawezesha ufikivu bila kibali cha mtumiaji."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"rejesha tokeni ya dirisha"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Inaruhusu programu kurejesha tokeni ya dirisha. Programu hasidi zinaweza kutekeleza mwingiliano usioidhinishwa na dirisha la programu zikiiga mfumo."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"rejesha takwimu za fremu"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Inaruhusu programu kukusanya takwimu za fremu. Programu hasidi zinaweza kuchunguza takwimu za fremu za dirisha kutoka kwenye programu zingine."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"chuja matukio"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Huruhusu programu kusajili kichujio ingizo kinachochuja mkondo wa matukio ya mtumiaji kabla ya kutumwa. Huenda programu hasidi ikadhibiti mfumo wa UI bila mtumiaji kuingilia kati."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"Zima nusu"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Huruhusu programu kutangaza taarifa kwamba ujumbe wa SMS umeingia. Programu hasidi zinaweza kutumia hii kubuni SMS zinazoingia."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"tuma tangazo lililopokewa la MSUKUMO WA WAP"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Inaruhusu programu kutangaza taarifa kwamba ujumbe wa WAP PUSH umepokewa. Programu hasidi zinaweza kutumia hii kubuni risiti ya ujumbe wa MMS au polepole kubadilisha maudhui yoyote ya ukurasa wa tovuti na vibadala vibovu."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"tuma tangazo la alama za mitandao"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Huruhusu programu kutangaza arifa kuwa mitandao inafaa kupewa alama. Haihitajiki kamwe kwa programu za kawaida."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"zuia idadi ya michakato inayoendeshwa"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Inaruhusu programu kudhibiti upeo wa idadi ya michakato ambayo itaendeshwa. Kamwe hazihitajiki kwa programu za kwaida."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"lazimisha programu za usuli kufunga"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Inaruhusu kishikiliaji kushurutisha kusano ya kiwango cha juu cha huduma ya Vpn. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"funga kwa mandhari"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Inaruhusu kishikiliaji kushurutisha kwa kusano ya kiwango cha juu cha mandhari. Haipaswi kamwe kuhitajika kwa programu za kawaida."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"shurutisha kwa muingiliano wa sauti"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Humruhusu mmiliki kushurutisha kwa kiolesura cha hali ya juu cha huduma ya muingiliano wa sauti. Kamwe isihitajike kwa programu za kawaida."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"fungisha kwenye mwonekano wa mbali"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Huruhusu mtumiaji kujifungia kiolesura cha kiwango cha juu cha mwonekano wa mbali. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"funga kwenye huduma ya widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Inaruhusu mmiliki kushurutisha kusano ya kiwango cha juu ya huduma ya wijeti. Haipaswi kuhitajika kwa programu za kawaida."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bandika kwenye huduma ya mtoa huduma za njia"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Huruhusu mmiliki kubandika kwenye watoa huduma za njia waliosajiliwa. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"jiunge na msimamizi wa kifaa"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Inamruhusu mmiliki kutuma malengo kwa msimamizi wa kifaa. Haipaswi kuhitajika kwa programu za kawaida."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bandika kwenye zana za data ya runinga"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Inaruhusu kishikiliaji kubandika kwenye kusano la kiwango cha juu cha zana za data kwenye runinga. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"ongeza au ondoa msimamizi wa kifaa"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Inaruhusu mmiliki kuongeza au kuondoa wasimamizi wa kifaa waliopo. Kamwe kisihitajike kwa ajili ya programu za kawaida."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"badilisha uelekezo wa skrini"</string>
@@ -401,15 +438,15 @@
     <string name="permdesc_deletePackages" msgid="7411480275167205081">"Inaruhusu programu kufuta furushi za Android. Programu hasidi zinaweza kutumia hii kufuta programu muhimu."</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"Futa data za programu zingine"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"Inaruhusu programu kufuta data ya mtumiaji."</string>
-    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"Futa kache za programu zingine"</string>
-    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Inaruhusu programu kufuta faili za kache."</string>
+    <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"Kufuta akiba za programu zingine"</string>
+    <string name="permdesc_deleteCacheFiles" msgid="3812998599006730196">"Huruhusu programu kufuta faili za akiba."</string>
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"Pima nafasi ya hifadhi ya programu"</string>
-    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Inaruhusu Programu kupata tena msimbo, data na ukubwa wa kache yake."</string>
+    <string name="permdesc_getPackageSize" msgid="3921068154420738296">"Huruhusu Programu kupata tena msimbo, data na ukubwa wa akiba yake"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"sakinisha programu moja kwa moja"</string>
     <string name="permdesc_installPackages" msgid="5628530972548071284">"Inaruhusu programu kusakanisha au kusasisha furushi mpya za Android. Programu hasidi zinaweza kutumia hii kuongeza programu mpya ambazo zina ruhusa zenye nguvu."</string>
-    <string name="permlab_clearAppCache" msgid="7487279391723526815">"Futa data yote kwenye kache ya programu"</string>
-    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Inaruhusu programu kutoa nafasi ya hifadhi ya kompyuta ndogo kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
-    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Inaruhusu programu kutoa nafasi ya hifadhi ya simu kwa kufuta faili katika saraka za kache za programu nyingine. Huenda hii ikasababisha programu nyingine kuanza polepole zaidi kwa sababu zinahitaji kuepua data zazo."</string>
+    <string name="permlab_clearAppCache" msgid="7487279391723526815">"kufuta data yote kwenye akiba ya programu"</string>
+    <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"Huruhusu programu kuongeza nafasi katika hifadhi ya kompyuta kibao kwa kufuta faili katika saraka za akiba za programu zingine. Huenda hii ikafanya baadhi ya programu zianze kufanya kazi polepole kwa sababu zinahitaji kupakua tena data iliyokuwemo."</string>
+    <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"Huruhusu programu kuongeza nafasi ya hifadhi ya simu kwa kufuta faili katika saraka za akiba za programu zingine. Huenda hii ikafanya baadhi ya programu zianze kufanya kazi polepole kwa sababu zinahitaji kupakua tena data iliyokuwemo."</string>
     <string name="permlab_movePackage" msgid="3289890271645921411">"songesha rasilimali ya programu"</string>
     <string name="permdesc_movePackage" msgid="319562217778244524">"Huruhusu programu kuhamisha nyenzo za programu kutoka midia ya ndani hadi ya nje na kinyume chake."</string>
     <string name="permlab_readLogs" msgid="6615778543198967614">"soma kumbukumbu ya data muhimu"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Inaruhusu programu kusoma taarifa ya kibinafsi ya maelezo mafupi yaliyohifadhiwa kwenye kifaa chako, kama vile jina lako na taarifa ya anwani. Hii inamaanisha kuwa programu inaweza kukutambua na inaweza kuwatumia wengine taarifa yako ya maelezo mafupi."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"rekebisha kadi yako mwenyewe ya mawasiliano"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Inaruhusu programu kubadilisha au kuongeza taarifa ya maelezo mafupi ya kibinafsi yaliyohifadhiwa kwenye kifaa chako, kama vile jina lako na taarifa ya anwani. Hii inamaanisha kuwa programu inaweza kukutambua na inaweza kutuma taarifa ya maelezo yako mafupi kwa wengine."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"vipima hali ya mwili (kama mpigo wa moyo)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Huruhusu programu kufikia data kutoka kwenye vipima mawimbi unavyotumia kupima kinachoendelea mwilini mwako kama vile mpigo wa moyo."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"soma mipasho yako wa kijamii"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Huruhusu programu kufikia na kupatanisha masasisho ya kijamii kutoka kwa marafiki zako. Kuwa makini wakati unashiriki taarifa -- hii huruhusu programu kusoma mawasiliano kati yako na marafiki zako kwenye mitandao jamii, bila kujali usiri. Kumbuka: idhini hii haiwezi kutekelezwa kwenye mitandao yote ya jamii."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"kuandikia mipasho yako wa kijamii"</string>
@@ -558,7 +597,7 @@
     <string name="permlab_modifyPhoneState" msgid="8423923777659292228">"badiliisha hali ya simu"</string>
     <string name="permdesc_modifyPhoneState" msgid="1029877529007686732">"Inaruhusu programu kudhibiti vipengee vya kifaa. Programu iliyo na ruhusa hii inaweza badilisha mtandao, kuzima na kuwasha redio ya simu bila hata kukujulisha."</string>
     <string name="permlab_readPhoneState" msgid="9178228524507610486">"kusoma hali na kitambulisho cha simu"</string>
-    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Inaruhusu programu kufikia vipengele vya simu vya kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama simu ni amilifu, na nambari ya mbali iliyounganishwa kwa simu."</string>
+    <string name="permdesc_readPhoneState" msgid="1639212771826125528">"Huruhusu programu kufikia vipengele vya simu vilivyo kwenye kifaa. Idhini hii inaruhusu programu kutambua nambari ya simu na kifaa, kama kuna simu inayopigwa, na nambari ya mbali iliyounganishwa kwenye simu."</string>
     <string name="permlab_readPrecisePhoneState" msgid="5476483020282007597">"Soma hali sahihi ya simu"</string>
     <string name="permdesc_readPrecisePhoneState" msgid="6648009074263855418">"Huruhusu programu kufikia hali sahihi ya simu. Ruhusa hii huwezesha programu kufahamu hali sahihi ya simu, iwapo simu inatumika au iko katika hali ya chini kwa chini, simu inaposhindikana, hali sahihi ya muunganisho wa data na muunganisho wa data unaposhindikana."</string>
     <string name="permlab_wakeLock" product="tablet" msgid="1531731435011495015">"zuia kompyuta ndogo dhidi ya kulala"</string>
@@ -598,13 +637,13 @@
     <string name="permdesc_manageAccounts" msgid="8698295625488292506">"Inaruhusu programu kutekeleza shughuli kama vile kuongeza na kutoa akaunti, na kufuta manenosiri yazo."</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"kutumia akaunti zilizo kwenye kifaa"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"Inaruhusu programu kuomba shuhuda za uthibitisho."</string>
-    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"Kuangalia mitandao"</string>
+    <string name="permlab_accessNetworkState" msgid="4951027964348974773">"kuona mitandao"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Inaruhusu programu kuona taarifa kuhusu miunganisho ya mtandao kama vile mitandao ipi iliyopo na imeunganishwa."</string>
     <string name="permlab_createNetworkSockets" msgid="8018758136404323658">"ufikiaji kamili wa mtandao"</string>
     <string name="permdesc_createNetworkSockets" msgid="3403062187779724185">"Inaruhusu programu kuunda soketi za mtandao na kutumia itifaki za mtandao maalum. Kivinajri na programu nyingine zilizotolewa zinamaanisha kutuma data kwenye mtandao, kwa hivyo kibali hiki hakihitajiki kutuma data kwenye mtandao."</string>
     <string name="permlab_writeApnSettings" msgid="505660159675751896">"mabadiliko / kuingilia mipangilio ya mtandao/msonmgamano"</string>
     <string name="permdesc_writeApnSettings" msgid="5333798886412714193">"Inaruhusu programu kubadilisha mipangilio ya mtandao na kukatiza na kukagua uendaji wa mtandao, kwa mfano kubadilisha kituo tarishi na mbadala cha APN yoyote. Programu hasidi zinaweza kuangalia, kuelekeza kwingine, au kurekebisha furushi za mtandao bila ya wewe kujua."</string>
-    <string name="permlab_changeNetworkState" msgid="958884291454327309">"badilisha muunganisho wa mtandao"</string>
+    <string name="permlab_changeNetworkState" msgid="958884291454327309">"kubadilisha muunganisho wa mtandao"</string>
     <string name="permdesc_changeNetworkState" msgid="6789123912476416214">"Inaruhusu programu kubadilisha hali ya muunganisho wa mtandao."</string>
     <string name="permlab_changeTetherState" msgid="5952584964373017960">"Badilisha muunganisho uliofunganishwa"</string>
     <string name="permdesc_changeTetherState" msgid="1524441344412319780">"Inaruhusu programu kubadilisha hali ya muunganisho wa mtandao uliofungwa."</string>
@@ -628,28 +667,31 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Badilisha hali ya WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Inaruhusu programu kuunganisha kompyuta kibao,  na kukata kompyuta kibao kutoka mitandao ya WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Inaruhusu programu kuunganisha simu kwenye, na kukata simu kutoka mitandao ya WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ipe mitandao alama"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Huruhusu programu kupanga mitandao kwa alama na kushawishi mitandao ambayo kompyuta kibao inapaswa kupendelea."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Huruhusu programu kupanga mitandao kwa alama na kushawishi mitandao ambayo simu inapaswa kupendelea."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"oanisha na vifaa vya Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye kompyuta kibao, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Inaruhusu programu kuona usanidi wa Bluetooth kwenye simu, na kuunda na kukubali miunganisho kwa vifaa vilivyooanishwa."</string>
-    <string name="permlab_nfc" msgid="4423351274757876953">"dhibiti Mawasiliano ya vifaa vilivyo Karibu"</string>
+    <string name="permlab_nfc" msgid="4423351274757876953">"kudhibiti Mawasiliano ya Vifaa Vilivyokaribu (NFC)"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Inaruhusu programu kuwasiliana na lebo, kadi na wasomaji wa Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"zima kufuli la skrini yako"</string>
     <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Inaruhusu programu kulemaza ufunguo wa vitufe na usalama mwingine ambata wa nenosiri. Kwa mfano, simu inalemaza ufunguo wa viitufe inapopokea simu inayoingia, kisha inawezesha upya ufunguo wa vitufe wakati simu inapokamilika."</string>
-    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"soma mipangilio ya usawazishaji"</string>
+    <string name="permlab_readSyncSettings" msgid="6201810008230503052">"kusoma mipangilio ya usawazishaji"</string>
     <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Inaruhusu programu kusoma mipangilio ya upatanishi wa akaunti. Kwa mfano, huku kunaweza kuamua kama programu ya Watu imepatanishwa na akaunti."</string>
-    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"washa na uzime usawazishaji"</string>
+    <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"kuwasha na kuzima usawazishaji"</string>
     <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Inaruhusu programu kurekebisha mipangalio ya upatanishi wa akaunti. Kwa mfano, hii inaweza kuwezesha programu ya upatanishi wa Watu na akaunti."</string>
-    <string name="permlab_readSyncStats" msgid="7396577451360202448">"soma takwimu za usawazishaji"</string>
+    <string name="permlab_readSyncStats" msgid="7396577451360202448">"kusoma takwimu za usawazishaji"</string>
     <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Inaruhusu programu kusoma takwimu za upatanishi za akaunti, ikiwa ni pamoja na historia ya matukio ya upatanishi na kiasi cha data kimepatanishwa."</string>
-    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"soma milisho ya kujiunga"</string>
+    <string name="permlab_subscribedFeedsRead" msgid="4756609637053353318">"kusoma mipasho kutoka vyanzo unavyofuatilia"</string>
     <string name="permdesc_subscribedFeedsRead" msgid="5557058907906144505">"Inaruhusu programu kupata maelezo kuhusu mlisho iliyolandanishwa kwa sasa."</string>
-    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"andika milisho ya kujiunga"</string>
+    <string name="permlab_subscribedFeedsWrite" msgid="9015246325408209296">"kuandika mipasho kutoka vyanzo unavyofuatilia"</string>
     <string name="permdesc_subscribedFeedsWrite" msgid="6928930188826089413">"Inaruhusu programu kurekebisha milisho yako iliyolandanishwa kwa sasa. Programu hasidi zinaweza kubadilisha milisho yako iliyolandanishwa."</string>
     <string name="permlab_readDictionary" msgid="4107101525746035718">"soma maneno uliyoongeza kwenye kamusi"</string>
     <string name="permdesc_readDictionary" msgid="659614600338904243">"Inaruhusu programu kusoma maneno, majina na misemo yote ambayo mtumiaji alihifadhi katika kamusi ya mtumiaji."</string>
     <string name="permlab_writeDictionary" msgid="2183110402314441106">"ongeza maneno katika kamusi ya mtumiaji iliyofafanuliwa"</string>
     <string name="permdesc_writeDictionary" msgid="8185385716255065291">"Inaruhusu programu kuandika maneno mapya katika kamusi ya mtumiaji."</string>
-    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"soma maudhui ya hifadhi yako ya USB"</string>
+    <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"kusoma maudhui yaliyo kwenye hifadhi yako ya USB"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"soma maudhui ya kadi yako ya SD"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Huruhusu programu kusoma maudhui ya hifadhi ya USB."</string>
     <string name="permdesc_sdcardRead" product="default" msgid="2607362473654975411">"Huruhusu programu kusoma maudhui ya kadi yako ya SD."</string>
@@ -663,12 +705,12 @@
     <string name="permdesc_manageDocs" product="default" msgid="8704323176914121484">"Huruhusu programu kudhibiti hifadhi ya hati."</string>
     <string name="permlab_sdcardAccessAll" msgid="8150613823900460576">"Fikia hifadhi ya nje ya watumiaji wote"</string>
     <string name="permdesc_sdcardAccessAll" msgid="3215208357415891320">"Inaruhusu programu kufikia hifadhi ya nje kwa watumiaji wote."</string>
-    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za kache"</string>
-    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Inaruhusu programu kusoma na kuandika mfumo wa faili wa kache."</string>
+    <string name="permlab_cache_filesystem" msgid="5656487264819669824">"fikia faili za mfumo za akiba"</string>
+    <string name="permdesc_cache_filesystem" msgid="5578967642265550955">"Huruhusu programu kusoma na kuandika mfumo wa faili wa akiba."</string>
     <string name="permlab_use_sip" msgid="5986952362795870502">"piga/pokea simu za mtandao"</string>
     <string name="permdesc_use_sip" msgid="4717632000062674294">"Inaruhusu programu kutumia huduma ya SIP kupiga/kupokea simu za mtandao."</string>
     <string name="permlab_bind_call_service" msgid="6724009726671246551">"tumikisha skrini ya simu inayoendelea"</string>
-    <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Inaruhusu programu kudhibiti wakati na jinsi mtumiaji anaona skrini ya simu inayoendelea."</string>
+    <string name="permdesc_bind_call_service" msgid="8732547662442572435">"Huruhusu programu kudhibiti wakati na jinsi mtumiaji anaona skrini anapopigiwa simu."</string>
     <string name="permlab_readNetworkUsageHistory" msgid="7862593283611493232">"soma matumizi ya historia ya mtandao"</string>
     <string name="permdesc_readNetworkUsageHistory" msgid="7689060749819126472">"Inaruhusu programu kusoma historia ya matumizi ya mtandao kwa mitandao maalum na programu."</string>
     <string name="permlab_manageNetworkPolicy" msgid="2562053592339859990">"dhibiti sera ya mtandao"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Huruhusu programu kurejesha, kuchunguza, na kuondoa arifa, ikiwa ni pamoja na zile zilizochapishwa na programu nyingine."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"unganisha kwenye huduma ya kisikilizi cha arifa"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Inaruhusu kishikilizi kuunganishwa kwenye kusano cha kiwango cha juu cha huduma ya kisikilizi cha arifa. Haipaswi kuhitajika tena kwa programu za kawaida."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"shurutisha kwa huduma ya mtoa masharti"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Humruhusu mmiliki kushurutisha kwa kiolesura cha kiwango cha juu cha huduma ya mtoa masharti. Kamwe isihitajike kwa pogramu za kawaida."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"omba programu ya usakinishaji inayotolewa na mtoa huduma."</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Inaruhusu kishikiliaji kuomba programu ya usakinishaji inayotolewa na mto huduma. Haipaswi kuhitajika kwa programu za kawaida."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"sikiliza matukio katika hali za mtandao"</string>
@@ -691,9 +735,9 @@
     <string name="permdesc_accessDrmCertificates" msgid="8073288354426159089">"Huruhusu programu kwa utoaji na matumizi ya vyeti vya DRM. Havifahi kuhitajika kwa ajili ya programu za kawaida."</string>
     <string name="policylab_limitPassword" msgid="4497420728857585791">"Kuweka kanuni za nenosiri"</string>
     <string name="policydesc_limitPassword" msgid="3252114203919510394">"Kudhibiti urefu na herufi zinazoruhusiwa katika manenosiri ya kufungua skrini."</string>
-    <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu idadi ya mara ambazo skrini inajaribu kufunguliwa"</string>
-    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Fuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na ufunge kompyuta kibao au ufute data yote iliyomo kama manenosiri mengi yenye makosa yataingizwa."</string>
-    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Fuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na ufunge simu au ufute data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string>
+    <string name="policylab_watchLogin" msgid="914130646942199503">"Kuhesabu mara ambazo skrini inajaribu kufunguliwa"</string>
+    <string name="policydesc_watchLogin" product="tablet" msgid="3215729294215070072">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga kompyuta kibao au kufuta data yote iliyomo kama manenosiri mengi yasiyo sahihi yataingizwa."</string>
+    <string name="policydesc_watchLogin" product="default" msgid="5712323091846761073">"Kufuatilia idadi ya manenosiri yasiyo sahihi yatakayoingizwa wakati wa kufungua skrini, na kufunga simu au kufuta data yote iliyomo kama manenosiri mengi sana yasiyo sahihi yataingizwa."</string>
     <string name="policylab_resetPassword" msgid="2620077191242688955">"Kubadilisha nenosiri la kufungua skrini"</string>
     <string name="policydesc_resetPassword" msgid="605963962301904458">"Kubadilisha nenosiri la kufungua skrini."</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Kufunga skrini"</string>
@@ -1270,14 +1314,14 @@
     <string name="usb_ptp_notification_title" msgid="1960817192216064833">"Imeunganishwa kama kamera"</string>
     <string name="usb_cd_installer_notification_title" msgid="6774712827892090754">"Imeunganishwa kama kisakinishi"</string>
     <string name="usb_accessory_notification_title" msgid="7848236974087653666">"Imeunganishwa kwa kifuasi cha USB"</string>
-    <string name="usb_notification_message" msgid="2290859399983720271">"Gusa kwa chaguo nyingine za USB."</string>
+    <string name="usb_notification_message" msgid="2290859399983720271">"Gusa ili uone chaguo zingine za USB."</string>
     <string name="extmedia_format_title" product="nosdcard" msgid="9020092196061007262">"Fomati hifadhi ya USB?"</string>
     <string name="extmedia_format_title" product="default" msgid="3648415921526526069">"Umbiza kadi ya SD."</string>
     <string name="extmedia_format_message" product="nosdcard" msgid="3934016853425761078">"Faili zote zilizohifadhiwa katika hifadhi yako ya USB zitafutwa. Hatua hii haiwezi kubadilishwa!"</string>
     <string name="extmedia_format_message" product="default" msgid="14131895027543830">"Data yote kwenye kadi yako itapotea."</string>
     <string name="extmedia_format_button_format" msgid="4131064560127478695">"Fomati"</string>
-    <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji USB umeunganishwa"</string>
-    <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili kulemaza utatuaji wa USB."</string>
+    <string name="adb_active_notification_title" msgid="6729044778949189918">"Utatuaji wa USB umeunganishwa"</string>
+    <string name="adb_active_notification_message" msgid="1016654627626476142">"Gusa ili uzime utatuaji wa USB."</string>
     <string name="select_input_method" msgid="4653387336791222978">"Chagua njia ya ingizo"</string>
     <string name="configure_input_methods" msgid="9091652157722495116">"Weka mbinu za ingizo"</string>
     <string name="use_physical_keyboard" msgid="6203112478095117625">"Kibodi halisi"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Mandhari"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Badilisha mandhari"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Kisikilizi cha arifa"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Mtoa hali"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN imewezeshwa"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN imeamilishwa na <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Gusa ili kudhibiti mtandao."</string>
diff --git a/core/res/res/values-th/strings.xml b/core/res/res/values-th/strings.xml
index ecb3a58..826fa64 100644
--- a/core/res/res/values-th/strings.xml
+++ b/core/res/res/values-th/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;ไม่มีชื่อ&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"ซิงค์"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"มีการลบ <xliff:g id="CONTENT_TYPE">%s</xliff:g> มากเกินไป"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"ที่จัดเก็บข้อมูลของแท็บเล็ตเต็ม ลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"ที่เก็บข้อมูลนาฬิกาเต็ม โปรดลบไฟล์บางไฟล์เพื่อเพิ่มพื้นที่ว่าง"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"ที่เก็บข้อมูลโทรศัพท์เต็ม ลบบางไฟล์เพื่อเพิ่มที่ว่าง"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"เครือข่ายอาจได้รับการตรวจสอบ"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"โดยบุคคลที่สามที่ไม่รู้จัก"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"เปิดเสียง"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"กำลังปิดระบบ..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"แท็บเล็ตของคุณจะปิดการทำงาน"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"นาฬิกาจะปิดการทำงาน"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"โทรศัพท์ของคุณจะปิดเครื่อง"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"คุณต้องการปิดการทำงานหรือไม่"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"รีบูตเข้าสู่โหมดปลอดภัย"</string>
@@ -162,15 +186,16 @@
     <string name="global_actions" product="default" msgid="2406416831541615258">"ตัวเลือกโทรศัพท์"</string>
     <string name="global_action_lock" msgid="2844945191792119712">"ล็อกหน้าจอ"</string>
     <string name="global_action_power_off" msgid="4471879440839879722">"ปิดเครื่อง"</string>
-    <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานบั๊ก"</string>
-    <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานบั๊ก"</string>
-    <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานบั๊กจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
+    <string name="global_action_bug_report" msgid="7934010578922304799">"รายงานข้อบกพร่อง"</string>
+    <string name="bugreport_title" msgid="2667494803742548533">"ใช้รายงานข้อบกพร่อง"</string>
+    <string name="bugreport_message" msgid="398447048750350456">"การดำเนินการนี้จะรวบรวมข้อมูลเกี่ยวกับสถานะปัจจุบันของอุปกรณ์ของคุณ โดยจะส่งไปในรูปแบบข้อความอีเมล อาจใช้เวลาสักครู่ตั้งแต่เริ่มการสร้างรายงานข้อบกพร่องจนกระทั่งเสร็จสมบูรณ์ โปรดอดทนรอ"</string>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"โหมดปิดเสียง"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"ปิดเสียงไว้"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"เปิดเสียงแล้ว"</string>
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"โหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"เปิดโหมดใช้งานบนเครื่องบิน"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"โหมดใช้งานบนเครื่องบินปิดทำงานอยู่"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"การตั้งค่า"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"โหมดปลอดภัย"</string>
     <string name="android_system_label" msgid="6577375335728551336">"ระบบ Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"อนุญาตให้แอปพลิเคชันดึงเนื้อหาของหน้าต่างที่ใช้งานอยู่ แอปพลิเคชันที่เป็นอันตรายอาจดึงเนื้อหาจากหน้าต่างทั้งหมดและตรวจสอบข้อความทั้งหมดยกเว้นรหัสผ่าน"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"เปิดใช้งานการเข้าถึงชั่วคราว"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"ช่วยให้แอปพลิเคชันสามารถเปิดใช้งานการเข้าถึงบนอุปกรณ์เป็นการชั่วคราว แอปพลิเคชันที่เป็นอันตรายอาจเปิดใช้งานการเข้าถึงโดยไม่ได้รับความยินยอมจากผู้ใช้"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"เรียกโทเค็นหน้าต่าง"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"อนุญาตให้แอปพลิเคชันเรียกโทเค็นหน้าต่าง แอปที่เป็นอันตรายอาจทำการโต้ตอบที่ไม่ได้รับอนุญาตกับหน้าต่างแอปพลิเคชันโดยปลอมแปลงเป็นระบบ"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"เรียกสถิติเฟรม"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"อนุญาตให้แอปพลิเคชันเก็บสถิติเฟรม แอปที่เป็นอันตรายอาจดูสถิติเฟรมของหน้าต่างจากแอปอื่น"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"กรองกิจกรรม"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"อนุญาตให้แอปพลิเคชันลงทะเบียนตัวกรองข้อมูลซึ่งจะกรองสตรีมกิจกรรมทั้งหมดของผู้ใช้ก่อนที่จะทำการเผยแพร่ออกไป แอปพลิเคชันที่เป็นอันตรายอาจควบคุม UI ของระบบโดยไม่ต้องให้ผู้ใช้จัดการ"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ปิดการทำงานบางส่วน"</string>
@@ -325,12 +354,14 @@
     <string name="permdesc_getTopActivityInfo" msgid="2512448855496067131">"ช่วยให้เจ้าของสามารถดึงข้อมูลส่วนตัวเกี่ยวกับแอปพลิเคชันปัจจุบันในส่วนหน้าของหน้าจอ"</string>
     <string name="permlab_runSetActivityWatcher" msgid="892239094867182656">"ตรวจสอบและควบคุมแอปพลิเคชันทั้งหมดที่เปิดใช้งาน"</string>
     <string name="permdesc_runSetActivityWatcher" msgid="6003603162578577406">"อนุญาตให้แอปพลิเคชันตรวจสอบและควบคุมวิธีการที่ระบบเปิดกิจกรรมต่างๆ แอปพลิเคชันที่เป็นอันตรายอาจทำอันตรายแก่ระบบได้อย่างสิ้นเชิง การอนุญาตนี้จำเป็นสำหรับการพัฒนาเท่านั้น ไม่ใช้สำหรับแอปพลิเคชันทั่วไปโดยเด็ดขาด"</string>
-    <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งการกระจายข้อมูลว่ามีการนำแพคเกจออก"</string>
-    <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าแพคเกจของแอปพลิเคชันหนึ่งๆ ได้ถูกนำออกไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ยุติแอปพลิเคชันอื่นๆ ที่กำลังทำงานอยู่"</string>
+    <string name="permlab_broadcastPackageRemoved" msgid="2576333434893532475">"ส่งการกระจายข้อมูลว่ามีการนำแพ็กเกจออก"</string>
+    <string name="permdesc_broadcastPackageRemoved" msgid="6621901216207931089">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าแพ็กเกจของแอปพลิเคชันหนึ่งๆ ได้ถูกนำออกไปแล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ยุติแอปพลิเคชันอื่นๆ ที่กำลังทำงานอยู่"</string>
     <string name="permlab_broadcastSmsReceived" msgid="5689095009030336593">"ส่งการกระจายข้อมูลว่าได้รับ SMS"</string>
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าได้รับข้อความ SMS แล้ว แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ปลอมข้อความ SMS ที่เข้ามา"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ส่งการกระจายข้อมูลว่าได้รับ WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"อนุญาตให้แอปพลิเคชันกระจายข้อมูลการแจ้งเตือนว่าได้รับข้อความ WAP PUSH แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ปลอมการแจ้งรับข้อความ MMS หรือแอบเปลี่ยนเนื้อหาในหน้าเว็บโดยใช้ตัวแปรที่เป็นอันตราย"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ส่งเผยแพร่การให้คะแนนเครือข่าย"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"อนุญาตให้แอปนี้เผยแพร่ข้อมูลการแจ้งเตือนว่าเครือข่ายจะต้องผ่านการให้คะแนน ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"จำกัดจำนวนกระบวนการที่กำลังทำงาน"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"อนุญาตให้แอปพลิเคชันควบคุมจำนวนสูงสุดของกระบวนการที่จะเรียกใช้ ไม่จำเป็นต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"บังคับปิดแอปพลิเคชันในพื้นหลัง"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการ VPN ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"เชื่อมโยงกับวอลเปเปอร์"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของวอลเปเปอร์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"เชื่อมโยงกับโปรแกรมโต้ตอบด้วยเสียง"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการโต้ตอบด้วยเสียง ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"ผูกกับจอแสดงผลระยะไกล"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"อนุญาตให้ผู้ใช้ผูกกับอินเทอร์เฟซระดับสูงสุดของจอแสดงผลระยะไกล ซึ่งแอปพลิเคชันทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"เชื่อมโยงกับบริการวิดเจ็ต"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"อนุญาตให้ผู้ใช้เชื่อมโยงกับส่วนติดต่อผู้ใช้ระดับสูงสุดของบริการวิดเจ็ต ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"เชื่อมโยงกับบริการของผู้ให้บริการเส้นทาง"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"ช่วยให้เจ้าของสามารถเชื่อมโยงกับผู้ให้บริการเส้นทางที่ลงทะเบียนรายใดก็ได้ ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"ติดต่อกับผู้ดูแลอุปกรณ์"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"อนุญาตให้ผู้ใช้ส่งการติดต่อไปยังโปรแกรมควบคุมอุปกรณ์ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"เชื่อมโยงกับอินพุตทีวี"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"อนุญาตให้เจ้าของเชื่อมโยงกับส่วนติดต่อระดับสูงสุดของอินพุตทีวี ซึ่งแอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"เพิ่มหรือลบผู้ดูแลระบบอุปกรณ์"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"อนุญาตให้เจ้าของเพิ่มหรือลบผู้ดูแลระบบอุปกรณ์ที่ใช้งาน ไม่ควรต้องใช้สำหรับแอปปกติ"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"เปลี่ยนการวางแนวหน้าจอ"</string>
@@ -398,7 +435,7 @@
     <string name="permdesc_persistentActivity" product="tablet" msgid="8525189272329086137">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้แท็บเล็ตทำงานช้าลง"</string>
     <string name="permdesc_persistentActivity" product="default" msgid="4384760047508278272">"อนุญาตให้แอปพลิเคชันทำให้ส่วนหนึ่งของตัวเองคงอยู่ถาวรในหน่วยความจำ ซึ่งจะจำกัดพื้นที่หน่วยความจำที่ใช้งานได้ของแอปพลิเคชันอื่นๆ และทำให้โทรศัพท์ทำงานช้าลง"</string>
     <string name="permlab_deletePackages" msgid="184385129537705938">"ลบแอปพลิเคชัน"</string>
-    <string name="permdesc_deletePackages" msgid="7411480275167205081">"อนุญาตให้แอปพลิเคชันลบแพคเกจ Android แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ลบแอปพลิเคชันที่สำคัญ"</string>
+    <string name="permdesc_deletePackages" msgid="7411480275167205081">"อนุญาตให้แอปพลิเคชันลบแพ็กเกจ Android แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ลบแอปพลิเคชันที่สำคัญ"</string>
     <string name="permlab_clearAppUserData" msgid="274109191845842756">"ลบข้อมูลของแอปพลิเคชันอื่น"</string>
     <string name="permdesc_clearAppUserData" msgid="4625323684125459488">"อนุญาตให้แอปพลิเคชันล้างข้อมูลผู้ใช้"</string>
     <string name="permlab_deleteCacheFiles" msgid="3128665571837408675">"ลบแคชของแอปพลิเคชันอื่น"</string>
@@ -406,7 +443,7 @@
     <string name="permlab_getPackageSize" msgid="7472921768357981986">"วัดพื้นที่เก็บข้อมูลของแอปพลิเคชัน"</string>
     <string name="permdesc_getPackageSize" msgid="3921068154420738296">"อนุญาตให้แอปพลิเคชันเรียกดูรหัส ข้อมูล และขนาดแคชของตน"</string>
     <string name="permlab_installPackages" msgid="2199128482820306924">"ติดตั้งแอปพลิเคชันโดยตรง"</string>
-    <string name="permdesc_installPackages" msgid="5628530972548071284">"อนุญาตให้แอปพลิเคชันติดตั้งแพคเกจ Android ใหม่หรือที่อัปเดต แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการเพิ่มแอปพลิเคชันใหม่ๆ ด้วยสิทธิ์ที่สูงนี้ได้ตามต้องการ"</string>
+    <string name="permdesc_installPackages" msgid="5628530972548071284">"อนุญาตให้แอปพลิเคชันติดตั้งแพ็กเกจ Android ใหม่หรือที่อัปเดต แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการเพิ่มแอปพลิเคชันใหม่ๆ ด้วยสิทธิ์ที่สูงนี้ได้ตามต้องการ"</string>
     <string name="permlab_clearAppCache" msgid="7487279391723526815">"ลบข้อมูลแคชของแอปพลิเคชันทั้งหมด"</string>
     <string name="permdesc_clearAppCache" product="tablet" msgid="8974640871945434565">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของแท็บเล็ต โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
     <string name="permdesc_clearAppCache" product="default" msgid="2459441021956436779">"อนุญาตให้แอปพลิเคชันสร้างพื้นที่ว่างในที่จัดเก็บข้อมูลของโทรศัพท์ โดยลบไฟล์ในไดเรกทอรีแคชของแอปพลิเคชันอื่นๆ ซึ่งอาจทำให้แอปพลิเคชันอื่นเริ่มทำงานช้ากว่าเดิมเนื่องจากต้องดึงข้อมูลของตนซ้ำ"</string>
@@ -443,14 +480,14 @@
     <string name="permdesc_broadcastSticky" product="tablet" msgid="7749760494399915651">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว การใช้งานมากเกินไปอาจทำให้แท็บเล็ตทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
     <string name="permdesc_broadcastSticky" product="default" msgid="2825803764232445091">"อนุญาตให้แอปพลิเคชันส่งการกระจายข้อมูลที่ติดหนึบ ซึ่งจะยังคงอยู่หลังจากการกระจายข้อมูลจบไปแล้ว การใช้งานมากเกินไปอาจทำให้โทรศัพท์ทำงานช้าลงหรือไม่เสถียรโดยการใช้หน่วยความจำมากเกินไป"</string>
     <string name="permlab_readContacts" msgid="8348481131899886131">"อ่านผู้ติดต่อของคุณ"</string>
-    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแบ่งปันข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
-    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแบ่งปันข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
+    <string name="permdesc_readContacts" product="tablet" msgid="5294866856941149639">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
+    <string name="permdesc_readContacts" product="default" msgid="8440654152457300662">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลผู้ติดต่อของคุณ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลผู้ติดต่อโดยไม่แจ้งให้คุณทราบ"</string>
     <string name="permlab_writeContacts" msgid="5107492086416793544">"แก้ไขผู้ติดต่อของคุณ"</string>
     <string name="permdesc_writeContacts" product="tablet" msgid="897243932521953602">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในแท็บเล็ต ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงข้อมูลผู้ติดต่อที่จัดเก็บไว้ในโทรศัพท์ ซึ่งรวมถึงความถี่ในการโทร ส่งอีเมล หรือการติดต่อด้วยวิธีอื่นๆ กับบุคคลใดบุคคลหนึ่ง การอนุญาตนี้ทำให้แอปพลิเคชันสามารถลบข้อมูลผู้ติดต่อได้"</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"อ่านประวัติการโทร"</string>
-    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของแท็บเล็ต ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแบ่งปันข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
-    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของโทรศัพท์ ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแบ่งปันข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
+    <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของแท็บเล็ต ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
+    <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"อนุญาตให้แอปพลิเคชันอ่านบันทึกการโทรของโทรศัพท์ ซึ่งรวมถึงข้อมูลเกี่ยวกับการโทรเข้าและโทรออก การอนุญาตนี้ทำให้แอปพลิเคชันสามารถบันทึกข้อมูลบันทึกการโทรของคุณได้ และแอปพลิเคชันที่เป็นอันตรายอาจแชร์ข้อมูลบันทึกการโทรนี้โดยไม่แจ้งให้คุณทราบ"</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"เขียนประวัติการโทร"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"อนุญาตให้แอปแก้ไขประวัติการโทรจากแท็บเล็ตของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ"</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"อนุญาตให้แอปแก้ไขประวัติการโทรจากโทรศัพท์ของคุณ รวมถึงข้อมูลเกี่ยวกับสายเรียกเข้าและการโทรออก แอปที่เป็นอันตรายอาจใช้สิ่งนี้เพื่อลบหรือแก้ไขประวัติการโทรของคุณ"</string>
@@ -458,13 +495,15 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"อนุญาตให้แอปพลิเคชันอ่านข้อมูลส่วนตัวในโปรไฟล์ที่จัดเก็บไว้ในอุปกรณ์ของคุณ เช่น ชื่อและข้อมูลติดต่อของคุณ ซึ่งหมายความว่าแอปพลิเคชันสามารถระบุตัวคุณและอาจส่งข้อมูลโปรไฟล์ของคุณให้ผู้อื่น"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"แก้ไขบัตรผู้ติดต่อของคุณเอง"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"อนุญาตให้แอปพลิเคชันเปลี่ยนแปลงหรือเพิ่มข้อมูลโปรไฟล์ส่วนตัวที่จัดเก็บไว้บนอุปกรณ์ของคุณ เช่น ชื่อและข้อมูลติดต่อ ซึ่งหมายความว่าแอปพลิเคชันจะสามารถระบุตัวตนของคุณและส่งข้อมูลโปรไฟล์ของคุณให้แก่ผู้อื่นได้"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"เซ็นเซอร์ร่างกาย (เช่น วัดอัตราการเต้นของหัวใจ)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"ช่วยให้แอปสามารถเข้าถึงข้อมูลจากเซ็นเซอร์ที่คุณใช้เพื่อวัดความเป็นไปภายในร่างกายของคุณ เช่น อัตราการเต้นของหัวใจ"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"อ่านสตรีมเครือข่ายสังคม"</string>
-    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"อนุญาตให้แอปพลิเคชันเข้าถึงและซิงค์การอัปเดตทางสังคมจากคุณและเพื่อน โปรดแบ่งปันข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถอ่านการติดต่อระหว่างคุณและเพื่อนในเครือข่ายสังคมได้ ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับแบบใดก็ตาม หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับทุกเครือข่ายสังคม"</string>
+    <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"อนุญาตให้แอปพลิเคชันเข้าถึงและซิงค์การอัปเดตทางสังคมจากคุณและเพื่อน โปรดแชร์ข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถอ่านการติดต่อระหว่างคุณและเพื่อนในเครือข่ายสังคมได้ ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับแบบใดก็ตาม หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้งานได้กับทุกเครือข่ายสังคม"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"เขียนในสตรีมเครือข่ายสังคม"</string>
-    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"อนุญาตให้แอปพลิเคชันแสดงการอัปเดตทางสังคมจากเพื่อนของคุณ โปรดแบ่งปันข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถสร้างข้อความที่ดูเหมือนมาจากเพื่อนได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้ได้กับทุกเครือข่ายสังคม"</string>
+    <string name="permdesc_writeSocialStream" product="default" msgid="3086557552204114849">"อนุญาตให้แอปพลิเคชันแสดงการอัปเดตทางสังคมจากเพื่อนของคุณ โปรดแชร์ข้อมูลอย่างระมัดระวังเนื่องจากการอนุญาตนี้ทำให้แอปพลิเคชันสามารถสร้างข้อความที่ดูเหมือนมาจากเพื่อนได้ หมายเหตุ: การอนุญาตนี้อาจไม่สามารถใช้ได้กับทุกเครือข่ายสังคม"</string>
     <string name="permlab_readCalendar" msgid="5972727560257612398">"อ่านกิจกรรมบนปฏิทินรวมถึงข้อมูลที่เป็นความลับ"</string>
-    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในแท็บเล็ตของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแบ่งปันหรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
-    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในโทรศัพท์ของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแบ่งปันหรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
+    <string name="permdesc_readCalendar" product="tablet" msgid="4216462049057658723">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในแท็บเล็ตของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแชร์หรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
+    <string name="permdesc_readCalendar" product="default" msgid="7434548682470851583">"อนุญาตให้แอปพลิเคชันอ่านกิจกรรมในปฏิทินทั้งหมดที่จัดเก็บไว้ในโทรศัพท์ของคุณ ซึ่งรวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย ซึ่งอาจทำให้แอปพลิเคชันสามารถแชร์หรือบันทึกข้อมูลในปฏิทินของคุณได้ไม่ว่าจะมีการรักษาข้อมูลที่เป็นความลับหรือหรือข้อมูลที่อ่อนไหวแบบใดก็ตาม"</string>
     <string name="permlab_writeCalendar" msgid="8438874755193825647">"เพิ่มหรือแก้ไขกิจกรรมบนปฏิทินและส่งอีเมลให้ผู้เข้าร่วมโดยที่เจ้าของไม่ทราบ"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="6679035520113668528">"อนุญาตให้แอปพลิเคชันเพิ่ม ลบ เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในแท็บเล็ตได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
     <string name="permdesc_writeCalendar" product="default" msgid="2324469496327249376">"อนุญาตให้แอปพลิเคชันเพิ่ม ลบ เปลี่ยนกิจกรรมที่คุณสามารถเปลี่ยนแปลงในโทรศัพท์ได้ รวมถึงกิจกรรมของเพื่อนหรือเพื่อนร่วมงานด้วย การอนุญาตนี้อาจทำให้แอปพลิเคชันสามารถส่งข้อความที่มาจากเจ้าของปฏิทิน หรือเปลี่ยนแปลงกิจกรรมโดยที่เจ้าของไม่ทราบ"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"เปลี่ยนสถานะของ WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อแท็บเล็ตกับเครือข่าย WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"อนุญาตให้แอปพลิเคชันเชื่อมต่อและยกเลิกการเชื่อมต่อโทรศัพท์กับเครือข่าย WiMAX"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ให้คะแนนเครือข่าย"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"อนุญาตให้แอปนี้จัดลำดับเครือข่าย ซึ่งมีผลต่อการเลือกใช้เครือข่ายของแท็บเล็ต"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"อนุญาตให้แอปนี้จัดอันดับเครือข่ายและมีผลต่อการเลือกใช้เครือข่ายของโทรศัพท์"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"จับคู่กับอุปกรณ์บลูทูธ"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของแท็บเล็ต ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"อนุญาตให้แอปพลิเคชันดูการกำหนดค่าบลูทูธของโทรศัพท์ ตลอดจนเชื่อมต่อและยอมรับการเชื่อมต่อกับอุปกรณ์ที่จับคู่ไว้"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"ทำให้แอปสามารถเรียกดู ตรวจสอบ และล้างการแจ้งเตือนได้ ซึ่งรวมถึงการแจ้งเตือนที่โพสต์โดยแอปอื่นๆ ด้วย"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"เชื่อมโยงกับบริการตัวฟังการแจ้งเตือน"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"อนุญาตให้เจ้าของเชื่อมโยงกับอินเตอร์เฟซระดับสูงสุดของบริการตัวฟังการแจ้งเตือน ซึ่งไม่มีความจำเป็นสำหรับแอปธรรมดา"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"เชื่อมโยงกับบริการของผู้เสนอเงื่อนไข"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"อนุญาตให้ผู้ใช้อุปกรณ์เชื่อมโยงกับอินเทอร์เฟซระดับบนสุดของบริการของผู้เสนอเงื่อนไข ไม่จำเป็นสำหรับแอปทั่วไป"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"เรียกใช้แอปการกำหนดค่าของผู้ให้บริการ"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"อนุญาตให้ผู้ใช้สามารถเรียกใช้แอปการกำหนดค่าของผู้ให้บริการ ซึ่งแอปทั่วไปไม่จำเป็นต้องใช้"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ฟังข้อสังเกตเกี่ยวกับสภาวะของเครือข่าย"</string>
@@ -927,7 +971,7 @@
     <string name="hour_cap_ampm" msgid="2083465992940444366">"<xliff:g id="HOUR">%-l</xliff:g><xliff:g id="AMPM">%p</xliff:g>"</string>
     <string name="factorytest_failed" msgid="5410270329114212041">"การทดสอบจากโรงงานล้มเหลว"</string>
     <string name="factorytest_not_system" msgid="4435201656767276723">"การทำงาน FACTORY_TEST ได้รับการสนับสนุนเฉพาะสำหรับแพ็คเก็จที่ติดตั้งใน /system/app เท่านั้น"</string>
-    <string name="factorytest_no_action" msgid="872991874799998561">"ไม่พบแพคเกจที่มีการทำงาน FACTORY_TEST"</string>
+    <string name="factorytest_no_action" msgid="872991874799998561">"ไม่พบแพ็กเกจที่มีการทำงาน FACTORY_TEST"</string>
     <string name="factorytest_reboot" msgid="6320168203050791643">"รีบูต"</string>
     <string name="js_dialog_title" msgid="1987483977834603872">"หน้าเว็บที่ \"<xliff:g id="TITLE">%s</xliff:g>\" ระบุว่า:"</string>
     <string name="js_dialog_title_default" msgid="6961903213729667573">"JavaScript"</string>
@@ -966,10 +1010,10 @@
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"อนุญาตให้แอปพลิเคชันเพิ่มข้อความลงในกล่องข้อความเสียงของคุณ"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"แก้ไขการอนุญาตเกี่ยวกับการระบุตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"อนุญาตให้แอปพลิเคชันแก้ไขการอนุญาตตำแหน่งทางภูมิศาสตร์ของเบราว์เซอร์ แอปพลิเคชันที่เป็นอันตรายอาจใช้การอนุญาตนี้ในการส่งข้อมูลตำแหน่งไปยังเว็บไซต์ต่างๆ ได้ตามต้องการ"</string>
-    <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ยืนยันแพคเกจ"</string>
-    <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"อนุญาตให้แอปพลิเคชันยืนยันว่าแพคเกจสามารถติดตั้งได้หรือไม่"</string>
-    <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"เชื่อมโยงกับการยืนยันแพคเกจ"</string>
-    <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"อนุญาตให้ผู้ใช้ส่งคำขอให้มีการยืนยันแพคเกจ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
+    <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"ยืนยันแพ็กเกจ"</string>
+    <string name="permdesc_packageVerificationAgent" msgid="8437590190990843381">"อนุญาตให้แอปพลิเคชันยืนยันว่าแพ็กเกจสามารถติดตั้งได้หรือไม่"</string>
+    <string name="permlab_bindPackageVerifier" msgid="4187786793360326654">"เชื่อมโยงกับการยืนยันแพ็กเกจ"</string>
+    <string name="permdesc_bindPackageVerifier" msgid="3180741773233862126">"อนุญาตให้ผู้ใช้ส่งคำขอให้มีการยืนยันแพ็กเกจ ไม่ควรต้องใช้สำหรับแอปพลิเคชันทั่วไป"</string>
     <string name="permlab_serialPort" msgid="546083327654631076">"เข้าถึงพอร์ตอนุกรม"</string>
     <string name="permdesc_serialPort" msgid="2991639985224598193">"อนุญาตให้ผู้ถือสามารถเข้าถึงพอร์ตอนุกรมโดยใช้ SerialManager API"</string>
     <string name="permlab_accessContentProvidersExternally" msgid="5077774297943409285">"เข้าถึงผู้ให้บริการเนื้อหาจากภายนอก"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"วอลเปเปอร์"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"เปลี่ยนวอลเปเปอร์"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"ตัวฟังการแจ้งเตือน"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"ผู้เสนอเงื่อนไข"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN เปิดใช้งานแล้ว"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"เปิดใช้งาน VPN โดย <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"แตะเพื่อจัดการเครือข่าย"</string>
@@ -1394,7 +1439,7 @@
     <string name="media_shared" product="nosdcard" msgid="5830814349250834225">"ขณะนี้ที่เก็บข้อมูล USB ถูกใช้งานอยู่โดยคอมพิวเตอร์"</string>
     <string name="media_shared" product="default" msgid="5706130568133540435">"ขณะนี้การ์ด SD มีการใช้งานอยู่โดยคอมพิวเตอร์"</string>
     <string name="media_unknown_state" msgid="729192782197290385">"สื่อภายนอกอยู่ในสถานะที่ไม่รู้จัก"</string>
-    <string name="share" msgid="1778686618230011964">"แบ่งปัน"</string>
+    <string name="share" msgid="1778686618230011964">"แชร์"</string>
     <string name="find" msgid="4808270900322985960">"ค้นหา"</string>
     <string name="websearch" msgid="4337157977400211589">"ค้นเว็บ"</string>
     <string name="find_next" msgid="5742124618942193978">"ค้นหาถัดไป"</string>
@@ -1437,8 +1482,8 @@
     <string name="keyboardview_keycode_enter" msgid="2985864015076059467">"ป้อน"</string>
     <string name="activitychooserview_choose_application" msgid="2125168057199941199">"เลือกแอปพลิเคชัน"</string>
     <string name="activitychooserview_choose_application_error" msgid="8624618365481126668">"ไม่สามารถเปิด <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
-    <string name="shareactionprovider_share_with" msgid="806688056141131819">"แบ่งปันกับ"</string>
-    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"แบ่งปันด้วย <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
+    <string name="shareactionprovider_share_with" msgid="806688056141131819">"แชร์กับ"</string>
+    <string name="shareactionprovider_share_with_application" msgid="5627411384638389738">"แชร์ด้วย <xliff:g id="APPLICATION_NAME">%s</xliff:g>"</string>
     <string name="content_description_sliding_handle" msgid="415975056159262248">"ที่จับสำหรับเลื่อน แตะค้างไว้"</string>
     <string name="description_target_unlock_tablet" msgid="3833195335629795055">"กวาดเพื่อปลดล็อก"</string>
     <string name="keyboard_headset_required_to_hear_password" msgid="7011927352267668657">"เสียบชุดหูฟังเพื่อฟังเสียงเมื่อพิมพ์รหัสผ่าน"</string>
@@ -1482,7 +1527,7 @@
     <string name="sha1_fingerprint" msgid="7930330235269404581">"ลายนิ้วมือ SHA-1"</string>
     <string name="activity_chooser_view_see_all" msgid="4292569383976636200">"ดูทั้งหมด"</string>
     <string name="activity_chooser_view_dialog_title_default" msgid="4710013864974040615">"เลือกกิจกรรม"</string>
-    <string name="share_action_provider_share_with" msgid="5247684435979149216">"แบ่งปันกับ"</string>
+    <string name="share_action_provider_share_with" msgid="5247684435979149216">"แชร์กับ"</string>
     <string name="list_delimeter" msgid="3975117572185494152">", "</string>
     <string name="sending" msgid="3245653681008218030">"กำลังส่ง…"</string>
     <string name="launchBrowserDefault" msgid="2057951947297614725">"เปิดเบราว์เซอร์หรือไม่"</string>
diff --git a/core/res/res/values-tl/strings.xml b/core/res/res/values-tl/strings.xml
index 0a5e64c..6e50517 100644
--- a/core/res/res/values-tl/strings.xml
+++ b/core/res/res/values-tl/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Walang pamagat&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"I-sync"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Masyadong maraming pagtanggal ng <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Puno na ang storage ng tablet. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Puno na ang storage ng relo. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Puno na ang storage ng telepono. Magtanggal ng ilang file upang magbakante ng espasyo."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Maaaring sinusubaybayan ang network"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ng isang di-kilalang third party"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"I-on ang ringer"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Nagsa-shut down…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Mag-shut down ang iyong tablet."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Magsa-shut down ang iyong relo."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Magsa-shut down ang iyong telepono."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Nais mo bang mag-shut down?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Mag-reboot sa safe mode"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Airplane mode"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Naka-ON ang airplane mode"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Naka-OFF ang airplane mode"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Mga Setting"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Safe mode"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android System"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Pinapayagan ang app na bawiin ang nilalaman ng aktibong window. Maaaring bawiin ng nakakahamak na apps ang kabuuang nilalaman ng window at suriin ang lahat ng teksto nito maliban sa mga password."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"pansamantalang paganahin ang accessibility"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Nagbibigay-daan sa isang application na pansamantalang paganahin ang accessibility sa device. Maaaring paganahin ng nakakahamak na apps ang accessibility nang walang pahintulot ng user."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"kunin ang token ng window"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Nagbibigay-daan sa isang application upang makuha ang token ng window. Maaaring magsagawa ng hindi pinapahintulutang pakikipag-ugnayan ang mga nakakahamak na app sa window ng application nang nagkukunwari bilang ang system."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"kunin ang mga istatistika ng frame"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Nagbibigay-daan sa isang application upang mangolekta ng mga istatistika ng frame. Maaaring mag-obserba ng mga window mula sa ibang mga app ang mga nakakahamak na app."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"i-filter ang mga kaganapan"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Pinapayagan ang isang application na magrehistro ng filter ng input na nagpi-filter sa stream ng lahat ng kaganapan ng user bago maipadala ang mga iyon. Maaaring kontrolin ng nakakahamak na app ang system UI nang hindi nakikialam ang user."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"bahagyang pag-shutdown"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Pinapayagan ang app na mag-broadcast ng isang notification na natanggap ang isang mensaheng SMS. Maaari itong gamitin ng nakakahamak na apps upang dayain ang papasok na mga mensaheng SMS."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"ipadala ang WAP-PUSH-natanggap na pag-broadcast"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Pinapayagan ang app na mag-broadcast ng isang notification na natanggap ang isang mensaheng WAP PUSH. Maaari itong gamitin ng nakakahamak na apps upang dayain ang pagtanggap ng mensaheng MMS o upang tahimik na palitan ang nilalaman ng anumang webpage ng mga nakakahamak na variant."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"magpadala ng broadcast ng mga network ng score"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Nagbibigay-daan sa app na mag-broadcast ng notification na kailangang ma-score ng mga network. Hindi kailanman kinakailangan para sa mga normal na app."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"limitahan ang numero ng mga tumatakbong proseso"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Pinapayagan ang app na kontrolin ang maximum na bilang ng mga proseso na tatakbo. Hindi kailanman kinakailangan para sa normal na apps."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"pwersahin ang mga app sa background na magsara"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng Vpn. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"sumailalim sa wallpaper"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng isang wallpaper. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"i-bind sa isang voice interactor"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Nagbibigay-daan sa may-hawak na i-bind ang top-level na interface ng isang serbisyo sa pakikipag-ugnayan gamit ang boses. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"magpasaklaw sa isang remote na display"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Binibigyang-daan ang may-hawak na masaklaw ang pinakamataas na antas ng interface ng isang remote na display. Hindi dapat kailanman kailanganin ng normal na apps."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"itali sa serbisyo ng widget"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Pinapayagan ang may-hawak na sumailalim sa nangungunang interface ng serbisyo ng widget. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"mag-bind sa isang serbisyo ng route provider"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Nagbibigay-daan sa may-pahintulot na mag-bind sa anumang nakarehistrong route provider. Hindi dapat kailanganin kailanman ng mga normal na app."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"makipag-ugnay sa tagapangasiwa ng device"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Pinapayagan ang mga may-ari na magpadala ng mga layunin sa administrator ng device. Hindi kailanman dapat na kailanganin para sa normal na apps."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"i-bind sa isang TV input"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Pinapayagan ang may-hawak na mag-bind sa top-level na interface ng isang TV input. Hindi kailanman kakailanganin ng mga normal na app."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"magdagdag o mag-alis ng admin ng device"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Pinapayagan ang may-ari na magdagdag o mag-alis ng mga aktibong administrator ng device. Hindi dapat kailanganin kailanman para sa normal na apps."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"baguhin ang orientation ng screen"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Pinapayagan ang app na basahin ang personal na impormasyon ng profile na naka-imbak sa iyong device, gaya ng iyong pangalan at impormasyon sa pakikipag-ugnay. Nangangahulugan ito na makikilala ka ng app at maaari nitong ipadala ang impormasyon ng iyong profile sa iba."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"baguhin sarili mo contact card"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Pinapayagan ang app na baguhin ang o magdagdag sa personal na impormasyon ng profile na naka-imbak sa iyong device, gaya ng iyong pangalan at impormasyon sa pakikipag-ugnay. Nangangahulugan ito na makikilala ka ng app at maaari nitong ipadala ang impormasyon ng iyong profile sa iba."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"mga sensor sa katawan (gaya ng mga heart rate monitor)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Pinapayagan ang app na i-access ang data mula sa mga sensor na ginagamit mo upang sukatin kung anong nangyayari sa iyong katawan, gaya ng heart rate."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"basahin ang iyong social stream"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Pinapayagan ang app na mag-access at mag-sync ng mga social na update mula sa iyo at sa iyong mga kaibigan. Maging maingat kapag nagbabahagi ng impormasyon -- pinapayagan nito ang app na magbasa ng mga pakikipag-ugnayan sa pagitan mo at ng iyong mga kaibigan sa mga social network, ano pa man ang katayuan sa pagiging kumpedensyal nito. Tandaan: hindi maaaring ipatupad ang pahintulot na ito sa lahat ng social network."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"magsulat sa iyong social stream"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Baguhin ang katayuan ng WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Pinapayagan ang app na ikonekta ang tablet at idiskonekta ang tablet mula sa mga WiMAX network."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Pinapayagan ang app na ikonekta ang telepono at idiskonekta ang telepono mula sa mga WiMAX network."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"mga network ng score"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Nagbibigay-daan sa app na iranggo ang mga network at impluwensiyahan kung aling mga network ang dapat na piliin ng tablet."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Nagbibigay-daan sa app na iranggo ang mga network at impluwensiyahan kung aling mga network ang dapat na piliin ng telepono."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ipares sa mga Bluetooth device"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa tablet, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Pinapayagan ang app na tingnan ang configuration ng Bluetooth sa telepono, at na gumawa at tumanggap ng mga koneksyong may mga nakapares na device."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Pinapayagan ang app na kumuha, sumuri, at mag-clear ng mga notification, kabilang ang mga na-post ng iba pang apps."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"mapailalim sa isang serbisyo ng notification listener"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Nagbibigay-daan sa may-ari na mapailalim sa interface sa tuktok na antas ng isang serbisyo ng notification listener. Hindi dapat kailanganin para sa karaniwang apps kahit kailan."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"i-bind sa isang serbisyo sa pagbibigay ng kundisyon"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Nagbibigay-daan sa naghahawak na i-bind ang top-level na interface ng isang serbisyo sa pagbibigay ng kundisyon. Hindi kailanman dapat kailanganin ng mga normal na app."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"paganahin ang app ng configuration na ibinigay ng carrier"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Nagbibigay-daan sa may-ari na paganahin ang app ng configuration na ibinigay ng carrier. Hindi dapat kailanganin para sa normal na apps kahit kailan."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"makinig sa mga obserbasyon sa mga kundisyon ng network"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Wallpaper"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Baguhin ang wallpaper"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Notification listener"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Nagbibigay ng kundisyon"</string>
     <string name="vpn_title" msgid="19615213552042827">"Naka-activate ang VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Isinaaktibo ang VPN ng <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Pindutin upang pamahalaan ang network."</string>
diff --git a/core/res/res/values-tr/strings.xml b/core/res/res/values-tr/strings.xml
index 72e149f..bd2f926 100644
--- a/core/res/res/values-tr/strings.xml
+++ b/core/res/res/values-tr/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Adsız&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Senk."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Çok fazla <xliff:g id="CONTENT_TYPE">%s</xliff:g> silme var."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Tabletin depolama alanı dolu! Yer açmak için bazı dosyaları silin."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Saat depolama alanınız dolu. Lütfen yer boşaltmak için bazı dosyaları silin."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Telefonun depolama alanı dolu! Yer açmak için bazı dosyaları silin."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Ağ izlenebilir"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Bunu, bilinmeyen üçüncü taraflar yapabilir"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Telefon zili açık"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Kapanıyor…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Tabletiniz kapanacak."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Saatiniz kapatılacak."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Telefonunuz kapanacak."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Kapatmak istiyor musunuz?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Güvenli modda yeniden aç"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Uçak modu"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Uçak modu AÇIK"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Uçak modu KAPALI"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Ayarlar"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Güvenli mod"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android Sistemi"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Uygulamaya, etkin pencerenin içeriğini alma izni verir. Kötü amaçlı uygulamalar tüm pencere içeriğini alabilir ve şifreleri hariç tüm metni inceleyebilir."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"erişilebilirliği geçici olarak etkinleştir"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Uygulamaya, cihazda erişilebilirliği geçici olarak etkinleştirme izni verir. Kötü amaçlı uygulamalar, kullanıcının izni olmadan erişilebilirliği etkinleştirebilirler."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"pencere kodunu alma"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Bir uygulamanın pencere kodunu almasına izin verir. Zararlı uygulamalar, uygulama penceresi yerine geçme sistemiyle yetkisiz etkileşim gerçekleştirebilir."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"çerçeve istatistiklerini alma"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Bir uygulamanın çerçeve istatistikleri toplamasına izin verir. Zararlı uygulamalar, diğer uygulamalardan pencerelerin çerçeve istatistiklerini alabilirler."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"etkinlikleri filtrele"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Uygulamaya, tüm kullanıcı etkinlikleri dağıtılmadan önce ilgili akışa filtre uygulayan bir giriş filtresi kaydetme izni verir. Zararlı uygulamalar kullanıcı müdahalesi olmadan sistem arayüzünü denetleyebilir."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"kısmi kapatma"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Uygulamaya, SMS mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte SMS mesajları göndermek için bunu kullanabilir."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"WAP-PUSH ile alınan yayın gönder"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Uygulamaya, WAP PUSH mesajı alındığına dair bildirim yayınlama izni verir. Kötü amaçlı uygulamalar sahte MMS bildirimleri oluşturmak veya bir web sayfasının içeriğini sessiz şekilde zararlı öğelerle değiştirmek için bunu kullanabilir."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"ağları puanlama yayını gönderme"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Uygulamaya, ağların puanlanması gerektiği bildirimini yayınlama izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"çalışan işlem sayısını sınırla"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Uygulamaya, çalışacak süreçlerin azami sayısını denetleme izni verir. Normal uygulamalar için gerekli değildir."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"arka plan uygulamaları kapanmaya zorla"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cihazın sahibine bir VPN hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"bir duvar kağıdına tabi kıl"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cihazın sahibine, duvar kağıdının en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"bir ses etkileşimi hizmetine bağlanma"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"İzin sahibinin, bir ses etkileşimi hizmetine ait üst düzey arayüze bağlanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"uzak ekrana bağlan"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"İzin sahibine, bir uzak ekranın en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bir widget hizmetine bağla"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cihazın sahibine bir widget hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"rota sağlayıcı hizmetine bağlanma"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"İzin verilen uygulamaya tüm kayıtlı rota sağlayıcılarına bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"bir cihaz yöneticisi ile etkileşimde bulun"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cihazın sahibinin cihaz yöneticisine amaç göndermesine izin verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"TV girişine bağlanma"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"İzin sahibine, bir TV girişinin en üst düzey arayüzüne bağlanma olanağı verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"cihaz yöneticisi ekle veya kaldır"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"İzin sahibine, etkin cihaz yöneticileri ekleyip kaldırma izni verir. Normal uygulamalar için hiçbir zaman gerekmez."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"ekran yönünü değiştir"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Uygulamaya adınız ve iletişim bilgileriniz gibi cihazınızda saklanan kişisel profil bilgilerini okuma izni verir. Bu izin, uygulamanın sizi tanımlayabileceği ve profil bilgilerinizi başkalarına gönderebileceği anlamına gelir."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"kendi kişi kartınızı değiştirme"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Uygulamaya adınız ve iletişim bilgileriniz gibi cihazınızda saklanan kişisel profil bilgilerini değiştirme veya bunlara ekleme yapma izni verir. Bu izin, uygulamanın sizi tanımlayabileceği ve profil bilgilerinizi başkalarına gönderebileceği anlamına gelir."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"vücut sensörleri (kalp atış hızı takip cihazları gibi)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Uygulamanın, kalp atış hızınız gibi vücudunuzla ilgili olayları ölçmek için kullandığınız sensörlerden gelen verilere erişmesine izin verir."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"sosyal akışınızı okuma"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Uygulamaya size veya arkadaşlarınıza ait sosyal güncellemelere erişme ve bunları senkronize etme izni verir. Bilgi paylaşırken dikkatli olun. Bu izin, uygulamanın sosyal ağlarda sizinle arkadaşlarınız arasındaki iletişimi, gizliliğine bakılmaksızın okumasına olanak sağlar. Not: Bu izin tüm sosyal ağlar için geçerli olmayabilir."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"sosyal akışınıza yazma"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"WiMAX durumunu değiştir"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Uygulamaya, tableti WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Uygulamaya, telefonu WiMAX ağlarına bağlanma veya bağlantıyı kesme izni verir."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"ağları puanlama"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Uygulamaya, ağları sıralama ve tabletin tercih edeceği ağları etkileme izni verir."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Uygulamaya, ağları sıralama ve telefonunun tercih edeceği ağları etkileme izni verir."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"Bluetooth cihazlarla eşle"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Uygulamaya, tabletteki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Uygulamaya, telefondaki Bluetooth yapılandırmasını görüntüleme, eşleştirilmiş cihazlarla bağlantı yapma ve bu tür bağlantıları kabul etme izni verir."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Uygulamanın bildirimler almasına, bildirimleri incelemesine ve temizlemesine izin verir. Buna diğer uygulamalar tarafından yayınlanan bildirimler de dahildir."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bildirim dinleyici hizmetine bağlan"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"İzin sahibine bir bildirim dinleyici hizmetinin en üst düzey arayüzüne bağlanma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"bir durum sağlayıcı hizmetine bağlanma"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"İzin sahibinin, bir durum sağlayıcı hizmete ait üst düzey arayüze bağlanmasına izin verir. Normal uygulamalar için hiçbir zaman gerekli değildir."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"operatör tarafından sağlanan yapılandırma uygulamasını çalıştır"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"İzin sahibine, operatör tarafından sağlanan yapılandırma uygulamasını çalıştırma izni verir. Normal uygulamalarda hiçbir zaman gerek duyulmaz."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"ağ koşullarındaki gözlemleri dinle"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Duvar Kağıdı"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Duvar kağıdını değiştir"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Bildirim dinleyici"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Durum sağlayıcı"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN etkinleştirildi"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN, <xliff:g id="APP">%s</xliff:g> tarafından etkinleştirildi"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Ağı yönetmek için dokunun."</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 563d5ee..d01c5776 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Без назви&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">".."</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Синхр."</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Забагато видалень <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Пам’ять планшетного ПК заповнено. Видаліть якісь файли, щоб звільнити місце."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Пам’ять годинника заповнено. Видаліть файли, щоб звільнити місце."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Пам’ять телефону заповнено. Видаліть якісь файли, щоб звільнити місце."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Мережа може відстежуватися"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Невідомою третьою стороною"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Дзвінок увімкнено"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Вимкнення..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ваш пристрій буде вимкнено."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Годинник буде вимкнено."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ваш телефон буде вимкнено."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Вимкнути?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Перейти в безпечний режим"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Режим польоту"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Режим польоту ВВІМК."</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Режим польоту ВИМК."</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Налаштування"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Безп. режим"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Система Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Дозволяє програмі отримувати вміст активного вікна. Шкідливі програми можуть отримувати весь вміст вікна та вивчати весь його текст, окрім паролів."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"тимчасово вмикати доступність"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Дозволяє програмі тимчасового вмикати доступність на пристрої. Шкідливі програми можуть вмикати доступність без згоди користувача."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"отримувати маркер вікна"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Дозволяє додатку отримувати маркер вікна. Шкідливі додатки можуть без дозволу взаємодіяти з вікном додатка, видаючи себе за систему."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"отримувати статистику частоти кадрів"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Дозволяє додатку збирати статистику частоти кадрів. Шкідливі додатки можуть відстежувати частоту кадрів у вікнах інших додатків."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"фільтрувати події"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Дозволяє програмі реєструвати вхідний фільтр, який фільтрує потік усіх подій користувача перед їх надсиланням. Шкідливі програми можуть контролювати інтерфейс системи без втручання користувача."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"частк. заверш. роб."</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Дозволяє програмі передавати сповіщення про отримання SMS повідомлення. Шкідливі програми можуть використовувати це для підробки вхідних SMS повідомлень."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"надсил. запис, отр. через WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Дозволяє програмі передавати сповіщення про отримання повідомлення WAP PUSH. Шкідливі програми можуть використовувати це для підробки отримання MMS повідомлень або для непомітної заміни вмісту будь-якої веб-сторінки шкідливими варіантами."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"надсилати сповіщення про оцінку мереж"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Дозволяє додатку передавати сповіщення про оцінку мереж. Ніколи не застосовується для звичайних додатків."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"обмежувати кількість запущ. процесів"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Дозволяє програмі контролювати максимальну кількість процесів, які буде запущено. Ніколи не вимагається для звичайних програм."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"примусово закривати фонові програми"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби VPN. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"прив’язати до фонового малюнка"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня фонового малюнка. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"підключитися до служби голосової взаємодії"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби голосової взаємодії. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"прив’язуватися до віддаленого екрана"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня віддаленого екрана. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"прив\'язувати до служби віджетів"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Дозволяє власникові прив’язуватися до інтерфейсу верхнього рівня служби віджетів. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"підключитися до служби постачання маршрутів"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Дозволяє власникові підключатися до зареєстрованих постачальників маршрутів. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"взаємодіяти з адмін. пристрою"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Дозволяє власнику надсилати задавані функції адміністратору пристрою. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"підключатися до TV-входу"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Додаток зможе підключатися до інтерфейсу верхнього рівня TV-входу. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"додавати чи вилучати адміністраторів пристрою"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Дозволяє власнику додавати чи вилучати активних адміністраторів пристрою. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"змінювати орієнтацію екрана"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Дозволяє програмі читати особисту інформацію профілю, збережену на пристрої, як-от ваше ім’я та контактну інформацію. Це означає, що програма може ідентифікувати вашу особу та надсилати дані вашого профілю іншим."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"змінювати картки контактів"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Дозволяє програмі змінювати чи додавати особисту інформацію профілю, збережену на пристрої, як-от ваше ім’я та контактну інформацію. Це означає, що програма може ідентифікувати вашу особу та надсилати дані вашого профілю іншим."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"датчики на тілі (як-от пульсометр)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Дозволяє додатку отримувати дані з датчиків, які вимірюють фізіологічні процеси, як-от пульс."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"читати ваш соціальний потік"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Дозволяє програмі отримувати доступ до оновлень із соціальних мереж від вас і ваших друзів та синхронізувати їх. Будьте обережні, надаючи доступ до інформації – це дозволяє програмі читати повідомлення, якими ви та ваші друзі обмінювалися в соціальних мережах, незалежно від конфіденційності. Зауважте: цей дозвіл не можна застосовувати в усіх соціальних мережах."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"писати у ваш соціальний потік"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Змінити стан WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Дозволяє програмі під’єднувати планшетний ПК до мереж WiMAX і від’єднувати його від них."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Дозволяє програмі під’єднувати телефон до мереж WiMAX і від’єднувати його від них."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"оцінювати мережі"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Дозволяє додатку оцінювати мережі та впливати на вибір мережі планшетом."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Дозволяє додатку оцінювати мережі та впливати на вибір мережі телефоном."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"створювати пару з пристроями Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Дозволяє програмі переглядати конфігурацію Bluetooth на планшетному ПК, а також створювати та приймати з’єднання зі спареними пристроями."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Дозволяє програмі переглядати конфігурацію Bluetooth на телефоні, а також створювати та приймати з’єднання зі спареними пристроями."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Дозволяє програмі отримувати, перевіряти й очищати сповіщення, зокрема опубліковані іншими програмами."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"прив’язуватися до служби читання сповіщень"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Дозволяє власнику прив’язуватися до інтерфейсу верхнього рівня служби читання сповіщень. Ніколи не застосовується для звичайних програм."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"підключитися до служби постачання умов"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Додаток зможе підключатися до інтерфейсу верхнього рівня служби постачання умов. Звичайні додатки ніколи не використовують цей дозвіл."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"викликати надану оператором програму конфігурації"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Дозволяє власнику викликати надану оператором програму конфігурації. Ніколи не застосовується для звичайних програм."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"прослуховувати дані спостережень за станом мережі"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Фоновий мал."</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Змінити фоновий малюнок"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Служба читання сповіщень"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Постачальник умов"</string>
     <string name="vpn_title" msgid="19615213552042827">"Мережу VPN активовано"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"Мережу VPN активовано програмою <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Торкніться, щоб керувати мережею."</string>
diff --git a/core/res/res/values-vi/strings.xml b/core/res/res/values-vi/strings.xml
index 8c424c3..24b2db5 100644
--- a/core/res/res/values-vi/strings.xml
+++ b/core/res/res/values-vi/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Không có tiêu đề&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Đồng bộ hóa"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Quá nhiều lần xóa <xliff:g id="CONTENT_TYPE">%s</xliff:g>."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Bộ nhớ máy tính bảng đã đầy. Hãy xóa một số tệp để tạo thêm dung lượng."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Bộ nhớ đồng hồ đã đầy. Hãy xóa một số tệp để giải phóng dung lượng."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Bộ nhớ điện thoại đã đầy. Hãy xóa một số tệp để tạo thêm dung lượng."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Mạng có thể được giám sát"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Bởi một bên thứ ba không xác định"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Bật chuông"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Đang tắt…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Máy tính bảng của bạn sẽ tắt."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Đồng hồ của bạn sẽ tắt."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Điện thoại của bạn sẽ tắt."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Bạn có muốn tắt không?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Khởi động lại ở chế độ an toàn"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Chế độ trên máy bay"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Chế độ trên máy bay BẬT"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Chế độ trên máy bay TẮT"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Cài đặt"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Chế độ an toàn"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Hệ thống Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Cho phép ứng dụng truy xuất nội dung của cửa sổ hiện hành. Ứng dụng độc hại có thể truy xuất toàn bộ nội dung của cửa sổ cũng như xem xét toàn bộ văn bản của cửa sổ ngoại trừ mật khẩu."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"tạm thời bật trợ năng"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Cho phép ứng dụng tạm thời bật trợ năng trên thiết bị. Các ứng dụng độc hại có thể bật trợ năng mà không có sự đồng ý của người dùng."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"truy xuất mã thông báo cửa sổ"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Cho phép một ứng dụng truy xuất mã thông báo cửa sổ. Các ứng dụng độc hại có thể thực hiện hoạt động tương tác trái phép với cửa sổ ứng dụng mạo danh hệ thống."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"truy xuất số liệu thống kê về khung"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Cho phép một ứng dụng thu thập số liệu thống kê về khung. Ứng dụng độc hại có thể quan sát số liệu thống kê về khung của cửa sổ từ ứng dụng khác."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"lọc sự kiện"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Cho phép ứng dụng đăng ký bộ lọc dữ liệu nhập để lọc luồng tất cả các sự kiện người dùng trước khi chúng được gửi đi. Ứng dụng độc hại có thể kiểm soát Giao diện người dùng hệ thống mà không cần sự can thiệp của người dùng."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"tắt từng phần"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Cho phép ứng dụng truyền phát thông báo cho biết đã nhận được tin nhắn SMS. Ứng dụng độc hại có thể sử dụng quyền này để giả mạo tin nhắn SMS đến."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"gửi truyền phát WAP-PUSH nhận được"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Cho phép ứng dụng truyền phát thông báo cho biết rằng đã nhận được tin nhắn WAP PUSH. Ứng dụng độc hại có thể sử dụng quyền này để giả mạo xác nhận đã nhận được tin nhắn MMS hoặc ngầm thay thế nội dung của bất kỳ trang web nào bằng các biến thể độc hại."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"gửi chương trình phát mạng điểm số"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Cho phép ứng dụng truyền thông báo rằng các mạng cần để được tính điểm. Không bao giờ cần cho ứng dụng thông thường."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"giới hạn số quá trình đang chạy"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Cho phép ứng dụng kiểm soát số quy trình tối đa sẽ chạy. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"buộc ứng dụng nền đóng"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ Vpn. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"liên kết với hình nền"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của hình nền. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"liên kết với trình tương tác bằng giọng nói"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tương tác bằng giọng nói. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"liên kết với màn hình từ xa"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của màn hình từ xa. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"liên kết với dịch vụ tiện ích con"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ tiện ích con. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"liên kết với dịch vụ nhà cung cấp định tuyến"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Cho phép chủ sở hữu liên kết với bất kỳ nhà cung cấp định tuyến đã đăng ký nào. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"tương tác với quản trị viên thiết bị"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Cho phép chủ sở hữu gửi các ý định đến quản trị viên thiết bị. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"liên kết với đầu vào TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của đầu vào TV. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"thêm hoặc xóa quản trị viên thiết bị"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Cho phép chủ sở hữu thêm hoặc xóa quản trị viên thiết bị đang hoạt động. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"thay đổi hướng màn hình"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Cho phép ứng dụng đọc thông tin tiểu sử cá nhân được lưu trữ trên thiết bị, chẳng hạn như tên và thông tin liên hệ của bạn. Điều này có nghĩa là ứng dụng có thể xác định danh tính của bạn và gửi thông tin tiểu sử của bạn cho người khác."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"sửa đổi thẻ liên hệ của riêng bạn"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Cho phép ứng dụng thay đổi hoặc thêm vào thông tin tiểu sử cá nhân được lưu trữ trên thiết bị, chẳng hạn như tên và thông tin liên hệ của bạn. Điều này có nghĩa là ứng dụng có thể xác định danh tính của bạn và gửi thông tin tiểu sử của bạn cho người khác."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"cảm biến cơ thể (như máy đo nhịp tim)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Cho phép ứng dụng truy cập dữ liệu từ cảm biến mà bạn sử dụng để đo những gì đang diễn ra bên trong cơ thể của bạn, chẳng hạn như nhịp tim."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"đọc luồng xã hội của bạn"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Cho phép ứng dụng truy cập và đồng bộ hóa các cập nhật xã hội của bạn và bạn bè bạn. Hãy cẩn trọng khi chia sẻ thông tin -- việc này có thể cho phép ứng dụng đọc thông tin liên lạc giữa bạn và bạn bè bạn trên các mạng xã hội, bất kể tính bí mật là gì. Lưu ý: quyền này có thể không được thực thi trên tất cả các mạng xã hội."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"ghi luồng xã hội của bạn"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Thay đổi trạng thái WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Cho phép ứng dụng kết nối máy tính bảng và ngắt kết nối máy tính bảng khỏi mạng WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Cho phép ứng dụng kết nối điện thoại và ngắt kết nối điện thoại khỏi mạng WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"mạng điểm số"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Cho phép ứng dụng xếp hạng mạng và ảnh hưởng đến việc máy tính bảng nên ưu tiên mạng nào."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Cho phép ứng dụng xếp hạng các mạng và ảnh hưởng đến việc điện thoại nên ưu tiên mạng nào."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"ghép nối với thiết bị Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Cho phép ứng dụng xem cấu hình của Bluetooth trên máy tính bảng và tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Cho phép ứng dụng xem cấu hình của Bluetooth trên điện thoại, tạo và chấp nhận các kết nối với các thiết bị được ghép nối."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Cho phép ứng dụng truy xuất, kiểm tra và xóa thông báo, bao gồm những thông báo được đăng bởi các ứng dụng khác."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"liên kết với dịch vụ trình xử lý thông báo"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình xử lý thông báo. Không cần thiết cho các ứng dụng thông thường."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"liên kết với dịch vụ trình cung cấp điều kiện"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Cho phép chủ sở hữu liên kết với giao diện cấp cao nhất của dịch vụ trình cung cấp điều kiện. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Cho phép chủ sở hữu gọi ra ứng dụng cấu hình do nhà cung cấp dịch vụ cung cấp. Không cần thiết cho các ứng dụng thông thường."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"quan sát các điều kiện mạng"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Hình nền"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Thay đổi hình nền"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Trình xử lý thông báo"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Trình cung cấp điều kiện"</string>
     <string name="vpn_title" msgid="19615213552042827">"Đã kích hoạt VPN"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"VPN được <xliff:g id="APP">%s</xliff:g> kích hoạt"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Chạm để quản lý mạng."</string>
diff --git a/core/res/res/values-watch/config.xml b/core/res/res/values-watch/config.xml
new file mode 100644
index 0000000..1dd4608
--- /dev/null
+++ b/core/res/res/values-watch/config.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<!-- These resources are around just to allow their values to be customized
+     for watch products.  Do not translate. -->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+
+    <!-- Only show power and settings items due to smaller real estate. -->
+    <string-array translatable="false" name="config_globalActionsList">
+        <item>power</item>
+        <item>settings</item>
+    </string-array>
+
+    <!-- Base "touch slop" value used by ViewConfiguration as a
+         movement threshold where scrolling should begin. -->
+    <dimen name="config_viewConfigurationTouchSlop">4dp</dimen>
+</resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index acb4a81..9297e3a 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -77,14 +99,14 @@
     <string name="serviceNotProvisioned" msgid="8614830180508686666">"未提供服务。"</string>
     <string name="CLIRPermanent" msgid="3377371145926835671">"您无法更改来电显示设置。"</string>
     <string name="RestrictedChangedTitle" msgid="5592189398956187498">"网络可用情况发生变化"</string>
-    <string name="RestrictedOnData" msgid="8653794784690065540">"数据服务已禁用。"</string>
-    <string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已禁用。"</string>
-    <string name="RestrictedOnNormal" msgid="4953867011389750673">"已禁用语音服务。"</string>
-    <string name="RestrictedOnAllVoice" msgid="3396963652108151260">"已停用所有语音服务。"</string>
-    <string name="RestrictedOnSms" msgid="8314352327461638897">"已禁用短信服务。"</string>
-    <string name="RestrictedOnVoiceData" msgid="996636487106171320">"已停用语音/数据服务。"</string>
-    <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"已禁用语音/短信服务。"</string>
-    <string name="RestrictedOnAll" msgid="5643028264466092821">"已停用所有语音/数据/短信服务。"</string>
+    <string name="RestrictedOnData" msgid="8653794784690065540">"数据网络服务已停用。"</string>
+    <string name="RestrictedOnEmergency" msgid="6581163779072833665">"紧急服务已停用。"</string>
+    <string name="RestrictedOnNormal" msgid="4953867011389750673">"语音服务已停用。"</string>
+    <string name="RestrictedOnAllVoice" msgid="3396963652108151260">"所有语音服务都已停用。"</string>
+    <string name="RestrictedOnSms" msgid="8314352327461638897">"短信服务已停用。"</string>
+    <string name="RestrictedOnVoiceData" msgid="996636487106171320">"语音/数据服务已停用。"</string>
+    <string name="RestrictedOnVoiceSms" msgid="1888588152792023873">"语音/短信服务已停用。"</string>
+    <string name="RestrictedOnAll" msgid="5643028264466092821">"所有语音/数据/短信服务都已停用。"</string>
     <string name="serviceClassVoice" msgid="1258393812335258019">"语音"</string>
     <string name="serviceClassData" msgid="872456782077937893">"数据"</string>
     <string name="serviceClassFAX" msgid="5566624998840486475">"传真"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同步"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"太多<xliff:g id="CONTENT_TYPE">%s</xliff:g>删除项。"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"平板电脑存储空间已满。请删除一些文件以腾出空间。"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"手表存储空间已满。请删除一些文件以腾出空间。"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"手机存储空间已满。请删除一些文件以腾出空间。"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"网络可能会受到监控"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"受到不明第三方的监控"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"振铃器开启"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"正在关机..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板电脑会关闭。"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手表即将关机。"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手机将会关机。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要关机吗?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"重新启动并进入安全模式"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飞行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"已开启飞行模式"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"未开启飞行模式"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"设置"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系统"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允许应用检索活动窗口的内容。恶意应用可能会检索整个窗口的内容,并检查其中除密码以外的所有文字。"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暂时启用辅助功能"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允许应用在设备上暂时启用辅助功能。恶意应用可能会在未经用户同意的情况下擅自启用辅助功能。"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"检索窗口令牌"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"允许应用检索窗口令牌。恶意软件可能会借此在未经授权的情况下冒充系统与应用窗口进行互动。"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"检索框架统计信息"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"允许应用收集框架统计信息。恶意应用可能会借此监测其他应用的窗口框架统计信息。"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"过滤事件"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"允许应用注册输入过滤器,这类过滤器会在所有用户事件分派之前对用户事件流进行过滤。恶意应用可能会在没有用户干预的情况下控制系统用户界面。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分关机"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允许应用广播一条有关已收到短信的通知。恶意应用可能借此伪造接到的短信。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"发送 WAP-PUSH 收到的广播"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允许应用广播一条有关已收到 WAP PUSH 短信的通知。恶意应用可能借此伪造短信接收,或在后台将任意网页的内容替换为恶意内容。"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"发送网络评分广播通知"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允许应用广播“需要为网络评分”的通知。普通应用绝不需要此权限。"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"限制运行的进程个数"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允许应用控制将运行的进程数上限。普通应用绝不需要此权限。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"强制关闭后台应用"</string>
@@ -378,12 +409,20 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允许用户绑定到 VPN 服务的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"绑定到壁纸"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允许用户绑定到壁纸的顶级接口。普通应用绝不需要此权限。"</string>
+    <!-- no translation found for permlab_bindVoiceInteraction (5334852580713715068) -->
+    <skip />
+    <!-- no translation found for permdesc_bindVoiceInteraction (2345721766501778101) -->
+    <skip />
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"绑定至远程显示屏"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允许应用绑定至远程显示屏的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"绑定到小部件服务"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允许应用绑定到小部件服务的顶级接口。普通应用绝不需要此权限。"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"绑定到路由程序服务"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允许应用绑定到任何已注册的路由程序。普通应用绝不需要此权限。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"与设备管理器交互"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允许用户将意向发送给设备管理员。普通应用绝不需要此权限。"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"绑定至电视输入设备"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"允许应用绑定至电视输入设备的顶级接口。普通应用绝不需要此权限。"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"添加或删除设备管理员"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允许应用添加或删除有效的设备管理员。普通应用绝不需要此权限。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕显示方向"</string>
@@ -458,6 +497,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"允许该应用读取您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着该应用可以识别您的身份,并可能将您的个人资料信息发送给他人。"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"修改您自己的名片"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允许该应用更改或添加您设备上存储的个人资料信息,例如您的姓名和联系信息。这意味着该应用可以识别您的身份,并可能将您的个人资料信息发送给他人。"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"人体传感器(如心跳速率检测器)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允许应用访问您用于测量身体状况(如心跳速率)的传感器中的数据。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"读取您的社交信息流"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允许该应用访问并同步您和朋友的社交动态信息。在分享信息时一定要小心,因为此权限可让该应用读取您与社交网络上的朋友之间的交流信息。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"写入您的社交信息流"</string>
@@ -594,8 +635,8 @@
     <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"允许该应用获取手机已知的帐户列表,其中可能包括由已安装的应用创建的所有帐户。"</string>
     <string name="permlab_authenticateAccounts" msgid="5265908481172736933">"创建帐户并设置密码"</string>
     <string name="permdesc_authenticateAccounts" msgid="5472124296908977260">"允许应用使用 AccountManager 的帐户身份验证程序功能,包括创建帐户以及获取和设置其密码。"</string>
-    <string name="permlab_manageAccounts" msgid="4983126304757177305">"添加或删除帐户"</string>
-    <string name="permdesc_manageAccounts" msgid="8698295625488292506">"允许应用执行添加帐户、删除帐户、删除帐户密码等操作。"</string>
+    <string name="permlab_manageAccounts" msgid="4983126304757177305">"添加或移除帐户"</string>
+    <string name="permdesc_manageAccounts" msgid="8698295625488292506">"允许应用执行添加帐户、移除帐户、删除帐户密码等操作。"</string>
     <string name="permlab_useCredentials" msgid="235481396163877642">"使用设备上的帐户"</string>
     <string name="permdesc_useCredentials" msgid="7984227147403346422">"允许应用请求身份验证令牌。"</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"查看网络连接"</string>
@@ -628,6 +669,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 状态"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允许该应用建立和断开平板电脑与 WiMAX 网络之间的连接。"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允许该应用建立和断开手机与 WiMAX 网络之间的连接。"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"为网络评分"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允许应用为网络评分,并控制平板电脑应优先使用的网络。"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允许应用为网络评分,并控制手机应优先使用的网络。"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"与蓝牙设备配对"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允许该应用查看平板电脑上的蓝牙配置,以及建立和接受与配对设备的连接。"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允许该应用查看手机上的蓝牙配置,以及建立和接受与配对设备的连接。"</string>
@@ -681,6 +725,10 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允许该应用检索、检查并清除通知,包括其他应用发布的通知。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"绑定到通知侦听器服务"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允许应用绑定到通知侦听器服务的顶级接口(普通应用绝不需要此权限)。"</string>
+    <!-- no translation found for permlab_bindConditionProviderService (1180107672332704641) -->
+    <skip />
+    <!-- no translation found for permdesc_bindConditionProviderService (1680513931165058425) -->
+    <skip />
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"调用运营商提供的配置应用"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允许应用调用运营商提供的配置应用。普通应用绝不需要此权限。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"监听网络状况的观测信息"</string>
@@ -1351,6 +1399,8 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"壁纸"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"更改壁纸"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知侦听器"</string>
+    <!-- no translation found for condition_provider_service_binding_label (1321343352906524564) -->
+    <skip />
     <string name="vpn_title" msgid="19615213552042827">"VPN 已激活"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"“<xliff:g id="APP">%s</xliff:g>”已激活 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"触摸可管理网络。"</string>
diff --git a/core/res/res/values-zh-rHK/strings.xml b/core/res/res/values-zh-rHK/strings.xml
index deb5a11..1c8cfe8 100644
--- a/core/res/res/values-zh-rHK/strings.xml
+++ b/core/res/res/values-zh-rHK/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Google Sync"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"平板電腦的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"手錶的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"手機的儲存空間已滿。請刪除一些檔案,以騰出可用空間。"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"網絡可能會受到監控"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"由不明的第三方監管"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"鈴聲開啟"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"正在關機..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板電腦將會關機。"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手錶即將關機。"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"您的手機即將關機。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要關機嗎?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"重新啟動進入安全模式"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛行模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛行模式為 [關閉]"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。惡意應用程式可能會擷取整個視窗的內容,以及檢視密碼除外的所有文字。"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暫時啟用協助工具"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允許應用程式在裝置上暫時啟用協助工具。惡意應用程式可能藉此在未經用戶同意的情況下擅自啟用協助工具。"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"擷取視窗憑證"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"允許應用程式擷取視窗憑證。惡意應用程式可能會在未經授權的情況下,與冒充系統的應用程式視窗互動。"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"擷取畫格統計資料"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"允許應用程式收集畫格統計資料。惡意應用程式可能會透過其他應用程式監察視窗畫格統計資料。"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有用戶活動的串流前先行篩選。惡意應用程式可能會繞過用戶操作,直接控制系統用戶介面。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允許應用程式在收到短訊時發出通知。惡意應用程式可能會藉此偽造外來短訊。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"傳送可由 WAP PUSH 接收的廣播"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允許應用程式在收到 WAP PUSH 訊息時發送通知。惡意應用程式可能會藉此偽造 MMS 訊息回條或私自以惡意內容更換網頁。"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"傳送網絡計分廣播"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允許應用程式廣播網絡需要計分的通知,但一般應用程式並不需要使用。"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"執行程序數目上限"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允許應用程式控制可執行程序的數量上限 (不建議一般應用程式使用)。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"強制關閉背景應用程式"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式繫結至 VPN 服務的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"繫結至桌布"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"繫結至語音互動器"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"允許應用程式繫結至語音互動服務的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端屏螢的頂層介面 (不建議一般應用程式使用)。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"繫結至路由供應商服務"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允許應用程式繫結至任何已註冊的路由供應商,但一般應用程式並不需要使用。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"允許應用程式繫結至電視訊號輸入裝置的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (不建議一般應用程式使用)。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"更改屏幕瀏覽方向"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"允許應用程式讀取裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這表示應用程式可以識別您的身份,並將您的個人資料傳送給他人。"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"修改自己的聯絡資料"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或更改裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這表示應用程式可以識別您的身份,並將您的個人資料傳送給他人。"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"身體感應器 (例如心跳監視器)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允許應用程式存取用於測量身體狀況感應器的資料,例如心跳。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"讀取您的社交串流"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允許應用程式存取並同步處理您和好友的最新動態。當您分享資訊時,請務必小心,因為這項權限允許應用程式讀取您和好友在社交網絡上的私人通訊,不論是否機密。注意:這項權限可能不適用於所有社交網絡。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"寫入您的社交串流"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"更改 WiMAX 狀態"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允許應用程式建立或中斷平板電腦與 WiMAX 網絡的連線。"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允許應用程式建立或中斷手機與 WiMAX 網絡的連線。"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"為網絡計分"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允許應用程式為網絡排名,及決定平板電腦偏好使用的網絡。"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允許應用程式為網絡排名,及決定手機偏好使用的網絡。"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"與藍牙裝置配對"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (不建議一般應用程式使用)。"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件供應商服務"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件供應商服務的頂層介面,但一般應用程式並不需要使用。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"調用流動網絡供應商提供的設定應用程式"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式調用流動網絡供應商提供的設定應用程式 (不建議一般應用程式使用)。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽對網絡狀況的觀察"</string>
@@ -963,7 +1007,7 @@
     <string name="permlab_setAlarm" msgid="1379294556362091814">"設定鬧鐘"</string>
     <string name="permdesc_setAlarm" msgid="316392039157473848">"允許應用程式在安裝的鬧鐘應用程式中設定鬧鐘,某些鬧鐘應用程式可能沒有這項功能。"</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"新增留言"</string>
-    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件匣。"</string>
+    <string name="permdesc_addVoicemail" msgid="6604508651428252437">"允許應用程式將訊息加到您的留言信箱收件箱。"</string>
     <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"修改瀏覽器地理資訊的權限"</string>
     <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"允許應用程式修改瀏覽器的地理資訊權限。惡意應用程式可能會藉此允許將您的位置資訊任意傳送給某些網站。"</string>
     <string name="permlab_packageVerificationAgent" msgid="5568139100645829117">"驗證套件"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件供應商"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用。"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網絡。"</string>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index b058860..05e0894 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;未命名&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"…"</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"同步處理"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"同時刪除太多 <xliff:g id="CONTENT_TYPE">%s</xliff:g>。"</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"平板電腦的儲存空間已滿。請刪除一些檔案,以釋放出可用空間。"</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"手錶儲存空間已用盡,請刪除一些檔案以釋出可用空間。"</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"手機儲存空間已滿。請刪除一些檔案,以釋放可用空間。"</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"網路可能會受到監控"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"受到不明的第三方監控"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"鈴聲開啟"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"關機中…"</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"您的平板電腦將會關機。"</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"您的手錶即將關機。"</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"手機即將關機。"</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"您要關機嗎?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"重新啟動進入安全模式"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"飛航模式"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"飛航模式為 [開啟]"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"飛航模式為 [關閉]"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"設定"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"超過 999"</string>
     <string name="safeMode" msgid="2788228061547930246">"安全模式"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Android 系統"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"允許應用程式擷取使用中的視窗內容。請注意,惡意應用程式可能利用此功能擷取完整視窗內容,並檢視密碼之外的所有文字。"</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"暫時啟用協助工具"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"允許應用程式在裝置上暫時啟用協助工具。惡意應用程式可能藉此在未經使用者同意的情況下擅自啟用協助工具。"</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"擷取視窗符記"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"允許應用程式擷取視窗符記。惡意應用程式可能會藉此在未經授權的情況下與模擬系統的應用程式視窗互動。"</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"擷取畫格統計資料"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"允許應用程式收集畫格統計資料。惡意應用程式可能會藉此得知其他應用程式的視窗畫格統計資料。"</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"篩選活動"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"允許應用程式註冊輸入篩選器,在分派所有使用者活動的串流前先行篩選。請注意,惡意應用程式可能藉此擅自控制系統使用者介面。"</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"部分關機"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"允許應用程式在收到 SMS 簡訊時發出通知。請注意,惡意應用程式可能利用此功能偽造外來的 SMS 簡訊。"</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"送出「WAP PUSH 已接收」廣播"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"允許應用程式在收到 WAP PUSH 訊息時發送通知。請注意,惡意應用程式可能利用此功能偽造 MMS 簡訊回條,或私自將網頁內容更換為惡意陷阱。"</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"傳送網路計分廣播通知"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"允許應用程式廣播「網路需計分」的通知訊息 (一般應用程式並不需要)。"</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"執行程序限制數"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"允許應用程式控制可執行程序的數量上限 (一般應用程式不需使用)。"</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"強制關閉背景應用程式"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"允許應用程式聯繫至 VPN 服務的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"連結至桌布"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"允許應用程式繫結至桌布的頂層介面 (一般應用程式不需使用)。"</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"繫結至語音互動器"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"允許應用程式繫結至語音互動服務的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"繫結至遠端螢幕"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"允許應用程式繫結至遠端螢幕的頂層介面 (一般應用程式不需使用)。"</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"繫結至小工具服務"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"允許應用程式繫結至小工具服務的頂層介面 (一般應用程式不需使用)。"</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"繫結至路由供應商服務"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"允許應用程式繫結至任何已註冊的路由供應商 (一般應用程式並不需要)。"</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"與裝置管理員互動"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"允許應用程式將調用請求傳送至裝置管理員 (一般應用程式不需使用)。"</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"繫結至電視訊號輸入裝置"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"允許應用程式繫結至電視訊號輸入裝置的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"新增或移除裝置管理員"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"允許應用程式新增或移除有效的裝置管理員 (一般應用程式並不需要)。"</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"變更螢幕顯示方向"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"允許應用程式讀取裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這表示應用程式可以識別您的身分,並將您的個人資料傳送給他人。"</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"修改自己的聯絡資訊"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"允許應用程式新增或變更裝置上儲存的個人資料,例如您的姓名和聯絡資訊。這項設定可讓應用程式識別您的身分,並可能將您的個人資料傳送給他人。"</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"身體感應器 (例如心律監測器)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"允許應用程式存取感應器從您的身體測得的資料,例如心跳頻率。"</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"讀取您的社交串流"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"允許應用程式存取並同步處理您和好友的最新動態。因此,當您分享資訊時請小心,因為這項權限可讓應用程式讀取您和好友在社交網路上的私人通訊,包括機密通訊。注意:並非所有社交網路皆適用於這項權限。"</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"寫入您的社交串流"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"變更 WiMAX 狀態"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"允許應用程式建立或中斷平板電腦與 WiMAX 網路的連線。"</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"允許應用程式建立或中斷手機與 WiMAX 網路的連線。"</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"為網路計分"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"允許應用程式建立網路排名,決定平板電腦偏好使用的網路。"</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"允許應用程式建立網路排名,決定手機偏好使用的網路。"</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"與藍牙裝置配對"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"允許應用程式查看平板電腦的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"允許應用程式查看手機的藍牙設定,以及建立和接受與其他配對裝置的連線。"</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"允許應用程式擷取、檢查及清除通知 (包括由其他應用程式發佈的通知)。"</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"繫結至通知接聽器服務"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"允許應用程式繫結至通知接聽器服務的頂層介面 (一般應用程式不需使用)。"</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"繫結至條件提供者服務"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"允許應用程式繫結至條件提供者服務的頂層介面 (一般應用程式並不需要)。"</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"叫用行動通訊業者提供的設定應用程式"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"允許應用程式叫用行動通訊業者提供的設定應用程式 (一般應用程式並不需要)。"</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"監聽網路狀況觀察資訊"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"桌布"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"變更桌布"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"通知接聽器"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"條件提供者"</string>
     <string name="vpn_title" msgid="19615213552042827">"VPN 已啟用"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"<xliff:g id="APP">%s</xliff:g> 已啟用 VPN"</string>
     <string name="vpn_text" msgid="3011306607126450322">"輕觸即可管理網路。"</string>
diff --git a/core/res/res/values-zu/strings.xml b/core/res/res/values-zu/strings.xml
index aacd3c1..9c8542e 100644
--- a/core/res/res/values-zu/strings.xml
+++ b/core/res/res/values-zu/strings.xml
@@ -27,6 +27,28 @@
     <string name="terabyteShort" msgid="231613018159186962">"TB"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"PB"</string>
     <string name="fileSizeSuffix" msgid="9164292791500531949">"<xliff:g id="NUMBER">%1$s</xliff:g><xliff:g id="UNIT">%2$s</xliff:g>"</string>
+    <!-- no translation found for durationDays (6652371460511178259) -->
+    <skip />
+    <!-- no translation found for durationDayHours (2713107458736744435) -->
+    <skip />
+    <!-- no translation found for durationDayHour (7293789639090958917) -->
+    <skip />
+    <!-- no translation found for durationHours (4266858287167358988) -->
+    <skip />
+    <!-- no translation found for durationHourMinutes (9029176248692041549) -->
+    <skip />
+    <!-- no translation found for durationHourMinute (2741677355177402539) -->
+    <skip />
+    <!-- no translation found for durationMinutes (3134226679883579347) -->
+    <skip />
+    <!-- no translation found for durationMinuteSeconds (1424656185379003751) -->
+    <skip />
+    <!-- no translation found for durationMinuteSecond (3989228718067466680) -->
+    <skip />
+    <!-- no translation found for durationSeconds (8050088505238241405) -->
+    <skip />
+    <!-- no translation found for durationSecond (985669622276420331) -->
+    <skip />
     <string name="untitled" msgid="4638956954852782576">"&lt;Akunasihloko&gt;"</string>
     <string name="ellipsis" msgid="7899829516048813237">"..."</string>
     <string name="ellipsis_two_dots" msgid="1228078994866030736">"‥"</string>
@@ -135,6 +157,7 @@
     <string name="contentServiceSyncNotificationTitle" msgid="397743349191901458">"Vumelanisa"</string>
     <string name="contentServiceTooManyDeletesNotificationDesc" msgid="8100981435080696431">"Kunokususa <xliff:g id="CONTENT_TYPE">%s</xliff:g> okuningi kakhulu."</string>
     <string name="low_memory" product="tablet" msgid="6494019234102154896">"Isilondolozi sethebhulethi sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
+    <string name="low_memory" product="watch" msgid="4415914910770005166">"Isitoreji sokubuka sigcwele. Susa amanye amafayela ukukhulula isikhala."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"Isilondolozi sefoni sigcwele! Susa amanye amafayela ukukhulula isikhala."</string>
     <string name="ssl_ca_cert_warning" msgid="5848402127455021714">"Inethiwekhi ingase inganyelwe"</string>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Ngenkampani yangaphandle engaziwa"</string>
@@ -152,6 +175,7 @@
     <string name="silent_mode_ring" msgid="8592241816194074353">"Iringa iyasebenza"</string>
     <string name="shutdown_progress" msgid="2281079257329981203">"Ivala shaqa..."</string>
     <string name="shutdown_confirm" product="tablet" msgid="3385745179555731470">"Ithebhulethi yakho izocima."</string>
+    <string name="shutdown_confirm" product="watch" msgid="3490275567476369184">"Ukubuka kwakho kuzocima."</string>
     <string name="shutdown_confirm" product="default" msgid="649792175242821353">"Ifoni yakho izocima."</string>
     <string name="shutdown_confirm_question" msgid="2906544768881136183">"Ingabe ufuna ukucisha?"</string>
     <string name="reboot_safemode_title" msgid="7054509914500140361">"Qala kabusha emodini ephephile"</string>
@@ -171,6 +195,7 @@
     <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Imodi yendiza"</string>
     <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Imodi yendiza IVULIWE"</string>
     <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Imodi yendiza IVALIWE"</string>
+    <string name="global_action_settings" msgid="1756531602592545966">"Izilungiselelo"</string>
     <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"999+"</string>
     <string name="safeMode" msgid="2788228061547930246">"Imodi ephephile"</string>
     <string name="android_system_label" msgid="6577375335728551336">"Uhlelo lwe-Android"</string>
@@ -315,6 +340,10 @@
     <string name="permdesc_retrieve_window_content" msgid="3193269069469700265">"Ivumela uhlelo lokusebenza ukuthi ithole okuqukethe kwi-Window. Izuhlelo lokusebenza ezinobungozi zingathola kabush iwindi eliphelele bese ibheka konke okuqukethwe ngaphandle kwaaaphasiwedi."</string>
     <string name="permlab_temporary_enable_accessibility" msgid="2312612135127310254">"nika amandla okwesikhashana ukufinyelela"</string>
     <string name="permdesc_temporary_enable_accessibility" msgid="8079456293182975464">"Ivumela uhlelo lokusebenza ukunika amandla ukufinyelela kwesikhashana kuvidayisi. Izinhlelo zokusebenza ezingalungile zinganika amandla ukufinyelela ngaphandle kwemvume yomsebenzisi."</string>
+    <string name="permlab_retrieveWindowToken" msgid="7154762602367758602">"buyisa ithokheni yewindi"</string>
+    <string name="permdesc_retrieveWindowToken" msgid="668173747687795074">"Ivumela uhlelo lokusebenza ukuletha ithokheni yewindi. Izinhlelo zokusebenza ezinonya zingenza izenzo ezingagunyaziwe ngewindi lohlelo lokusebenza lizenze isistimu."</string>
+    <string name="permlab_frameStats" msgid="7056374987314361639">"buyisa izibalo zefreyimu"</string>
+    <string name="permdesc_frameStats" msgid="4758001089491284919">"Ivumela uhlelo lokusebenza ukuthi luqoqe izibalo zefreyimu. Izinhlelo zokusebenza ezinonya zingabona izibalo zefreyimu zamawindi kusuka kwezinye izinhlelo zokusebenza."</string>
     <string name="permlab_filter_events" msgid="8675535648807427389">"hlunga imicimbi"</string>
     <string name="permdesc_filter_events" msgid="8006236315888347680">"Ivumela uhlelo lokusebenza ukubhalisa isihlungi sokufaka ukusakaza kwazo zonke izehlakalo zomsebenzisi ngaphambi kokuthunyelwa. Izinhlelo zokusebenza zingalawula i-UI yohlelo ngaphandle kokungena komsebenzisi."</string>
     <string name="permlab_shutdown" msgid="7185747824038909016">"ukuvala shaqa kwengxenye"</string>
@@ -331,6 +360,8 @@
     <string name="permdesc_broadcastSmsReceived" msgid="4152037720034365492">"Ivumela uhlelo lokusebenza ukuthi isakaze isaziso sokuthi umyalezo we-SMS utholakele. Izuhlelo lokusebenza ezinobungozi zingasebenzisa lokhu ukufoja imiyalezo ye-SMS engenayo."</string>
     <string name="permlab_broadcastWapPush" msgid="3145347413028582371">"thumela umsakazo otholwe nge-WAP-PUSH"</string>
     <string name="permdesc_broadcastWapPush" msgid="4783402525039442729">"Ivumela uhlelo lokusebenza ukuthi isakaze isaziso sokuthi umyalezo we-WAP PUSH utholakele. Izuhlelo lokusebenza ezinobungozi zingasebenzisa lokhu ukufoja ukutholakala kwemiyalezo ye-S noma zisuse okuqukethwe kwanoma iliphi ikhasi lewebhu eliqukethe okunobungozi."</string>
+    <string name="permlab_broadcastScoreNetworks" msgid="6432008366605475024">"thumela ukusakaza kwamanethiwekhi ayisikolo"</string>
+    <string name="permdesc_broadcastScoreNetworks" msgid="7652980974435077828">"Ivumela uhlelo lokusebenza ukusakaza isaziso sokuthi amanethiwekhi adinga isikolo. Awadingeki kuzinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_setProcessLimit" msgid="2451873664363662666">"khawula inani lezinqubo ezisebenzayo"</string>
     <string name="permdesc_setProcessLimit" msgid="7318061314040879542">"Ivumela uhlelo lokusebenza ukuthi ilawule isibalo esikhulu sezinto eziqhubekayo eziyosebenza. Ayidingakeli izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_setAlwaysFinish" msgid="550958507798796965">"phoqa izinhlelo zokusebenza ezingemuva ukuthi zivaleke"</string>
@@ -378,12 +409,18 @@
     <string name="permdesc_bindVpnService" msgid="2067845564581693905">"Ivumela umnini ukuthi abophele kwissekelo esingaphezulu sesevisi ye-Vpm. Ayidingakeli izinhlelo zokusebenza ezejwayelekile."</string>
     <string name="permlab_bindWallpaper" msgid="8716400279937856462">"hlanganisa kwiphephadonga"</string>
     <string name="permdesc_bindWallpaper" msgid="7108428692595491668">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lwephephadonga. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_bindVoiceInteraction" msgid="5334852580713715068">"hlanganisa kusisebenzisani sezwi"</string>
+    <string name="permdesc_bindVoiceInteraction" msgid="2345721766501778101">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo sesevisi yokusebenzisana yezwi. Akufanele kudingekele izinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindRemoteDisplay" msgid="1782923938029941960">"bophezela kusibonisi sesilawuli kude"</string>
     <string name="permdesc_bindRemoteDisplay" msgid="1261242718727295981">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo esisezingeni eliphezulu sesibonisi sesilawuli kude. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_bindRemoteViews" msgid="5697987759897367099">"bophezela kube isevisi yesinqunjana"</string>
     <string name="permdesc_bindRemoteViews" msgid="4717987810137692572">"Ivumela umbambi ukuhlanganisa uxhumano nomsebenzisi kwezinga eliphezulu lensizakalo yesinqunjwana. Akusoze kwadingeka kwezinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_bindRouteProvider" msgid="4869394607915096847">"bophezela kusevisi yomhlinzeki womzila"</string>
+    <string name="permdesc_bindRouteProvider" msgid="4703804520859960329">"Ivumela isibambi ukubophezela kunoma yimuphi umhlinzeki womzila obhalisiwe. Akufanele kudingeke izinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_bindDeviceAdmin" msgid="8704986163711455010">"xhumana nomphathi wedivaysi"</string>
     <string name="permdesc_bindDeviceAdmin" msgid="569715419543907930">"Ivumela ummeli ukuthumela okuqukethwe kumphathi wedivaysi. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_bindTvInput" msgid="5601264742478168987">"bophezela kokokufaka kwe-TV"</string>
+    <string name="permdesc_bindTvInput" msgid="2371008331852001924">"Ivumela umbambi ukuthi abophezele uxhumano nomsebenzisi kwezinga eliphezulu lokokufaka kwe-TV. Akumele kudingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_manageDeviceAdmins" msgid="4248828900045808722">"engeza noma susa umlawuli wedivayisi"</string>
     <string name="permdesc_manageDeviceAdmins" msgid="5025608167709942485">"Ivumela umnikazi ukuthi angeze noma asuse abalawuli bedivayisi esebenzayo. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_setOrientation" msgid="3365947717163866844">"shintsha ukujikeleza kwesikrini"</string>
@@ -458,6 +495,8 @@
     <string name="permdesc_readProfile" product="default" msgid="5462475151849888848">"Ivumela uhlelo lokusebenza ukuthi lifunde ulwazi lephrofayela lomuntu siqu olugcinwe kudivayisi yakho njengegama lakho kanye nolwazi lokuxhumana. Lokhu kuchaza ukuthi uhlelo lokusebenza lingakuhlonza bese lithumelela abanye ulwazi lakho lephrofayela."</string>
     <string name="permlab_writeProfile" msgid="907793628777397643">"guqula ikhadi lakho lokuxhumana"</string>
     <string name="permdesc_writeProfile" product="default" msgid="5552084294598465899">"Ivumela uhlelo lokusebenza ukushintsha noma ingeze ulwazi lomuntu siqu lwephrofayela olulondolozwe kudivayisi yakho, njengegama lakho kanye nolwazi lokuxhumana. Lokhu kuchaza ukuthi ezinye izinhlelo zokusebenza zingakuhlonza bese zithumelela abanye ulwazi lephrofayela yakho."</string>
+    <string name="permlab_bodySensors" msgid="4871091374767171066">"izinzwa zomzimba (njengeziqaphi zokulinganisela inhliziyo)"</string>
+    <string name="permdesc_bodySensors" product="default" msgid="2998865085124153531">"Ivumela uhlelo lokusebenza ukuze lufinyelele kudatha esuka kuzinzwa ozisebenzisayo ukuze lulinganise ukuthi kwenzakalani phakathi komzimba wakho, njengokulinganisela kwenhliziyo."</string>
     <string name="permlab_readSocialStream" product="default" msgid="1268920956152419170">"funda ngezindlela zakho zokuxhumana nabanye abantu"</string>
     <string name="permdesc_readSocialStream" product="default" msgid="4255706027172050872">"Ivumela uhlelo lokusebenza ukufinyelela nokuvumelanisa izibuyekezo zomphakathi ezivela kuwe nakubangani bakho. Qaphela uma waba ulwazi -- lokhu kuvumela uhlelo lokusebenza ukufunda ukuxhumana phakathi kwakho nabangani bakho kumanethiwekhi omphakathi, ngaphandle kokugcinwa kuyimfihlo. Qaphela: le mvume ingaphoqelelwa kuwo onke amanethiwekhi omphakathi."</string>
     <string name="permlab_writeSocialStream" product="default" msgid="3504179222493235645">"bhala indlela yakho yokuxhumana nabantu"</string>
@@ -628,6 +667,9 @@
     <string name="permlab_changeWimaxState" msgid="2405042267131496579">"Shintsha isimo se-WiMAX"</string>
     <string name="permdesc_changeWimaxState" product="tablet" msgid="3156456504084201805">"Ivumela uhlelo lokusebenza ukuxhuma ithebhulethi nokunqamula ithebhulethi kumanethiwekhi e-WiMAX."</string>
     <string name="permdesc_changeWimaxState" product="default" msgid="697025043004923798">"Ivumela uhlelo lokusebenza ukuxhuma ifoni nokuyinqamula kumanethiwekhi e-WiMAX."</string>
+    <string name="permlab_scoreNetworks" msgid="6445777779383587181">"amanethiwekhi ayisikolo"</string>
+    <string name="permdesc_scoreNetworks" product="tablet" msgid="1304304745850215556">"Ivumela uhlelo lokusebenza ukuthi lilinganise amanethiwekhi futhi lithuthukise ukuthi imaphi amanethiwekhi ithebhulethi okufanele iwakhethe."</string>
+    <string name="permdesc_scoreNetworks" product="default" msgid="1831501848178651379">"Ivumela uhlelo lokusebenza ukuthi lilinganise amanethiwekhi futhi lithuthukise ukuthi imaphi amanethiwekhi ifoni okufanele iwakhethe."</string>
     <string name="permlab_bluetooth" msgid="6127769336339276828">"matanisa namadivayisi e-Bluetooth"</string>
     <string name="permdesc_bluetooth" product="tablet" msgid="3480722181852438628">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth kuthebhulethi, nokwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
     <string name="permdesc_bluetooth" product="default" msgid="3207106324452312739">"Ivumela uhlelo lokusebenza ukubuka ukucushwa kwe-Bluetooth efonini, ukwenza futhi nokwamukela uxhumo namadivayisi amatanisiwe."</string>
@@ -681,6 +723,8 @@
     <string name="permdesc_accessNotifications" msgid="458457742683431387">"Ivumela uhlelo lokusebenza ukuthi lithole, lihlole, liphinde lisuse izaziso, ezifaka lezo ezithunyelwe ezinye izinhlelo zokusebenza."</string>
     <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"bophezela kwisevisi yomlaleli wesaziso"</string>
     <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"Ivumela umbambi ukubophezela kwisixhumi esibonakalayo sezinga eliphezulu lesevisi yomlaleli wesaziso. Akusoze kwadingeka kwizinhlelo zokusebenza ezivamile."</string>
+    <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"hlanganisa kwisevisi yomhlinzeki wesimo"</string>
+    <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"Ivumela umbambi ukuhlanganisa isixhumi esibonakalayo seleveli ephezulu sesevisi yomhlinzeki wesimo. Akufanele kudingekele izinhlelo zokusebenza ezivamile."</string>
     <string name="permlab_invokeCarrierSetup" msgid="3699600833975117478">"buyisela uhlelo lokusebenza lokulungiselelwa okunikezwe yinkampani yenethiwekhi"</string>
     <string name="permdesc_invokeCarrierSetup" msgid="4159549152529111920">"Ivumela umnikazi ukuthi abuyisele uhlelo lokusebenza lokulungiselelwa. Akumele idingelwe izinhlelo zokusebenza ezijwayelekile."</string>
     <string name="permlab_accessNetworkConditions" msgid="8206077447838909516">"Lalela okubonwayo kuzimo zenethiwekhi"</string>
@@ -1351,6 +1395,7 @@
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"Iphephadonga"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"Shintsha iphephadonga"</string>
     <string name="notification_listener_binding_label" msgid="2014162835481906429">"Umlaleli wesaziso"</string>
+    <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"Umhlinzeki wesimo"</string>
     <string name="vpn_title" msgid="19615213552042827">"I-VPN isiyasebenza"</string>
     <string name="vpn_title_long" msgid="6400714798049252294">"i-VPN ivuswe ngu <xliff:g id="APP">%s</xliff:g>"</string>
     <string name="vpn_text" msgid="3011306607126450322">"Thinta ukuze wengamele inethiwekhi."</string>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index e100a4d..efc1b55 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -245,6 +245,8 @@
 
         <!-- The preferred TextAppearance for the primary text of list items. -->
         <attr name="textAppearanceListItem" format="reference" />
+        <!-- The preferred TextAppearance for the secondary text of list items. -->
+        <attr name="textAppearanceListItemSecondary" format="reference" />
         <!-- The preferred TextAppearance for the primary text of small list items. -->
         <attr name="textAppearanceListItemSmall" format="reference" />
 
@@ -460,6 +462,41 @@
              transitions between different window content. -->
         <attr name="windowContentTransitionManager" format="reference" />
 
+        <!-- Reference to a Transition XML resource defining the desired Transition
+             used to move Views into the initial Window's content Scene. Corresponds to
+             {@link android.view.Window#setEnterTransition(android.transition.Transition)}. -->
+        <attr name="windowEnterTransition" format="reference"/>
+
+        <!-- Reference to a Transition XML resource defining the desired Transition
+             used to move Views out of the Window's content Scene when launching a new Activity.
+             Corresponds to
+             {@link android.view.Window#setExitTransition(android.transition.Transition)}. -->
+        <attr name="windowExitTransition" format="reference"/>
+
+        <!-- Reference to a Transition XML resource defining the desired Transition
+             used to move shared elements transferred into the Window's initial content Scene.
+             Corresponds to {@link android.view.Window#setSharedElementEnterTransition(
+             android.transition.Transition)}. -->
+        <attr name="windowSharedElementEnterTransition" format="reference"/>
+
+        <!-- Reference to a Transition XML resource defining the desired Transition
+             used when starting a new Activity to move shared elements prior to transferring
+             to the called Activity.
+             Corresponds to {@link android.view.Window#setSharedElementExitTransition(
+             android.transition.Transition)}. -->
+        <attr name="windowSharedElementExitTransition" format="reference"/>
+
+        <!-- Flag indicating whether this Window's transition should overlap with
+             the exiting transition of the calling Activity. Corresponds to
+             {@link android.view.Window#setAllowEnterTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowEnterTransitionOverlap" format="boolean"/>
+
+        <!-- Flag indicating whether this Window's transition should overlap with
+             the exiting transition of the called Activity when the called Activity
+             finishes. Corresponds to
+             {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowExitTransitionOverlap" format="boolean"/>
+
         <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
@@ -1688,6 +1725,41 @@
              or a fraction of the screen size in that dimension. -->
         <attr name="windowFixedHeightMajor" format="dimension|fraction" />
         <attr name="windowOutsetBottom" format="dimension" />
+        <!-- Reference to a TransitionManager XML resource defining the desired Transition
+             used to move Views into the initial Window's content Scene. Corresponds to
+             {@link android.view.Window#setEnterTransition(android.transition.Transition)}. -->
+        <attr name="windowEnterTransition"/>
+
+        <!-- Reference to a TransitionManager XML resource defining the desired Transition
+             used to move Views out of the Window's content Scene when launching a new Activity.
+             Corresponds to
+             {@link android.view.Window#setExitTransition(android.transition.Transition)}. -->
+        <attr name="windowExitTransition"/>
+
+        <!-- Reference to a TransitionManager XML resource defining the desired Transition
+             used to move shared elements transferred into the Window's initial content Scene.
+             Corresponds to {@link android.view.Window#setSharedElementEnterTransition(
+             android.transition.Transition)}. -->
+        <attr name="windowSharedElementEnterTransition"/>
+
+        <!-- Reference to a TransitionManager XML resource defining the desired Transition
+             used when starting a new Activity to move shared elements prior to transferring
+             to the called Activity.
+             Corresponds to {@link android.view.Window#setSharedElementExitTransition(
+             android.transition.Transition)}. -->
+        <attr name="windowSharedElementExitTransition"/>
+
+
+        <!-- Flag indicating whether this Window's transition should overlap with
+             the exiting transition of the calling Activity. Corresponds to
+             {@link android.view.Window#setAllowEnterTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowEnterTransitionOverlap"/>
+
+        <!-- Flag indicating whether this Window's transition should overlap with
+             the exiting transition of the called Activity when the called Activity
+             finishes. Corresponds to
+             {@link android.view.Window#setAllowExitTransitionOverlap(boolean)}. -->
+        <attr name="windowAllowExitTransitionOverlap"/>
     </declare-styleable>
 
     <!-- The set of attributes that describe a AlertDialog's theme. -->
@@ -2119,6 +2191,9 @@
              (completely opaque). -->
         <attr name="alpha" format="float" />
 
+        <!-- base z depth of the view -->
+        <attr name="elevation" format="dimension" />
+
         <!-- translation in x of the view. This value is added post-layout to the left
              property of the view, which is set by its layout. -->
         <attr name="translationX" format="dimension" />
@@ -2127,7 +2202,7 @@
              property of the view, which is set by its layout. -->
         <attr name="translationY" format="dimension" />
 
-        <!-- translation in z of the view. This value is added post-layout to its position. -->
+        <!-- translation in z of the view. This value is added to its elevation. -->
         <attr name="translationZ" format="dimension" />
 
         <!-- x location of the pivot point around which the view will rotate and scale.
@@ -2285,6 +2360,10 @@
              Activity to UI element in the called Activity. Names should be unique in the
              View hierarchy. -->
         <attr name="sharedElementName" format="string" />
+
+        <!-- Specifies that this view should permit nested scrolling within a compatible
+             ancestor view. -->
+        <attr name="nestedScrollingEnabled" format="boolean" />
     </declare-styleable>
 
     <!-- Attributes that can be assigned to a tag for a particular View. -->
@@ -2381,8 +2460,9 @@
              when doing an Activity transition. Typically, the elements inside a
              ViewGroup are each transitioned from the scene individually. The default
              for a ViewGroup is false unless it has a background. See
-             {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.View, String)}
-             for more information. -->
+             {@link android.app.ActivityOptions#makeSceneTransitionAnimation(android.view.Window,
+             android.view.View, String)} for more information. Corresponds to
+             {@link android.view.ViewGroup#setTransitionGroup(boolean)}.-->
         <attr name="transitionGroup" format="boolean" />
     </declare-styleable>
 
@@ -3355,6 +3435,8 @@
         <attr name="shadowDy" format="float" />
         <!-- Radius of the shadow. -->
         <attr name="shadowRadius" format="float" />
+        <!-- Elegant text height, especially for less compacted complex script text. -->
+        <attr name="elegantTextHeight" format="boolean" />
     </declare-styleable>
     <declare-styleable name="TextClock">
         <!-- Specifies the formatting pattern used to show the time and/or date
@@ -3646,6 +3728,8 @@
         <attr name="textIsSelectable" />
         <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
         <attr name="textAllCaps" />
+        <!-- Elegant text height, especially for less compacted complex script text. -->
+        <attr name="elegantTextHeight" />
     </declare-styleable>
     <declare-styleable name="TextViewAppearance">
         <!-- Base text color, typeface, size, and style. -->
@@ -4427,6 +4511,8 @@
                  result to valid color values. Saturate(S + D) -->
             <enum name="add" value="16" />
         </attr>
+        <!-- Specifies the alpha multiplier to apply to the base drawable. -->
+        <attr name="alpha" />
     </declare-styleable>
 
     <!-- Drawable used to draw 9-patches. -->
@@ -4446,6 +4532,8 @@
         <!-- When a tint color is set, specifies its Porter-Duff blending mode. The
              default value is src_in, which treats the drawable as an alpha mask. -->
         <attr name="tintMode" />
+        <!-- Specifies the alpha multiplier to apply to the base drawable. -->
+        <attr name="alpha" />
     </declare-styleable>
 
     <!-- Drawable used to draw a single color. -->
@@ -4937,6 +5025,12 @@
     <declare-styleable name="TransitionTarget">
         <!-- The id of a target on which this transition will animate changes. -->
         <attr name="targetId" format="reference" />
+        <!-- The id of a target to exclude from this transition. -->
+        <attr name="excludeId" format="reference" />
+        <!-- The fully-qualified name of the Class to exclude from this transition. -->
+        <attr name="excludeClass" format="string" />
+        <!-- The fully-qualified name of the Class to include in this transition. -->
+        <attr name="targetClass" />
     </declare-styleable>
 
     <!-- Use <code>set</code> as the root tag of the XML resource that
@@ -6182,13 +6276,22 @@
     </declare-styleable>
 
     <!-- Use <code>recognition-service</code> as the root tag of the XML resource that
-         describes a {@link android.speech.RecognitionService}, which is reference from
+         describes a {@link android.speech.RecognitionService}, which is referenced from
          its {@link android.speech.RecognitionService#SERVICE_META_DATA} meta-data entry.
          Described here are the attributes that can be included in that tag. -->
     <declare-styleable name="RecognitionService">
         <attr name="settingsActivity" />
     </declare-styleable>
 
+    <!-- Use <code>voice-interaction-service</code> as the root tag of the XML resource that
+         describes a {@link android.service.voice.VoiceInteractionService}, which is referenced from
+         its {@link android.service.voice.VoiceInteractionService#SERVICE_META_DATA} meta-data entry.
+         Described here are the attributes that can be included in that tag. -->
+    <declare-styleable name="VoiceInteractionService">
+        <attr name="sessionService" format="string" />
+        <attr name="settingsActivity" />
+    </declare-styleable>
+
     <!-- Attributes used to style the Action Bar. -->
     <declare-styleable name="ActionBar">
         <!-- The type of navigation to use. -->
diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml
index b14453a..cce4dbd 100644
--- a/core/res/res/values/attrs_manifest.xml
+++ b/core/res/res/values/attrs_manifest.xml
@@ -746,7 +746,14 @@
              selected a new global font size. -->
         <flag name="fontScale" value="0x40000000" />
     </attr>
-    
+
+    <!-- Indicate that the activity can be launched as the embedded child of another
+         activity. Particularly in the case where the child lives in a container
+         such as a Display owned by another activity.
+
+         <p>The default value of this attribute is <code>false</code>. -->
+    <attr name="allowEmbedded" format="boolean" />
+
     <!-- Descriptive text for the associated data. -->
     <attr name="description" format="reference" />
     
@@ -1541,6 +1548,7 @@
              primary user.  Can only be used with receivers. -->
         <attr name="primaryUserOnly" format="boolean" />
         <attr name="persistable" />
+        <attr name="allowEmbedded" />
     </declare-styleable>
     
     <!-- The <code>activity-alias</code> tag declares a new
diff --git a/core/res/res/values/colors_quantum.xml b/core/res/res/values/colors_quantum.xml
index ebe4a49..f8f192f 100644
--- a/core/res/res/values/colors_quantum.xml
+++ b/core/res/res/values/colors_quantum.xml
@@ -118,11 +118,11 @@
 
     <!-- Text & foreground colors -->
 
-    <color name="primary_text_quantum_light">#de000000</color>
+    <color name="primary_text_default_quantum_light">#de000000</color>
     <color name="secondary_text_quantum_light">#8a000000</color>
     <color name="tertiary_text_quantum_light">#4d000000</color>
 
-    <color name="primary_text_quantum_dark">#deffffff</color>
+    <color name="primary_text_default_quantum_dark">#deffffff</color>
     <color name="secondary_text_quantum_dark">#8affffff</color>
     <color name="tertiary_text_quantum_dark">#4dffffff</color>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index fbe066a..f919c9f 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -807,6 +807,21 @@
         <item>com.android.location.fused</item>
     </string-array>
 
+    <!-- This string array can be overriden to enable test location providers initially. -->
+    <!-- Array of "[locationProviderName],[requiresNetwork],
+         [requiresSatellite],[requiresCell],[hasMonetaryCost],
+         [supportAltitute],[supportsSpeed],[supportsBearing],
+         [powerRequirement],[accuracy]" -->
+    <!-- powerRequirement is defined in android.location.Criteria
+         0 = NO_REQUIREMENT / 1 = POWER_LOW / 2 = POWER_MEDIUM / 3 = POWER_HIGH -->
+    <!-- accuracy is defined in anroid.location.Criteria
+         1 = ACCURACY_FINE / 2 = ACCURACY_COARSE -->
+    <string-array name="config_testLocationProviders" translatable="false">
+        <!-- Example test network location provider
+        <item>network,false,false,false,false,true,true,true,1,2</item>
+        -->
+    </string-array>
+
     <!-- Boolean indicating if current platform supports bluetooth SCO for off call
     use cases -->
     <bool name="config_bluetooth_sco_off_call">true</bool>
@@ -1340,10 +1355,10 @@
          Example: com.google.android.myapp/.resolver.MyResolverActivity  -->
     <string name="config_customResolverActivity"></string>
 
-    <!-- Name of the activity that prompts the user to reject, accept, or whitelist
+    <!-- Name of the activity or service that prompts the user to reject, accept, or whitelist
          an adb host's public key, when an unwhitelisted host connects to the local adbd.
          Can be customized for other product types -->
-    <string name="config_customAdbPublicKeyActivity"
+    <string name="config_customAdbPublicKeyConfirmationComponent"
             >com.android.systemui/com.android.systemui.usb.UsbDebuggingActivity</string>
 
     <!-- Apps that are authorized to access shared accounts, overridden by product overlays -->
@@ -1370,7 +1385,7 @@
     </string-array>
 
     <string-array name="config_notificationScorers">
-        <item>com.android.internal.notification.DemoContactNotificationScorer</item>
+        <item>com.android.internal.notification.PeopleNotificationScorer</item>
     </string-array>
 
     <!-- Flag indicating that this device does not rotate and will always remain in its default
@@ -1429,4 +1444,28 @@
          2 - The device DOES NOT have a permanent menu key; ignore autodetection. -->
     <integer name="config_overrideHasPermanentMenuKey">0</integer>
 
+    <!-- default window inset isRound property -->
+    <bool name="config_windowIsRound">false</bool>
+
+    <!-- Package name for default network scorer app; overridden by product overlays. -->
+    <string name="config_defaultNetworkScorerPackageName"></string>
+
+    <!-- Defines the default set of global actions. Actions may still be disabled or hidden based
+         on the current state of the device.
+         Each item must be one of the following strings:
+         "power" = Power off
+         "settings" = An action to launch settings
+         "airplane" = Airplane mode toggle
+         "bugreport" = Take bug report, if available
+         "silent" = silent mode
+         "users" = list of users
+         -->
+    <string-array translatable="false" name="config_globalActionsList">
+        <item>power</item>
+        <item>airplane</item>
+        <item>bugreport</item>
+        <item>silent</item>
+        <item>users</item>
+    </string-array>
+
 </resources>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 94123a2..6b2c788 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -201,7 +201,7 @@
     <dimen name="textview_error_popup_default_width">240dip</dimen>
 
     <!-- Volume panel y offset -->
-    <dimen name="volume_panel_top">80dp</dimen>
+    <dimen name="volume_panel_top">16dp</dimen>
 
     <!-- Default padding to apply to AppWidgetHostViews containing widgets targeting API level 14 and up. -->
     <dimen name="default_app_widget_padding_left">8dp</dimen>
diff --git a/core/res/res/values/dimens_quantum.xml b/core/res/res/values/dimens_quantum.xml
index 3913752..cebee12 100644
--- a/core/res/res/values/dimens_quantum.xml
+++ b/core/res/res/values/dimens_quantum.xml
@@ -17,6 +17,8 @@
 
     <!-- Default height of an action bar. -->
     <dimen name="action_bar_default_height_quantum">56dp</dimen>
+    <!-- Default padding of an action bar. -->
+    <dimen name="action_bar_default_padding_quantum">4dp</dimen>
     <!-- Vertical padding around action bar icons. -->
     <dimen name="action_bar_icon_vertical_padding_quantum">16dp</dimen>
     <!-- Text size for action bar titles -->
@@ -28,6 +30,10 @@
     <!-- Bottom margin for action bar subtitles -->
     <dimen name="action_bar_subtitle_bottom_margin_quantum">5dp</dimen>
 
+    <dimen name="action_button_min_width_quantum">48dp</dimen>
+    <dimen name="action_button_min_height_quantum">48dp</dimen>
+    <dimen name="action_overflow_min_width_quantum">36dp</dimen>
+
     <dimen name="text_size_display_4_quantum">112sp</dimen>
     <dimen name="text_size_display_3_quantum">56sp</dimen>
     <dimen name="text_size_display_2_quantum">45sp</dimen>
@@ -41,4 +47,6 @@
     <dimen name="text_size_menu_quantum">14sp</dimen>
     <dimen name="text_size_button_quantum">14sp</dimen>
 
+    <dimen name="floating_window_z">16dp</dimen>
+    <dimen name="floating_window_margin">32dp</dimen>
 </resources>
diff --git a/core/res/res/values/ids.xml b/core/res/res/values/ids.xml
index a79e1fe..889c368 100644
--- a/core/res/res/values/ids.xml
+++ b/core/res/res/values/ids.xml
@@ -84,4 +84,5 @@
   <item type="id" name="scene_layoutid_cache" />
   <item type="id" name="shared_element_name" />
   <item type="id" name="mask" />
+  <item type="id" name="shared_element" />
 </resources>
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index acdf926..5ccb05b 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2094,7 +2094,8 @@
 
   <public type="attr" name="banner" id="0x10103f2" />
   <public type="attr" name="windowSwipeToDismiss" id="0x10103f3" />
-  <public type="attr" name="isGame" />
+  <public type="attr" name="isGame" id="0x10103f4" />
+  <public type="attr" name="allowEmbedded" id="0x10103f5" />
 
 <!-- ===============================================================
      Resources added in version 21 of the platform
@@ -2148,6 +2149,23 @@
   <public type="attr" name="subtitleTextAppearance" />
   <public type="attr" name="slideEdge" />
   <public type="attr" name="actionBarTheme" />
+  <public type="attr" name="textAppearanceListItemSecondary" />
+  <public type="attr" name="colorPrimaryLight" />
+  <public type="attr" name="colorPrimary" />
+  <public type="attr" name="colorPrimaryDark" />
+  <public type="attr" name="colorAccent" />
+  <public type="attr" name="nestedScrollingEnabled" />
+  <public type="attr" name="windowEnterTransition" />
+  <public type="attr" name="windowExitTransition" />
+  <public type="attr" name="windowSharedElementEnterTransition" />
+  <public type="attr" name="windowSharedElementExitTransition" />
+  <public type="attr" name="windowAllowExitTransitionOverlap" />
+  <public type="attr" name="windowAllowEnterTransitionOverlap" />
+  <public type="attr" name="sessionService" />
+  <public type="attr" name="switchStyle" />
+  <public type="attr" name="elevation" />
+  <public type="attr" name="excludeId" />
+  <public type="attr" name="excludeClass" />
 
   <public-padding type="dimen" name="l_resource_pad" end="0x01050010" />
 
@@ -2158,6 +2176,7 @@
 
   <public type="id" name="shared_element_name" />
   <public type="id" name="mask" />
+  <public type="id" name="shared_element" />
 
   <public-padding type="style" name="l_resource_pad" end="0x01030200" />
 
@@ -2377,4 +2396,15 @@
   <public type="style" name="TextAppearance.Quantum.Button" />
 
   <public type="style" name="Widget.Holo.Light.Button.Borderless" />
+
+  <public-padding type="interpolator" name="l_resource_pad" end="0x010c0010" />
+
+  <!-- An interpolator which accelerates fast but decelerates slowly. -->
+  <public type="interpolator" name="fast_out_slow_in" />
+  <!-- An interpolator which starts with a peak non-zero velocity and decelerates slowly. -->
+  <public type="interpolator" name="linear_out_slow_in" />
+  <!-- An interpolator which accelerates fast and keeps accelerating until the end. -->
+  <public type="interpolator" name="fast_out_linear_in" />
+
+  <public type="transition" name="no_transition" id="0x010f0000"/>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4a121d1..97400b2 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -36,6 +36,45 @@
          the placeholders. -->
     <string name="fileSizeSuffix"><xliff:g id="number" example="123">%1$s</xliff:g><xliff:g id="unit" example="KB">%2$s</xliff:g></string>
 
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration in days -->
+    <string name="durationDays"><xliff:g id="days">%1$d</xliff:g> days</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one day with hours -->
+    <string name="durationDayHours"><xliff:g id="days">%1$d</xliff:g> day
+            <xliff:g id="hours">%2$d</xliff:g> hrs</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one day with one hours -->
+    <string name="durationDayHour"><xliff:g id="days">%1$d</xliff:g> day
+            <xliff:g id="hours">%2$d</xliff:g> hr</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration in hours -->
+    <string name="durationHours"><xliff:g id="hours">%1$d</xliff:g> hrs</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one hour with minutes -->
+    <string name="durationHourMinutes"><xliff:g id="hours">%1$d</xliff:g> hr
+            <xliff:g id="minutes">%2$d</xliff:g> mins</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one hour with one minute -->
+    <string name="durationHourMinute"><xliff:g id="hours">%1$d</xliff:g> hr
+            <xliff:g id="minutes">%2$d</xliff:g> min</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration in minutes -->
+    <string name="durationMinutes"><xliff:g id="minutes">%1$d</xliff:g> mins</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with seconds -->
+    <string name="durationMinuteSeconds"><xliff:g id="minutes">%1$d</xliff:g> min
+            <xliff:g id="seconds">%2$d</xliff:g> secs</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one minute with one second -->
+    <string name="durationMinuteSecond"><xliff:g id="minutes">%1$d</xliff:g> min
+            <xliff:g id="seconds">%2$d</xliff:g> sec</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration in seconds -->
+    <string name="durationSeconds"><xliff:g id="seconds">%1$d</xliff:g> secs</string>
+
+    <!-- [CHAR_LIMIT=10] Suffix added to signify duration of one second -->
+    <string name="durationSecond"><xliff:g id="seconds">%1$d</xliff:g> sec</string>
+
     <!-- Used in Contacts for a field that has no label and in Note Pad
          for a note with no name. -->
     <string name="untitled">&lt;Untitled&gt;</string>
@@ -278,6 +317,8 @@
     <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
     <string name="low_memory" product="tablet">Tablet storage is full. Delete some files to free space.</string>
     <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
+    <string name="low_memory" product="watch">Watch storage is full. Delete some files to free space.</string>
+    <!-- If MMS discovers there isn't much space left on the device, it will show a toast with this message. -->
     <string name="low_memory" product="default">Phone storage is full. Delete some files to free space.</string>
 
     <!-- SSL CA cert notification --> <skip />
@@ -324,6 +365,9 @@
     <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the phone, there will
          be a confirmation dialog.  This is the message. -->
     <string name="shutdown_confirm" product="tablet">Your tablet will shut down.</string>
+    <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the watch, there will
+         be a confirmation dialog.  This is the message. -->
+    <string name="shutdown_confirm" product="watch">Your watch will shut down.</string>
     <!-- Shutdown Confirmation Dialog.  When the user chooses to power off the phone, there will
          be a confirmation dialog.  This is the message. -->
     <string name="shutdown_confirm" product="default">Your phone will shut down.</string>
@@ -394,6 +438,9 @@
     <!-- status message in phone options dialog for when airplane mode is off -->
     <string name="global_actions_airplane_mode_off_status">Airplane mode is OFF</string>
 
+    <!-- label for item that launches settings in phone options dialog [CHAR LIMIT=15]-->
+    <string name="global_action_settings">Settings</string>
+
     <!-- Text to use when the number in a notification info is too large
          (greater than status_bar_notification_info_maxnum, defined in
          values/config.xml) and must be truncated. May need to be localized
@@ -407,6 +454,12 @@
     <!-- Label for the Android system components when they are shown to the user. -->
     <string name="android_system_label">Android System</string>
 
+    <!-- Label for the user owner in the intent forwarding app. -->
+    <string name="user_owner_label">Personal</string>
+
+    <!-- Label for a corporate profile in the intent forwarding app. -->
+    <string name="managed_profile_label">Work</string>
+
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_costMoney">Services that cost you money</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
@@ -830,6 +883,20 @@
          user consent.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_retrieveWindowToken">retrieve window token</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_retrieveWindowToken">Allows an application to retrieve
+        the window token. Malicious apps may perfrom unauthorized interaction with
+        the application window impersonating the system.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_frameStats">retrieve frame statistics</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_frameStats">Allows an application to collect
+        frame statistics. Malicious apps may observe the frame statistics
+        of windows from other apps.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_filter_events">filter events</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_filter_events">Allows an application to register an input filter
@@ -887,6 +954,14 @@
         silently replace the content of any webpage with malicious variants.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_broadcastScoreNetworks">send score networks broadcast</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_broadcastScoreNetworks">Allows the app
+        to broadcast a notification that networks need to be scored.
+        Never needed for normal apps.
+    </string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_setProcessLimit">limit number of running processes</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_setProcessLimit">Allows the app
@@ -1038,6 +1113,12 @@
         interface of a wallpaper. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindVoiceInteraction">bind to a voice interactor</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindVoiceInteraction">Allows the holder to bind to the top-level
+        interface of a voice interaction service. Should never be needed for normal apps.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindRemoteDisplay">bind to a remote display</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindRemoteDisplay">Allows the holder to bind to the top-level
@@ -1050,6 +1131,12 @@
         interface of a widget service. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindRouteProvider">bind to a route provider service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindRouteProvider">Allows the holder to bind to any registered
+        route providers. Should never be needed for normal apps.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bindDeviceAdmin">interact with a device admin</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bindDeviceAdmin">Allows the holder to send intents to
@@ -1329,6 +1416,14 @@
       as your name and contact information.  This means the app can identify you
       and may send your profile information to others.</string>
 
+    <!-- Title of the body sensors permission, listed so the user can decide whether to allow the application to access body sensor data. [CHAR LIMIT=30] -->
+    <string name="permlab_bodySensors">body sensors (like heart rate monitors)
+    </string>
+    <!-- Description of the body sensors permission, listed so the user can decide whether to allow the application to access data from body sensors. [CHAR LIMIT=NONE] -->
+    <string name="permdesc_bodySensors" product="default">Allows the app to
+      access data from sensors you use to measure what’s happening inside your
+      body, such as heart rate.</string>
+
     <!-- Title of the read social stream permission, listed so the user can decide whether to allow the application to read information from the user's social stream. [CHAR LIMIT=30] -->
     <string name="permlab_readSocialStream" product="default">read your social stream</string>
     <string name="permdesc_readSocialStream" product="default">Allows the app
@@ -1854,6 +1949,15 @@
       connect the phone to and disconnect the phone from WiMAX networks.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_scoreNetworks">score networks</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_scoreNetworks" product="tablet">Allows the app to
+      rank networks and influence which networks the tablet should prefer.</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_scoreNetworks" product="default">Allows the app to
+        rank networks and influence which networks the phone should prefer.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_bluetooth">pair with Bluetooth devices</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_bluetooth" product="tablet">Allows the app to view the
@@ -1995,6 +2099,11 @@
     <string name="permdesc_bindNotificationListenerService">Allows the holder to bind to the top-level interface of a notification listener service. Should never be needed for normal apps.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_bindConditionProviderService">bind to a condition provider service</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_bindConditionProviderService">Allows the holder to bind to the top-level interface of a condition provider service. Should never be needed for normal apps.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_invokeCarrierSetup">invoke the carrier-provided configuration app</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_invokeCarrierSetup">Allows the holder to invoke the carrier-provided configuration app. Should never be needed for normal apps.</string>
@@ -3744,6 +3853,8 @@
     <!-- Label to show for a service that is running because it is observing
          the user's notifications. -->
     <string name="notification_listener_binding_label">Notification listener</string>
+    <!-- Label to show for a service that is running because it is providing conditions. -->
+    <string name="condition_provider_service_binding_label">Condition provider</string>
 
     <!-- Do Not Translate: Alternate eri.xml -->
     <string name="alternate_eri_file">/data/eri.xml</string>
diff --git a/core/res/res/values/styles_quantum.xml b/core/res/res/values/styles_quantum.xml
index dd148c4..57f2443 100644
--- a/core/res/res/values/styles_quantum.xml
+++ b/core/res/res/values/styles_quantum.xml
@@ -33,7 +33,7 @@
     <eat-comment/>
 
     <style name="Preference.Quantum">
-        <item name="layout">@layout/preference_holo</item>
+        <item name="layout">@layout/preference_quantum</item>
     </style>
 
     <style name="PreferenceFragment.Quantum">
@@ -42,13 +42,13 @@
     </style>
 
     <style name="Preference.Quantum.Information">
-        <item name="layout">@layout/preference_information_holo</item>
+        <item name="layout">@layout/preference_information_quantum</item>
         <item name="enabled">false</item>
         <item name="shouldDisableView">false</item>
     </style>
 
     <style name="Preference.Quantum.Category">
-        <item name="layout">@layout/preference_category_holo</item>
+        <item name="layout">@layout/preference_category_quantum</item>
         <!-- The title should not dim if the category is disabled, instead only the preference children should dim. -->
         <item name="shouldDisableView">false</item>
         <item name="selectable">false</item>
@@ -97,6 +97,7 @@
         <item name="textColorLink">?textColorLink</item>
         <item name="textSize">@dimen/text_size_body_1_quantum</item>
         <item name="fontFamily">@string/font_family_body_1_quantum</item>
+        <item name="elegantTextHeight">true</item>
     </style>
 
     <style name="TextAppearance.Quantum.Display4">
@@ -479,16 +480,23 @@
     <style name="Widget.Quantum.AbsListView" parent="Widget.AbsListView"/>
 
     <style name="Widget.Quantum.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
-        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
     </style>
 
     <style name="Widget.Quantum.CompoundButton" parent="Widget.CompoundButton"/>
-    <style name="Widget.Quantum.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox"/>
-    <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton"/>
+
+    <style name="Widget.Quantum.CompoundButton.CheckBox" parent="Widget.CompoundButton.CheckBox">
+        <item name="background">?attr/selectableItemBackground</item>
+    </style>
+
+    <style name="Widget.Quantum.CompoundButton.RadioButton" parent="Widget.CompoundButton.RadioButton">
+        <item name="background">?attr/selectableItemBackground</item>
+    </style>
 
     <style name="Widget.Quantum.CompoundButton.Star" parent="Widget.CompoundButton.Star">
         <item name="button">@drawable/btn_star_quantum</item>
+        <item name="background">?attr/selectableItemBackground</item>
     </style>
 
     <style name="Widget.Quantum.CompoundButton.Switch">
@@ -500,6 +508,7 @@
         <item name="thumbTextPadding">12dip</item>
         <item name="switchMinWidth">72dip</item>
         <item name="switchPadding">16dip</item>
+        <item name="background">?attr/selectableItemBackground</item>
     </style>
 
     <style name="Widget.Quantum.EditText" parent="Widget.EditText"/>
@@ -618,6 +627,7 @@
         <item name="paddingStart">16dip</item>
         <item name="paddingEnd">16dip</item>
         <item name="mirrorForRtl">true</item>
+        <item name="background">?attr/selectableItemBackground</item>
     </style>
 
     <style name="Widget.Quantum.RatingBar" parent="Widget.RatingBar">
@@ -644,7 +654,7 @@
 
     <style name="Widget.Quantum.Spinner" parent="Widget.Spinner.DropDown">
         <item name="background">@drawable/spinner_background_quantum</item>
-        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
@@ -703,7 +713,7 @@
     <style name="Widget.Quantum.QuickContactBadgeSmall.WindowLarge" parent="Widget.QuickContactBadgeSmall.WindowLarge"/>
 
     <style name="Widget.Quantum.ListPopupWindow" parent="Widget.ListPopupWindow">
-        <item name="dropDownSelector">@drawable/list_selector_holo_dark</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
@@ -713,10 +723,9 @@
     <style name="Widget.Quantum.PopupMenu" parent="Widget.Quantum.ListPopupWindow"/>
 
     <style name="Widget.Quantum.ActionButton" parent="Widget.ActionButton">
-        <item name="minWidth">@dimen/action_button_min_width</item>
+        <item name="minWidth">@dimen/action_button_min_width_quantum</item>
+        <item name="minHeight">@dimen/action_button_min_height_quantum</item>
         <item name="gravity">center</item>
-        <item name="paddingStart">12dip</item>
-        <item name="paddingEnd">12dip</item>
         <item name="scaleType">center</item>
         <item name="maxLines">2</item>
     </style>
@@ -729,6 +738,9 @@
         <item name="src">@drawable/ic_menu_moreoverflow_quantum</item>
         <item name="background">?attr/actionBarItemBackground</item>
         <item name="contentDescription">@string/action_menu_overflow_description</item>
+        <item name="minWidth">@dimen/action_overflow_min_width_quantum</item>
+        <item name="minHeight">@dimen/action_button_min_height_quantum</item>
+        <item name="scaleType">center</item>
     </style>
 
     <style name="Widget.Quantum.ActionButton.TextButton" parent="Widget.Quantum.ButtonBar"/>
@@ -756,16 +768,19 @@
     </style>
 
     <style name="Widget.Quantum.ActionBar" parent="Widget.ActionBar">
-        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
-        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="background">@null</item>
         <item name="backgroundStacked">@null</item>
         <item name="backgroundSplit">@null</item>
+        <item name="displayOptions">useLogo|showHome|showTitle</item>
         <item name="divider">?attr/dividerVertical</item>
+        <item name="titleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Title</item>
+        <item name="subtitleTextStyle">@style/TextAppearance.Quantum.Widget.ActionBar.Subtitle</item>
         <item name="progressBarStyle">@style/Widget.Quantum.ProgressBar.Horizontal</item>
         <item name="indeterminateProgressStyle">@style/Widget.Quantum.ProgressBar</item>
         <item name="progressBarPadding">32dip</item>
         <item name="itemPadding">8dip</item>
+        <item name="homeLayout">@layout/action_bar_home_quantum</item>
+        <item name="gravity">center_vertical</item>
     </style>
 
     <style name="Widget.Quantum.ActionBar.Solid">
@@ -836,11 +851,19 @@
     <style name="Widget.Quantum.Light.AbsListView" parent="Widget.Quantum.AbsListView"/>
 
     <style name="Widget.Quantum.Light.AutoCompleteTextView" parent="Widget.AutoCompleteTextView">
-        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
     </style>
 
+    <style name="Widget.Quantum.Light.CompoundButton" parent="Widget.Quantum.CompoundButton"/>
     <style name="Widget.Quantum.Light.CompoundButton.CheckBox" parent="Widget.Quantum.CompoundButton.CheckBox"/>
+    <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
+    <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
+
+    <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
+        <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
+    </style>
+
     <style name="Widget.Quantum.Light.ListView.DropDown" parent="Widget.Quantum.ListView.DropDown"/>
     <style name="Widget.Quantum.Light.EditText" parent="Widget.Quantum.EditText"/>
     <style name="Widget.Quantum.Light.ExpandableListView" parent="Widget.Quantum.ExpandableListView"/>
@@ -910,13 +933,12 @@
         <item name="maxHeight">16dip</item>
     </style>
 
-    <style name="Widget.Quantum.Light.CompoundButton.RadioButton" parent="Widget.Quantum.CompoundButton.RadioButton"/>
     <style name="Widget.Quantum.Light.ScrollView" parent="Widget.Quantum.ScrollView"/>
     <style name="Widget.Quantum.Light.HorizontalScrollView" parent="Widget.Quantum.HorizontalScrollView"/>
 
     <style name="Widget.Quantum.Light.Spinner" parent="Widget.Quantum.Spinner">
         <item name="background">@drawable/spinner_background_quantum</item>
-        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
@@ -926,7 +948,6 @@
 
     <style name="Widget.Quantum.Light.Spinner.DropDown" parent="Widget.Quantum.Spinner.DropDown"/>
     <style name="Widget.Quantum.Light.Spinner.DropDown.ActionBar" parent="Widget.Quantum.Spinner.DropDown.ActionBar"/>
-    <style name="Widget.Quantum.Light.CompoundButton.Star" parent="Widget.Quantum.CompoundButton.Star"/>
     <style name="Widget.Quantum.Light.TabWidget" parent="Widget.Quantum.TabWidget"/>
     <style name="Widget.Quantum.Light.WebTextView" parent="Widget.Quantum.WebTextView"/>
     <style name="Widget.Quantum.Light.WebView" parent="Widget.Quantum.WebView"/>
@@ -941,7 +962,7 @@
     <style name="Widget.Quantum.Light.QuickContactBadgeSmall.WindowLarge" parent="Widget.Quantum.QuickContactBadgeSmall.WindowLarge"/>
 
     <style name="Widget.Quantum.Light.ListPopupWindow" parent="Widget.ListPopupWindow">
-        <item name="dropDownSelector">@drawable/list_selector_holo_light</item>
+        <item name="dropDownSelector">@drawable/list_selector_quantum</item>
         <item name="popupBackground">?attr/colorBackground</item>
         <item name="dropDownVerticalOffset">0dip</item>
         <item name="dropDownHorizontalOffset">0dip</item>
@@ -983,10 +1004,6 @@
         <item name="backgroundSplit">?attr/colorPrimary</item>
     </style>
 
-    <style name="Widget.Quantum.Light.CompoundButton.Switch" parent="Widget.Quantum.CompoundButton.Switch">
-        <item name="switchTextAppearance">@style/TextAppearance.Quantum.Light.Widget.Switch</item>
-    </style>
-
     <style name="Widget.Quantum.Light.FastScroll" parent="Widget.Quantum.FastScroll"/>
 
     <style name="Widget.Quantum.Light.MediaRouteButton" parent="Widget.Quantum.MediaRouteButton">
@@ -1002,16 +1019,16 @@
     <!-- Dialog styles -->
 
     <style name="AlertDialog.Quantum" parent="AlertDialog">
-        <item name="fullDark">?attr/colorBackground</item>
-        <item name="topDark">?attr/colorBackground</item>
-        <item name="centerDark">?attr/colorBackground</item>
-        <item name="bottomDark">?attr/colorBackground</item>
-        <item name="fullBright">?attr/colorBackground</item>
-        <item name="topBright">?attr/colorBackground</item>
-        <item name="centerBright">?attr/colorBackground</item>
-        <item name="bottomBright">?attr/colorBackground</item>
-        <item name="bottomMedium">?attr/colorBackground</item>
-        <item name="centerMedium">?attr/colorBackground</item>
+        <item name="fullDark">@color/transparent</item>
+        <item name="topDark">@color/transparent</item>
+        <item name="centerDark">@color/transparent</item>
+        <item name="bottomDark">@color/transparent</item>
+        <item name="fullBright">@color/transparent</item>
+        <item name="topBright">@color/transparent</item>
+        <item name="centerBright">@color/transparent</item>
+        <item name="bottomBright">@color/transparent</item>
+        <item name="bottomMedium">@color/transparent</item>
+        <item name="centerMedium">@color/transparent</item>
         <item name="layout">@layout/alert_dialog_quantum</item>
         <item name="listLayout">@layout/select_dialog_quantum</item>
         <item name="progressLayout">@layout/progress_dialog_quantum</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b011483..d4ac74a 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -233,7 +233,6 @@
   <java-symbol type="attr" name="searchDialogTheme" />
   <java-symbol type="attr" name="searchViewSearchIcon" />
   <java-symbol type="attr" name="stackViewStyle" />
-  <java-symbol type="attr" name="switchStyle" />
   <java-symbol type="attr" name="textAppearanceAutoCorrectionSuggestion" />
   <java-symbol type="attr" name="textAppearanceEasyCorrectSuggestion" />
   <java-symbol type="attr" name="textAppearanceMisspelledSuggestion" />
@@ -291,6 +290,7 @@
   <java-symbol type="bool" name="config_wifi_batched_scan_supported" />
   <java-symbol type="bool" name="config_enableMultiUserUI"/>
   <java-symbol type="bool" name="config_disableUsbPermissionDialogs"/>
+  <java-symbol type="bool" name="config_windowIsRound" />
 
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
@@ -505,6 +505,17 @@
   <java-symbol type="string" name="display_manager_overlay_display_secure_suffix" />
   <java-symbol type="string" name="display_manager_overlay_display_title" />
   <java-symbol type="string" name="double_tap_toast" />
+  <java-symbol type="string" name="durationDays" />
+  <java-symbol type="string" name="durationDayHours" />
+  <java-symbol type="string" name="durationDayHour" />
+  <java-symbol type="string" name="durationHours" />
+  <java-symbol type="string" name="durationHourMinutes" />
+  <java-symbol type="string" name="durationHourMinute" />
+  <java-symbol type="string" name="durationMinutes" />
+  <java-symbol type="string" name="durationMinuteSeconds" />
+  <java-symbol type="string" name="durationMinuteSecond" />
+  <java-symbol type="string" name="durationSeconds" />
+  <java-symbol type="string" name="durationSecond" />
   <java-symbol type="string" name="elapsed_time_short_format_h_mm_ss" />
   <java-symbol type="string" name="elapsed_time_short_format_mm_ss" />
   <java-symbol type="string" name="emailTypeCustom" />
@@ -986,6 +997,7 @@
   <java-symbol type="array" name="config_operatorConsideredNonRoaming" />
   <java-symbol type="array" name="config_sameNamedOperatorConsideredRoaming" />
   <java-symbol type="array" name="config_callBarringMMI" />
+  <java-symbol type="array" name="config_globalActionsList" />
 
   <java-symbol type="drawable" name="default_wallpaper" />
   <java-symbol type="drawable" name="indicator_input_error" />
@@ -1092,6 +1104,7 @@
   <java-symbol type="drawable" name="unlock_ring" />
   <java-symbol type="drawable" name="unlock_wave" />
   <java-symbol type="drawable" name="notification_bg" />
+  <java-symbol type="drawable" name="notification_bg_dim" />
   <java-symbol type="drawable" name="notification_bg_low" />
   <java-symbol type="drawable" name="notification_template_icon_bg" />
   <java-symbol type="drawable" name="notification_template_icon_low_bg" />
@@ -1228,6 +1241,7 @@
   <java-symbol type="xml" name="sms_short_codes" />
   <java-symbol type="xml" name="audio_assets" />
   <java-symbol type="xml" name="global_keys" />
+  <java-symbol type="xml" name="default_zen_mode_config" />
 
   <java-symbol type="raw" name="accessibility_gestures" />
   <java-symbol type="raw" name="incognito_mode_start_page" />
@@ -1254,7 +1268,6 @@
   <java-symbol type="style" name="TextAppearance.SlidingTabNormal" />
   <java-symbol type="style" name="Theme.DeviceDefault.Dialog.NoFrame" />
   <java-symbol type="style" name="Theme.IconMenu" />
-  <java-symbol type="style" name="Theme.Panel.Volume" />
 
   <java-symbol type="attr" name="mediaRouteButtonStyle" />
   <java-symbol type="attr" name="externalRouteEnabledDrawable" />
@@ -1387,6 +1400,7 @@
   <java-symbol type="string" name="global_actions_airplane_mode_on_status" />
   <java-symbol type="string" name="global_actions_toggle_airplane_mode" />
   <java-symbol type="string" name="global_action_bug_report" />
+  <java-symbol type="string" name="global_action_settings" />
   <java-symbol type="string" name="global_action_silent_mode_off_status" />
   <java-symbol type="string" name="global_action_silent_mode_on_status" />
   <java-symbol type="string" name="global_action_toggle_silent_mode" />
@@ -1440,6 +1454,7 @@
   <java-symbol type="array" name="radioAttributes" />
   <java-symbol type="array" name="config_oemUsbModeOverride" />
   <java-symbol type="array" name="config_locationProviderPackageNames" />
+  <java-symbol type="array" name="config_testLocationProviders" />
   <java-symbol type="array" name="config_defaultNotificationVibePattern" />
   <java-symbol type="array" name="config_notificationFallbackVibePattern" />
   <java-symbol type="array" name="config_onlySingleDcAllowed" />
@@ -1459,6 +1474,7 @@
   <java-symbol type="color" name="input_method_navigation_guard" />
   <java-symbol type="drawable" name="ic_notification_ime_default" />
   <java-symbol type="drawable" name="ic_menu_refresh" />
+  <java-symbol type="drawable" name="ic_settings" />
   <java-symbol type="drawable" name="stat_notify_car_mode" />
   <java-symbol type="drawable" name="stat_notify_disabled" />
   <java-symbol type="drawable" name="stat_notify_disk_full" />
@@ -1574,6 +1590,7 @@
   <java-symbol type="string" name="low_internal_storage_view_text" />
   <java-symbol type="string" name="low_internal_storage_view_title" />
   <java-symbol type="string" name="notification_listener_binding_label" />
+  <java-symbol type="string" name="condition_provider_service_binding_label" />
   <java-symbol type="string" name="report" />
   <java-symbol type="string" name="select_input_method" />
   <java-symbol type="string" name="select_keyboard_layout_notification_title" />
@@ -1623,7 +1640,8 @@
   <java-symbol type="string" name="enable_explore_by_touch_warning_message" />
   <java-symbol type="bool" name="config_powerDecoupleAutoSuspendModeFromDisplay" />
   <java-symbol type="bool" name="config_powerDecoupleInteractiveModeFromDisplay" />
-  <java-symbol type="string" name="config_customAdbPublicKeyActivity" />
+  <java-symbol type="string" name="config_customAdbPublicKeyConfirmationComponent" />
+  <java-symbol type="string" name="config_defaultNetworkScorerPackageName" />
 
   <java-symbol type="layout" name="resolver_list" />
   <java-symbol type="id" name="resolver_list" />
@@ -1642,6 +1660,8 @@
   <java-symbol type="layout" name="notification_template_quantum_inbox" />
   <java-symbol type="color" name="notification_action_legacy_color_filter" />
   <java-symbol type="drawable" name="notification_icon_legacy_bg_inset" />
+  <java-symbol type="drawable" name="notification_quantum_bg_dim" />
+  <java-symbol type="drawable" name="notification_quantum_bg" />
 
     <!-- From SystemUI -->
   <java-symbol type="anim" name="push_down_in" />
@@ -1792,6 +1812,7 @@
   <java-symbol type="attr" name="amPmSelectedBackgroundColor" />
   <java-symbol type="attr" name="numbersSelectorColor" />
   <java-symbol type="attr" name="timePickerHeaderTimeLabelTextAppearance" />
+  <java-symbol type="attr" name="nestedScrollingEnabled" />
   <java-symbol type="style" name="TextAppearance.Holo.TimePicker.TimeLabel" />
   <java-symbol type="layout" name="time_picker_holo" />
   <java-symbol type="layout" name="time_header_label" />
@@ -1835,5 +1856,8 @@
   <java-symbol type="attr" name="titleTextAppearance" />
   <java-symbol type="attr" name="subtitleTextAppearance" />
   <java-symbol type="drawable" name="ic_lock_bugreport" />
+  <java-symbol type="id" name="icon_frame" />
+  <java-symbol type="style" name="Animation.VolumePanel" />
+  <java-symbol type="transition" name="no_transition" />
 
 </resources>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 7aea814..7b3d5e3 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -126,6 +126,7 @@
         <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeight</item>
         <item name="textAppearanceListItem">?android:attr/textAppearanceLarge</item>
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceLarge</item>
+        <item name="textAppearanceListItemSecondary">?android:attr/textAppearanceSmall</item>
         <item name="listPreferredItemPaddingLeft">6dip</item>
         <item name="listPreferredItemPaddingRight">6dip</item>
         <item name="listPreferredItemPaddingStart">6dip</item>
@@ -349,6 +350,7 @@
         <item name="actionMenuTextAppearance">@android:style/TextAppearance.Holo.Widget.ActionBar.Menu</item>
         <item name="actionMenuTextColor">?android:attr/textColorPrimary</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarTheme">@null</item>
         <item name="actionBarDivider">?android:attr/dividerVertical</item>
         <item name="actionBarItemBackground">?android:attr/selectableItemBackground</item>
 
@@ -701,6 +703,7 @@
         <item name="itemTextAppearance">@android:style/TextAppearance.Large.Inverse</item>
         <item name="textAppearanceListItem">@android:style/TextAppearance.Large.Inverse</item>
         <item name="textAppearanceListItemSmall">@android:style/TextAppearance.Large.Inverse</item>
+        <item name="textAppearanceListItemSecondary">@android:style/TextAppearance.Small.Inverse</item>
     </style>
 
     <!-- Default heme for the TimePicker dialog windows, which is used by the
@@ -889,11 +892,6 @@
         <item name="android:windowCloseOnTouchOutside">false</item>
     </style>
 
-    <style name="Theme.Panel.Volume">
-        <item name="android:windowAnimationStyle">@android:style/Animation.VolumePanel</item>
-        <item name="android:windowCloseOnTouchOutside">true</item>
-    </style>
-
     <!-- Default theme with an Action Bar. -->
     <style name="Theme.WithActionBar">
         <item name="android:windowActionBar">true</item>
@@ -1006,6 +1004,7 @@
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeightSmall</item>
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
+        <item name="textAppearanceListItemSecondary">?android:attr/textAppearanceSmall</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
         <item name="listPreferredItemPaddingStart">8dip</item>
@@ -1194,6 +1193,7 @@
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@android:style/Widget.Holo.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarTheme">@null</item>
 
         <item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_dark</item>
         <item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_dark</item>
@@ -1335,6 +1335,7 @@
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?android:attr/listPreferredItemHeightSmall</item>
         <item name="textAppearanceListItemSmall">?android:attr/textAppearanceMedium</item>
+        <item name="textAppearanceListItemSecondary">?android:attr/textAppearanceSmall</item>
         <item name="listPreferredItemPaddingLeft">8dip</item>
         <item name="listPreferredItemPaddingRight">8dip</item>
         <item name="listPreferredItemPaddingStart">8dip</item>
@@ -1526,6 +1527,7 @@
         <item name="actionBarSize">@dimen/action_bar_default_height</item>
         <item name="actionModePopupWindowStyle">@android:style/Widget.Holo.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
+        <item name="actionBarTheme">@null</item>
 
         <item name="actionModeCutDrawable">@android:drawable/ic_menu_cut_holo_light</item>
         <item name="actionModeCopyDrawable">@android:drawable/ic_menu_copy_holo_light</item>
@@ -1585,6 +1587,7 @@
         <item name="android:windowContentOverlay">@android:drawable/ab_solid_shadow_holo</item>
         <item name="android:actionBarStyle">@android:style/Widget.Holo.Light.ActionBar.Solid.Inverse</item>
         <item name="actionBarWidgetTheme">@android:style/Theme.Holo</item>
+        <item name="actionBarTheme">@null</item>
 
         <item name="actionDropDownStyle">@android:style/Widget.Holo.Spinner.DropDown.ActionBar</item>
         <item name="actionButtonStyle">@android:style/Widget.Holo.ActionButton</item>
diff --git a/core/res/res/values/themes_quantum.xml b/core/res/res/values/themes_quantum.xml
index b5ac8fa..9f76eae 100644
--- a/core/res/res/values/themes_quantum.xml
+++ b/core/res/res/values/themes_quantum.xml
@@ -109,11 +109,13 @@
         <item name="listPreferredItemHeightSmall">48dip</item>
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
-        <item name="textAppearanceListItemSmall">?attr/textAppearanceMedium</item>
-        <item name="listPreferredItemPaddingLeft">8dip</item>
-        <item name="listPreferredItemPaddingRight">8dip</item>
-        <item name="listPreferredItemPaddingStart">8dip</item>
-        <item name="listPreferredItemPaddingEnd">8dip</item>
+        <item name="textAppearanceListItem">@style/TextAppearance.Quantum.Subhead</item>
+        <item name="textAppearanceListItemSmall">@style/TextAppearance.Quantum.Subhead</item>
+        <item name="textAppearanceListItemSecondary">@style/TextAppearance.Quantum.Body1</item>
+        <item name="listPreferredItemPaddingLeft">16dip</item>
+        <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -121,9 +123,9 @@
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.TextView.ListSeparator</item>
 
         <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
-        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_dark</item>
+        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum</item>
 
         <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum</item>
 
@@ -200,9 +202,9 @@
         <item name="scrollbarTrackVertical">@null</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
-        <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
-        <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+        <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+        <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -269,6 +271,7 @@
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@style/Preference.Quantum.PreferenceScreen</item>
         <item name="preferenceFragmentStyle">@style/PreferenceFragment.Quantum</item>
+        <item name="preferenceFragmentPaddingSide">0dip</item>
         <item name="preferenceCategoryStyle">@style/Preference.Quantum.Category</item>
         <item name="preferenceStyle">@style/Preference.Quantum</item>
         <item name="preferenceInformationStyle">@style/Preference.Quantum.Information</item>
@@ -278,7 +281,7 @@
         <item name="dialogPreferenceStyle">@style/Preference.Quantum.DialogPreference</item>
         <item name="editTextPreferenceStyle">@style/Preference.Quantum.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Quantum.RingtonePreference</item>
-        <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
+        <item name="preferenceLayoutChild">@layout/preference_child_quantum</item>
         <item name="detailsElementBackground">?attr/colorBackground</item>
 
         <!-- Search widget styles -->
@@ -297,10 +300,10 @@
         <item name="actionModeStyle">@style/Widget.Quantum.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@style/Widget.Quantum.ActionBar.Solid</item>
-        <item name="actionBarSize">@dimen/action_bar_default_height</item>
+        <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@null</item>
+        <item name="actionBarTheme">@style/ThemeOverlay.Quantum.ActionBarWidget</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -314,11 +317,18 @@
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Widget.Quantum.ButtonBar</item>
-        <item name="buttonBarButtonStyle">?attr/borderlessButtonStyle</item>
+        <item name="buttonBarButtonStyle">@style/Widget.Quantum.Button.Borderless.Small</item>
         <item name="segmentedButtonStyle">@style/Widget.Quantum.SegmentedButton</item>
 
         <!-- SearchView attributes -->
-        <item name="searchDropdownBackground">@drawable/search_dropdown_dark</item>
+        <item name="searchDropdownBackground">?attr/colorBackground</item>
+        <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+        <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+        <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
 
         <item name="searchDialogTheme">@style/Theme.Quantum.SearchBar</item>
 
@@ -442,11 +452,13 @@
         <item name="listPreferredItemHeightSmall">48dip</item>
         <item name="listPreferredItemHeightLarge">80dip</item>
         <item name="dropdownListPreferredItemHeight">?attr/listPreferredItemHeightSmall</item>
-        <item name="textAppearanceListItemSmall">?attr/textAppearanceMedium</item>
-        <item name="listPreferredItemPaddingLeft">8dip</item>
-        <item name="listPreferredItemPaddingRight">8dip</item>
-        <item name="listPreferredItemPaddingStart">8dip</item>
-        <item name="listPreferredItemPaddingEnd">8dip</item>
+        <item name="textAppearanceListItem">@style/TextAppearance.Quantum.Subhead</item>
+        <item name="textAppearanceListItemSmall">@style/TextAppearance.Quantum.Subhead</item>
+        <item name="textAppearanceListItemSecondary">@style/TextAppearance.Quantum.Body1</item>
+        <item name="listPreferredItemPaddingLeft">16dip</item>
+        <item name="listPreferredItemPaddingRight">16dip</item>
+        <item name="listPreferredItemPaddingStart">16dip</item>
+        <item name="listPreferredItemPaddingEnd">16dip</item>
 
         <!-- @hide -->
         <item name="searchResultListItemHeight">58dip</item>
@@ -454,9 +466,9 @@
         <item name="listSeparatorTextViewStyle">@style/Widget.Quantum.Light.TextView.ListSeparator</item>
 
         <item name="listChoiceIndicatorSingle">@drawable/btn_radio_quantum</item>
-        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum</item>
+        <item name="listChoiceIndicatorMultiple">@drawable/btn_check_quantum_anim</item>
 
-        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_holo_light</item>
+        <item name="listChoiceBackgroundIndicator">@drawable/list_selector_quantum</item>
 
         <item name="activatedBackgroundIndicator">@drawable/activated_background_quantum</item>
 
@@ -532,9 +544,9 @@
         <item name="scrollbarTrackVertical">@null</item>
 
         <!-- Text selection handle attributes -->
-        <item name="textSelectHandleLeft">@drawable/text_select_handle_left</item>
-        <item name="textSelectHandleRight">@drawable/text_select_handle_right</item>
-        <item name="textSelectHandle">@drawable/text_select_handle_middle</item>
+        <item name="textSelectHandleLeft">@drawable/text_select_handle_left_quantum</item>
+        <item name="textSelectHandleRight">@drawable/text_select_handle_right_quantum</item>
+        <item name="textSelectHandle">@drawable/text_select_handle_middle_quantum</item>
         <item name="textSelectHandleWindowStyle">@style/Widget.Quantum.TextSelectHandle</item>
         <item name="textSuggestionsWindowStyle">@style/Widget.Quantum.Light.TextSuggestionsPopupWindow</item>
         <item name="textCursorDrawable">@drawable/text_cursor_quantum</item>
@@ -601,6 +613,7 @@
         <!-- Preference styles -->
         <item name="preferenceScreenStyle">@style/Preference.Quantum.PreferenceScreen</item>
         <item name="preferenceFragmentStyle">@style/PreferenceFragment.Quantum</item>
+        <item name="preferenceFragmentPaddingSide">0dip</item>
         <item name="preferenceCategoryStyle">@style/Preference.Quantum.Category</item>
         <item name="preferenceStyle">@style/Preference.Quantum</item>
         <item name="preferenceInformationStyle">@style/Preference.Quantum.Information</item>
@@ -610,7 +623,7 @@
         <item name="dialogPreferenceStyle">@style/Preference.Quantum.DialogPreference</item>
         <item name="editTextPreferenceStyle">@style/Preference.Quantum.DialogPreference.EditTextPreference</item>
         <item name="ringtonePreferenceStyle">@style/Preference.Quantum.RingtonePreference</item>
-        <item name="preferenceLayoutChild">@layout/preference_child_holo</item>
+        <item name="preferenceLayoutChild">@layout/preference_child_quantum</item>
         <item name="detailsElementBackground">?attr/colorBackground</item>
 
         <!-- PreferenceFrameLayout attributes -->
@@ -632,10 +645,10 @@
         <item name="actionModeStyle">@style/Widget.Quantum.Light.ActionMode</item>
         <item name="actionModeCloseButtonStyle">@style/Widget.Quantum.Light.ActionButton.CloseMode</item>
         <item name="actionBarStyle">@style/Widget.Quantum.Light.ActionBar.Solid</item>
-        <item name="actionBarSize">@dimen/action_bar_default_height</item>
+        <item name="actionBarSize">@dimen/action_bar_default_height_quantum</item>
         <item name="actionModePopupWindowStyle">@style/Widget.Quantum.Light.PopupWindow.ActionMode</item>
         <item name="actionBarWidgetTheme">@null</item>
-        <item name="actionBarTheme">@null</item>
+        <item name="actionBarTheme">@style/ThemeOverlay.Quantum.Light.ActionBarWidget</item>
         <item name="actionBarItemBackground">@drawable/item_background_quantum</item>
 
         <item name="actionModeCutDrawable">@drawable/ic_menu_cut_quantum</item>
@@ -649,11 +662,18 @@
         <item name="dividerVertical">?attr/listDivider</item>
         <item name="dividerHorizontal">?attr/listDivider</item>
         <item name="buttonBarStyle">@style/Widget.Quantum.Light.ButtonBar</item>
-        <item name="buttonBarButtonStyle">?attr/borderlessButtonStyle</item>
+        <item name="buttonBarButtonStyle">@style/Widget.Quantum.Light.Button.Borderless.Small</item>
         <item name="segmentedButtonStyle">@style/Widget.Quantum.Light.SegmentedButton</item>
 
         <!-- SearchView attributes -->
-        <item name="searchDropdownBackground">@drawable/search_dropdown_light</item>
+        <item name="searchDropdownBackground">?attr/colorBackground</item>
+        <item name="searchViewTextField">@drawable/textfield_search_quantum</item>
+        <item name="searchViewTextFieldRight">@drawable/textfield_search_quantum</item>
+        <item name="searchViewCloseIcon">@android:drawable/ic_clear_quantum</item>
+        <item name="searchViewSearchIcon">@android:drawable/ic_search_api_quantum</item>
+        <item name="searchViewGoIcon">@android:drawable/ic_go_search_api_quantum</item>
+        <item name="searchViewVoiceIcon">@android:drawable/ic_voice_search_api_quantum</item>
+        <item name="searchViewEditQuery">@android:drawable/ic_commit_search_api_quantum</item>
 
         <item name="searchDialogTheme">@style/Theme.Quantum.Light.SearchBar</item>
 
@@ -702,11 +722,29 @@
         <item name="colorButtonPressedColored">?attr/colorPrimaryDark</item>
     </style>
 
+    <style name="ThemeOverlay" />
+    <style name="ThemeOverlay.Quantum" />
+    <style name="ThemeOverlay.Quantum.Light" />
+
+    <!-- Variant of the quantum theme that replaces the activated control color
+         (which by default is identical to the action bar background color) with
+         the normal control color . -->
+    <style name="ThemeOverlay.Quantum.ActionBarWidget">
+        <item name="colorControlActivated">?attr/colorControlNormal</item>
+    </style>
+
+    <!-- Variant of the quantum (light) theme that replaces the activated control
+         color (which by default is identical to the action bar background color)
+         with the normal control color . -->
+    <style name="ThemeOverlay.Quantum.Light.ActionBarWidget">
+        <item name="colorControlActivated">?attr/colorControlNormal</item>
+    </style>
+
     <!-- Variant of the quantum (light) theme that has a solid (opaque) action bar
          with an inverse color profile. The dark action bar sharply stands out against
          the light content. -->
     <style name="Theme.Quantum.Light.DarkActionBar">
-        <item name="actionBarTheme">@style/Theme.Quantum</item>
+        <!-- TODO -->
     </style>
 
     <!-- Variant of the quantum (dark) theme with no action bar. -->
@@ -860,7 +898,7 @@
     <style name="Theme.Quantum.Dialog">
         <item name="windowFrame">@null</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum</item>
-        <item name="windowBackground">?attr/colorBackground</item>
+        <item name="windowBackground">@drawable/dialog_background_quantum</item>
         <item name="windowIsFloating">true</item>
         <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@style/Animation.Quantum.Dialog</item>
@@ -926,8 +964,6 @@
          its pixels. -->
     <style name="Theme.Quantum.Dialog.NoFrame">
         <item name="windowBackground">@color/transparent</item>
-        <item name="windowFrame">@null</item>
-        <item name="windowContentOverlay">@null</item>
         <item name="windowAnimationStyle">@null</item>
         <item name="backgroundDimEnabled">false</item>
         <item name="windowIsTranslucent">true</item>
@@ -943,7 +979,6 @@
     <style name="Theme.Quantum.Dialog.Alert">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum</item>
-        <item name="windowContentOverlay">@null</item>
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
@@ -1064,7 +1099,6 @@
     <style name="Theme.Quantum.Light.Dialog.Alert">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum.Light</item>
-        <item name="windowContentOverlay">@null</item>
         <item name="windowMinWidthMajor">@dimen/dialog_min_width_major</item>
         <item name="windowMinWidthMinor">@dimen/dialog_min_width_minor</item>
     </style>
@@ -1074,7 +1108,6 @@
     <style name="Theme.Quantum.Light.Dialog.TimePicker">
         <item name="windowBackground">@color/transparent</item>
         <item name="windowTitleStyle">@style/DialogWindowTitle.Quantum.Light</item>
-        <item name="windowContentOverlay">@null</item>
     </style>
 
     <!-- Theme for a presentation window on a secondary display. -->
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/core/res/res/xml/default_zen_mode_config.xml
similarity index 62%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to core/res/res/xml/default_zen_mode_config.xml
index 5812682..1bdc1ec 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/core/res/res/xml/default_zen_mode_config.xml
@@ -1,4 +1,7 @@
-/* Copyright 2014, The Android Open Source Project
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
@@ -12,7 +15,10 @@
 ** See the License for the specific language governing permissions and
 ** limitations under the License.
 */
+-->
 
-package android.media.session;
-
-parcelable MediaSessionToken;
+<!-- Default configuration for zen mode.  See android.service.notification.ZenModeConfig. -->
+<zen version="1">
+    <allow calls="false" messages="false" />
+    <sleep startHour="22" startMin="0" endHour="7" endMin="0" />
+</zen>
diff --git a/core/tests/bluetoothtests/AndroidManifest.xml b/core/tests/bluetoothtests/AndroidManifest.xml
index 60b6dc1..cbfa84d 100644
--- a/core/tests/bluetoothtests/AndroidManifest.xml
+++ b/core/tests/bluetoothtests/AndroidManifest.xml
@@ -31,5 +31,8 @@
     <instrumentation android:name="android.bluetooth.BluetoothTestRunner"
             android:targetPackage="com.android.bluetooth.tests"
             android:label="Bluetooth Tests" />
+    <instrumentation android:name="android.bluetooth.BluetoothInstrumentation"
+            android:targetPackage="com.android.bluetooth.tests"
+            android:label="Bluetooth Test Utils" />
 
 </manifest>
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
new file mode 100644
index 0000000..0cd19f2
--- /dev/null
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothInstrumentation.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.bluetooth;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.os.Bundle;
+
+public class BluetoothInstrumentation extends Instrumentation {
+
+    private BluetoothTestUtils mUtils = null;
+    private BluetoothAdapter mAdapter = null;
+    private Bundle mArgs = null;
+    private Bundle mSuccessResult = null;
+
+    private BluetoothTestUtils getBluetoothTestUtils() {
+        if (mUtils == null) {
+            mUtils = new BluetoothTestUtils(getContext(),
+                    BluetoothInstrumentation.class.getSimpleName());
+        }
+        return mUtils;
+    }
+
+    private BluetoothAdapter getBluetoothAdapter() {
+        if (mAdapter == null) {
+            mAdapter = ((BluetoothManager)getContext().getSystemService(
+                    Context.BLUETOOTH_SERVICE)).getAdapter();
+        }
+        return mAdapter;
+    }
+
+    @Override
+    public void onCreate(Bundle arguments) {
+        super.onCreate(arguments);
+        mArgs = arguments;
+        // create the default result response, but only use it in success code path
+        mSuccessResult = new Bundle();
+        mSuccessResult.putString("result", "SUCCESS");
+        start();
+    }
+
+    @Override
+    public void onStart() {
+        String command = mArgs.getString("command");
+        if ("enable".equals(command)) {
+            enable();
+        } else if ("disable".equals(command)) {
+            disable();
+        } else if ("unpairAll".equals(command)) {
+            unpairAll();
+        } else if ("getName".equals(command)) {
+            getName();
+        } else {
+            finish(null);
+        }
+    }
+
+    public void enable() {
+        getBluetoothTestUtils().enable(getBluetoothAdapter());
+        finish(mSuccessResult);
+    }
+
+    public void disable() {
+        getBluetoothTestUtils().disable(getBluetoothAdapter());
+        finish(mSuccessResult);
+    }
+
+    public void unpairAll() {
+        getBluetoothTestUtils().unpairAll(getBluetoothAdapter());
+        finish(mSuccessResult);
+    }
+
+    public void getName() {
+        String name = getBluetoothAdapter().getName();
+        mSuccessResult.putString("name", name);
+        finish(mSuccessResult);
+    }
+
+    public void finish(Bundle result) {
+        if (result == null) {
+            result = new Bundle();
+        }
+        finish(Activity.RESULT_OK, result);
+    }
+}
diff --git a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
index 4858be8..8fbd214 100644
--- a/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
+++ b/core/tests/bluetoothtests/src/android/bluetooth/BluetoothTestUtils.java
@@ -34,6 +34,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Set;
 
 public class BluetoothTestUtils extends Assert {
 
@@ -893,6 +894,17 @@
     }
 
     /**
+     * Deletes all pairings of remote devices
+     * @param adapter the BT adapter
+     */
+    public void unpairAll(BluetoothAdapter adapter) {
+        Set<BluetoothDevice> devices = adapter.getBondedDevices();
+        for (BluetoothDevice device : devices) {
+            unpair(adapter, device);
+        }
+    }
+
+    /**
      * Connects a profile from the local device to a remote device and checks to make sure that the
      * profile is connected and that the correct actions were broadcast.
      *
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 73a53cb..6bdeaf0 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_DX_FLAGS := --core-library
 LOCAL_AAPT_FLAGS = -0 dat -0 gld
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock mockito-target
 LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common
 LOCAL_PACKAGE_NAME := FrameworksCoreTests
 
diff --git a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
index e77564f..07a6a10 100644
--- a/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
+++ b/core/tests/coretests/src/android/content/pm/PackageManagerTests.java
@@ -16,7 +16,7 @@
 
 package android.content.pm;
 
-import static libcore.io.OsConstants.*;
+import static android.system.OsConstants.*;
 
 import com.android.frameworks.coretests.R;
 import com.android.internal.content.PackageHelper;
@@ -48,6 +48,9 @@
 import android.os.storage.StorageResultCode;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.test.suitebuilder.annotation.SmallTest;
@@ -62,10 +65,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
-
 public class PackageManagerTests extends AndroidTestCase {
     private static final boolean localLOGV = true;
 
@@ -503,7 +502,7 @@
         final StructStat stat;
 
         try {
-            stat = Libcore.os.lstat(path);
+            stat = Os.lstat(path);
         } catch (ErrnoException e) {
             throw new AssertionError(reason + "\n" + "Got: " + path + " does not exist");
         }
diff --git a/core/tests/coretests/src/android/net/LinkAddressTest.java b/core/tests/coretests/src/android/net/LinkAddressTest.java
index 17423be..bccf556 100644
--- a/core/tests/coretests/src/android/net/LinkAddressTest.java
+++ b/core/tests/coretests/src/android/net/LinkAddressTest.java
@@ -32,13 +32,13 @@
 import android.test.AndroidTestCase;
 import android.test.suitebuilder.annotation.SmallTest;
 
-import static libcore.io.OsConstants.IFA_F_DEPRECATED;
-import static libcore.io.OsConstants.IFA_F_PERMANENT;
-import static libcore.io.OsConstants.IFA_F_TENTATIVE;
-import static libcore.io.OsConstants.RT_SCOPE_HOST;
-import static libcore.io.OsConstants.RT_SCOPE_LINK;
-import static libcore.io.OsConstants.RT_SCOPE_SITE;
-import static libcore.io.OsConstants.RT_SCOPE_UNIVERSE;
+import static android.system.OsConstants.IFA_F_DEPRECATED;
+import static android.system.OsConstants.IFA_F_PERMANENT;
+import static android.system.OsConstants.IFA_F_TENTATIVE;
+import static android.system.OsConstants.RT_SCOPE_HOST;
+import static android.system.OsConstants.RT_SCOPE_LINK;
+import static android.system.OsConstants.RT_SCOPE_SITE;
+import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
 
 /**
  * Tests for {@link LinkAddress}.
diff --git a/core/tests/coretests/src/android/net/LinkPropertiesTest.java b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
index a602e07..553afe0 100644
--- a/core/tests/coretests/src/android/net/LinkPropertiesTest.java
+++ b/core/tests/coretests/src/android/net/LinkPropertiesTest.java
@@ -18,14 +18,13 @@
 
 import android.net.LinkProperties;
 import android.net.RouteInfo;
+import android.system.OsConstants;
 import android.test.suitebuilder.annotation.SmallTest;
 import junit.framework.TestCase;
 
 import java.net.InetAddress;
 import java.util.ArrayList;
 
-import libcore.io.OsConstants;
-
 public class LinkPropertiesTest extends TestCase {
     private static InetAddress ADDRV4 = NetworkUtils.numericToInetAddress("75.208.6.1");
     private static InetAddress ADDRV6 = NetworkUtils.numericToInetAddress(
diff --git a/core/tests/coretests/src/android/net/NetworkKeyTest.java b/core/tests/coretests/src/android/net/NetworkKeyTest.java
new file mode 100644
index 0000000..9005188
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkKeyTest.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+public class NetworkKeyTest extends TestCase {
+    public void testValidWifiKey_utf8() {
+        new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03");
+        new WifiKey("\"\"", "AB:CD:01:EF:23:03");
+    }
+
+    public void testValidWifiKey_hex() {
+        new WifiKey("0x1234abcd", "AB:CD:01:EF:23:03");
+    }
+
+    public void testInvalidWifiKey_empty() {
+        try {
+            new WifiKey("", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_unquotedUtf8() {
+        try {
+            new WifiKey("unquotedSsid", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_invalidHex() {
+        try {
+            new WifiKey("0x\"nothex\"", "AB:CD:01:EF:23:03");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - empty SSID
+        }
+    }
+
+    public void testInvalidWifiKey_shortBssid() {
+        try {
+            new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - BSSID too short
+        }
+    }
+
+    public void testInvalidWifiKey_longBssid() {
+        try {
+            new WifiKey("\"quotedSsid\"", "AB:CD:01:EF:23:03:11");
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected - BSSID too long
+        }
+    }
+
+    public void testParceling() {
+        WifiKey wifiKey = new WifiKey("\"ssid\"", "00:00:00:00:00:00");
+        NetworkKey networkKey = new NetworkKey(wifiKey);
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeParcelable(networkKey, 0);
+            parcel.setDataPosition(0);
+            networkKey = parcel.readParcelable(getClass().getClassLoader());
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+
+        assertEquals(NetworkKey.TYPE_WIFI, networkKey.type);
+        assertEquals("\"ssid\"", networkKey.wifiKey.ssid);
+        assertEquals("00:00:00:00:00:00", networkKey.wifiKey.bssid);
+    }
+}
diff --git a/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
new file mode 100644
index 0000000..cac6b93
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkScorerAppManagerTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.Manifest.permission;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.InstrumentationTestCase;
+
+import com.google.android.collect.Lists;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Iterator;
+
+public class NetworkScorerAppManagerTest extends InstrumentationTestCase {
+    @Mock private Context mMockContext;
+    @Mock private PackageManager mMockPm;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // Configuration needed to make mockito/dexcache work.
+        System.setProperty("dexmaker.dexcache",
+                getInstrumentation().getTargetContext().getCacheDir().getPath());
+        ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
+        Thread.currentThread().setContextClassLoader(newClassLoader);
+
+        MockitoAnnotations.initMocks(this);
+        Mockito.when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+    }
+
+    public void testGetAllValidScorers() throws Exception {
+        // Package 1 - Valid scorer.
+        ResolveInfo package1 = buildResolveInfo("package1", true, true);
+
+        // Package 2 - Receiver does not have BROADCAST_SCORE_NETWORKS permission.
+        ResolveInfo package2 = buildResolveInfo("package2", false, true);
+
+        // Package 3 - App does not have SCORE_NETWORKS permission.
+        ResolveInfo package3 = buildResolveInfo("package3", true, false);
+
+        setScorers(package1, package2, package3);
+
+        Iterator<String> result =
+                NetworkScorerAppManager.getAllValidScorers(mMockContext).iterator();
+
+        assertTrue(result.hasNext());
+        assertEquals("package1", result.next());
+
+        assertFalse(result.hasNext());
+    }
+
+    private void setScorers(ResolveInfo... scorers) {
+        Mockito.when(mMockPm.queryBroadcastReceivers(
+                Mockito.argThat(new ArgumentMatcher<Intent>() {
+                    @Override
+                    public boolean matches(Object object) {
+                        Intent intent = (Intent) object;
+                        return NetworkScoreManager.ACTION_SCORE_NETWORKS.equals(intent.getAction());
+                    }
+                }), Mockito.eq(0)))
+                .thenReturn(Lists.newArrayList(scorers));
+    }
+
+    private ResolveInfo buildResolveInfo(String packageName,
+            boolean hasReceiverPermission, boolean hasScorePermission) throws Exception {
+        Mockito.when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
+                .thenReturn(hasScorePermission ?
+                        PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
+
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.packageName = packageName;
+        if (hasReceiverPermission) {
+            resolveInfo.activityInfo.permission = permission.BROADCAST_SCORE_NETWORKS;
+        }
+        return resolveInfo;
+    }
+}
diff --git a/core/tests/coretests/src/android/net/ScoredNetworkTest.java b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
new file mode 100644
index 0000000..7ab69ad
--- /dev/null
+++ b/core/tests/coretests/src/android/net/ScoredNetworkTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package android.net;
+
+import android.os.Parcel;
+
+import junit.framework.TestCase;
+
+import java.util.Arrays;
+
+public class ScoredNetworkTest extends TestCase {
+    private static final RssiCurve CURVE =
+            new RssiCurve(-110, 10, new byte[] {0, 1, 2, 3, 4, 5, 6, 7});
+
+    public void testInvalidCurve_nullBuckets() {
+        try {
+            new RssiCurve(-110, 10, null);
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testInvalidCurve_emptyBuckets() {
+        try {
+            new RssiCurve(-110, 10, new byte[] {});
+            fail("Should have thrown IllegalArgumentException");
+        } catch (IllegalArgumentException e) {
+            // expected
+        }
+    }
+
+    public void testParceling() {
+        NetworkKey key = new NetworkKey(new WifiKey("\"ssid\"", "00:00:00:00:00:00"));
+        ScoredNetwork network = new ScoredNetwork(key, CURVE);
+        Parcel parcel = null;
+        try {
+            parcel = Parcel.obtain();
+            parcel.writeParcelable(network, 0);
+            parcel.setDataPosition(0);
+            network = parcel.readParcelable(getClass().getClassLoader());
+        } finally {
+            if (parcel != null) {
+                parcel.recycle();
+            }
+        }
+        assertEquals(CURVE.start, network.rssiCurve.start);
+        assertEquals(CURVE.bucketWidth, network.rssiCurve.bucketWidth);
+        assertTrue(Arrays.equals(CURVE.rssiBuckets, network.rssiCurve.rssiBuckets));
+    }
+}
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index 6fb8946..cd45017 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -19,12 +19,14 @@
 import android.content.ContentUris;
 import android.os.Parcel;
 import android.test.suitebuilder.annotation.SmallTest;
+
+import junit.framework.TestCase;
+
 import java.io.File;
 import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
-import junit.framework.TestCase;
 
 public class UriTest extends TestCase {
 
@@ -752,4 +754,54 @@
         assertEquals("d e", Uri.parse("http://a/b?c=d%20e").getQueryParameter("c"));
         assertEquals("d e", Uri.parse("http://a/b?c=d+e").getQueryParameter("c"));
     }
+
+    public void testPathPrefixMatch() {
+        // Exact match
+        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+                Uri.parse("content://com.example/path")));
+        assertTrue(Uri.parse("content://com.example///path///").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+        assertTrue(Uri.parse("content://com.example/path").isPathPrefixMatch(
+                Uri.parse("content://com.example///path///")));
+
+        // Child match
+        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+        assertTrue(Uri.parse("content://com.example/path/to/child").isPathPrefixMatch(
+                Uri.parse("content://com.example/path")));
+
+        // Extra parameters
+        assertTrue(Uri.parse("content://com.example/path#fragment").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+        assertTrue(Uri.parse("content://com.example/path?q=v").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+        assertTrue(Uri.parse("content://com.example/path/?q=v").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/")));
+
+        // Different path
+        assertFalse(Uri.parse("content://com.example/path").isPathPrefixMatch(
+                Uri.parse("content://com.example/path/deeper/")));
+        assertFalse(Uri.parse("content://com.example/path2").isPathPrefixMatch(
+                Uri.parse("content://com.example/path")));
+
+        // Top-level match
+        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+                Uri.parse("content://com.example/")));
+        assertTrue(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+                Uri.parse("content://com.example")));
+
+        // Different prefixes
+        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+                Uri.parse("file://com.example/path/")));
+        assertFalse(Uri.parse("content://com.example/path/").isPathPrefixMatch(
+                Uri.parse("content://org.example/path/")));
+
+        // Escaping
+        assertTrue(Uri.parse("content://com.example/path path/").isPathPrefixMatch(
+                Uri.parse("content://com.example/path%20path/")));
+        assertFalse(Uri.parse("content://com.example/path/path").isPathPrefixMatch(
+                Uri.parse("content://com.example/path%2Fpath")));
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
index 0e3c13a..3f9e62e 100644
--- a/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/util/FileRotatorTest.java
@@ -46,7 +46,6 @@
 import junit.framework.Assert;
 
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 /**
  * Tests for {@link FileRotator}.
diff --git a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
index efd06bf..18411b0 100644
--- a/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
+++ b/core/tests/coretests/src/com/android/internal/widget/SizeAdaptiveLayoutTest.java
@@ -438,17 +438,6 @@
         assertEquals("ModestyPanel color should match the SizeAdaptiveLayout",
                      panelColor.getColor(), Color.RED);
     }
-
-    @SmallTest
-    public void testModestyPanelHasDefault() {
-        inflate(R.layout.size_adaptive);
-        View panel = mSizeAdaptiveLayout.getModestyPanel();
-        assertNull("SizeAdaptiveLayout should have no background for this test",
-                     mSizeAdaptiveLayout.getBackground());
-        assertTrue("ModestyPanel should have a ColorDrawable background",
-                   panel.getBackground() instanceof ColorDrawable);
-    }
-
     @SmallTest
     public void testOpenSmallEvenWhenLargeIsActuallySmall() {
         inflate(R.layout.size_adaptive_lies);
diff --git a/core/tests/inputmethodtests/run_core_inputmethod_test.sh b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
index b0b119b..9029ba5 100755
--- a/core/tests/inputmethodtests/run_core_inputmethod_test.sh
+++ b/core/tests/inputmethodtests/run_core_inputmethod_test.sh
@@ -21,4 +21,4 @@
   $COMMAND
 fi
 
-adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
+adb shell am instrument -w -e class android.os.InputMethodTest,android.os.InputMethodSubtypeArrayTest,android.os.InputMethodSubtypeSwitchingControllerTest com.android.frameworks.coretests.inputmethod/android.test.InstrumentationTestRunner
diff --git a/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
new file mode 100644
index 0000000..6d33529
--- /dev/null
+++ b/core/tests/inputmethodtests/src/android/os/InputMethodSubtypeSwitchingControllerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.os;
+
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.test.InstrumentationTestCase;
+import android.test.suitebuilder.annotation.SmallTest;
+import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodSubtype;
+import android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
+
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
+import com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class InputMethodSubtypeSwitchingControllerTest extends InstrumentationTestCase {
+    final private static String DUMMY_PACKAGE_NAME = "dymmy package name";
+    final private static String DUMMY_SETTING_ACTIVITY_NAME = "";
+    final private static boolean DUMMY_IS_AUX_IME = false;
+    final private static boolean DUMMY_FORCE_DEFAULT = false;
+    final private static int DUMMY_IS_DEFAULT_RES_ID = 0;
+    final private static String SYSTEM_LOCALE = "en_US";
+
+    private static InputMethodSubtype createDummySubtype(final String locale) {
+        final InputMethodSubtypeBuilder builder = new InputMethodSubtypeBuilder();
+        return builder.setSubtypeNameResId(0)
+                .setSubtypeIconResId(0)
+                .setSubtypeLocale(locale)
+                .setIsAsciiCapable(true)
+                .build();
+    }
+
+    private static void addDummyImeSubtypeListItems(List<ImeSubtypeListItem> items,
+            String imeName, String imeLabel, List<String> subtypeLocales,
+            boolean supportsSwitchingToNextInputMethod) {
+        final ResolveInfo ri = new ResolveInfo();
+        final ServiceInfo si = new ServiceInfo();
+        final ApplicationInfo ai = new ApplicationInfo();
+        ai.packageName = DUMMY_PACKAGE_NAME;
+        ai.enabled = true;
+        si.applicationInfo = ai;
+        si.enabled = true;
+        si.packageName = DUMMY_PACKAGE_NAME;
+        si.name = imeName;
+        si.exported = true;
+        si.nonLocalizedLabel = imeLabel;
+        ri.serviceInfo = si;
+        final List<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
+        for (String subtypeLocale : subtypeLocales) {
+            subtypes.add(createDummySubtype(subtypeLocale));
+        }
+        final InputMethodInfo imi = new InputMethodInfo(ri, DUMMY_IS_AUX_IME,
+                DUMMY_SETTING_ACTIVITY_NAME, subtypes, DUMMY_IS_DEFAULT_RES_ID,
+                DUMMY_FORCE_DEFAULT, supportsSwitchingToNextInputMethod);
+        for (int i = 0; i < subtypes.size(); ++i) {
+            final String subtypeLocale = subtypeLocales.get(i);
+            final InputMethodSubtype subtype = subtypes.get(i);
+            items.add(new ImeSubtypeListItem(imeName, subtypeLocale, imi, i, subtypeLocale,
+                    SYSTEM_LOCALE));
+        }
+    }
+
+    private static List<ImeSubtypeListItem> createTestData() {
+        final List<ImeSubtypeListItem> items = new ArrayList<ImeSubtypeListItem>();
+        addDummyImeSubtypeListItems(items, "switchAwareLatinIme", "switchAwareLatinIme",
+                Arrays.asList("en_US", "es_US", "fr"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareLatinIme", "nonSwitchAwareLatinIme",
+                Arrays.asList("en_UK", "hi"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "switchAwareJapaneseIme", "switchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                true /* supportsSwitchingToNextInputMethod*/);
+        addDummyImeSubtypeListItems(items, "nonSwitchAwareJapaneseIme", "nonSwitchAwareJapaneseIme",
+                Arrays.asList("ja_JP"),
+                false /* supportsSwitchingToNextInputMethod*/);
+        return items;
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithNotOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = false;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "nonSwitchAwareLatinIme/en_UK
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(5), nextIme);
+        // "switchAwareJapaneseIme/ja_JP" -> "nonSwitchAwareJapaneseIme/ja_JP"
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(6), nextIme);
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+    }
+
+    @SmallTest
+    public void testGetNextInputMethodImplWithOnlyCurrentIme() throws Exception {
+        final List<ImeSubtypeListItem> imList = createTestData();
+
+        final boolean ONLY_CURRENT_IME = true;
+        ImeSubtypeListItem currentIme;
+        ImeSubtypeListItem nextIme;
+
+        // "switchAwareLatinIme/en_US" -> "switchAwareLatinIme/es_US"
+        currentIme = imList.get(0);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(1), nextIme);
+        // "switchAwareLatinIme/es_US" -> "switchAwareLatinIme/fr"
+        currentIme = imList.get(1);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(2), nextIme);
+        // "switchAwareLatinIme/fr" -> "switchAwareLatinIme/en_US"
+        currentIme = imList.get(2);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(0), nextIme);
+
+        // "nonSwitchAwareLatinIme/en_UK" -> "nonSwitchAwareLatinIme/hi"
+        currentIme = imList.get(3);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(4), nextIme);
+        // "nonSwitchAwareLatinIme/hi" -> "switchAwareLatinIme/en_UK"
+        currentIme = imList.get(4);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertEquals(imList.get(3), nextIme);
+
+        // "switchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(5);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+
+        // "nonSwitchAwareJapaneseIme/ja_JP" -> null
+        currentIme = imList.get(6);
+        nextIme = InputMethodSubtypeSwitchingController.getNextInputMethodImpl(
+                imList, ONLY_CURRENT_IME, currentIme.mImi, createDummySubtype(
+                        currentIme.mSubtypeName.toString()));
+        assertNull(nextIme);
+    }
+ }
diff --git a/data/keyboards/AVRCP.kl b/data/keyboards/AVRCP.kl
index 736b43c..ccd0209 100644
--- a/data/keyboards/AVRCP.kl
+++ b/data/keyboards/AVRCP.kl
@@ -14,10 +14,10 @@
 
 # Key layout used for Bluetooth AVRCP support.
 
-key 200   MEDIA_PLAY          WAKE
-key 201   MEDIA_PAUSE         WAKE
-key 166   MEDIA_STOP          WAKE
-key 163   MEDIA_NEXT          WAKE
-key 165   MEDIA_PREVIOUS      WAKE
-key 168   MEDIA_REWIND        WAKE
-key 208   MEDIA_FAST_FORWARD  WAKE
+key 200   MEDIA_PLAY
+key 201   MEDIA_PAUSE
+key 166   MEDIA_STOP
+key 163   MEDIA_NEXT
+key 165   MEDIA_PREVIOUS
+key 168   MEDIA_REWIND
+key 208   MEDIA_FAST_FORWARD
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
index 0cdcb1c..56423c9 100644
--- a/data/keyboards/Generic.kl
+++ b/data/keyboards/Generic.kl
@@ -135,7 +135,7 @@
 key 113   VOLUME_MUTE
 key 114   VOLUME_DOWN
 key 115   VOLUME_UP
-key 116   POWER             WAKE
+key 116   POWER
 key 117   NUMPAD_EQUALS
 # key 118 "KEY_KPPLUSMINUS"
 key 119   BREAK
@@ -146,7 +146,7 @@
 key 124   YEN
 key 125   META_LEFT
 key 126   META_RIGHT
-key 127   MENU              WAKE_DROPPED
+key 127   MENU
 key 128   MEDIA_STOP
 # key 129 "KEY_AGAIN"
 # key 130 "KEY_PROPS"
@@ -158,11 +158,11 @@
 # key 136 "KEY_FIND"
 # key 137 "KEY_CUT"
 # key 138 "KEY_HELP"
-key 139   MENU              WAKE_DROPPED
+key 139   MENU
 key 140   CALCULATOR
 # key 141 "KEY_SETUP"
-key 142   SLEEP             WAKE
-key 143   WAKEUP            WAKE
+key 142   SLEEP
+key 143   WAKEUP
 # key 144 "KEY_FILE"
 # key 145 "KEY_SENDFILE"
 # key 146 "KEY_DELETEFILE"
@@ -171,13 +171,13 @@
 # key 149 "KEY_PROG2"
 key 150   EXPLORER
 # key 151 "KEY_MSDOS"
-key 152   POWER             WAKE
+key 152   POWER
 # key 153 "KEY_DIRECTION"
 # key 154 "KEY_CYCLEWINDOWS"
 key 155   ENVELOPE
 key 156   BOOKMARK
 # key 157 "KEY_COMPUTER"
-key 158   BACK              WAKE_DROPPED
+key 158   BACK
 key 159   FORWARD
 key 160   MEDIA_CLOSE
 key 161   MEDIA_EJECT
diff --git a/data/keyboards/Vendor_0a5c_Product_8502.kl b/data/keyboards/Vendor_0a5c_Product_8502.kl
index f6dbfd4..2f07328 100644
--- a/data/keyboards/Vendor_0a5c_Product_8502.kl
+++ b/data/keyboards/Vendor_0a5c_Product_8502.kl
@@ -24,7 +24,7 @@
 key 317 BUTTON_THUMBL
 key 318 BUTTON_THUMBR
 
-key 158 BACK            WAKE_DROPPED
+key 158 BACK
 key 172 HOME
 
 axis 0x00 X
diff --git a/data/keyboards/Vendor_18d1_Product_2c40.kl b/data/keyboards/Vendor_18d1_Product_2c40.kl
index 903f13b6..6efde4f 100644
--- a/data/keyboards/Vendor_18d1_Product_2c40.kl
+++ b/data/keyboards/Vendor_18d1_Product_2c40.kl
@@ -24,7 +24,7 @@
 key 317 BUTTON_THUMBL
 key 318 BUTTON_THUMBR
 
-key 158 BACK            WAKE_DROPPED
+key 158 BACK
 key 172 HOME
 
 axis 0x00 X
diff --git a/data/keyboards/Vendor_1949_Product_0401.kl b/data/keyboards/Vendor_1949_Product_0401.kl
new file mode 100644
index 0000000..ab24bcd
--- /dev/null
+++ b/data/keyboards/Vendor_1949_Product_0401.kl
@@ -0,0 +1,27 @@
+# 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.
+
+# Amazon Fire TV remote
+
+key 103 DPAD_UP
+key 108 DPAD_DOWN
+key 105 DPAD_LEFT
+key 106 DPAD_RIGHT
+key 96  DPAD_CENTER
+key 158 BACK
+key 172 HOME
+key 168 MEDIA_REWIND
+key 208 MEDIA_FAST_FORWARD
+key 164 MEDIA_PLAY_PAUSE
+key 217 ASSIST
diff --git a/data/keyboards/qwerty.kl b/data/keyboards/qwerty.kl
index f1caacd..58bf654 100644
--- a/data/keyboards/qwerty.kl
+++ b/data/keyboards/qwerty.kl
@@ -30,29 +30,29 @@
 key 9     8
 key 10    9
 key 11    0
-key 158   BACK              WAKE_DROPPED
-key 230   SOFT_RIGHT        WAKE
-key 60    SOFT_RIGHT        WAKE
-key 107   ENDCALL           WAKE_DROPPED
-key 62    ENDCALL           WAKE_DROPPED
-key 229   MENU              WAKE_DROPPED
-key 139   MENU              WAKE_DROPPED
-key 59    MENU              WAKE_DROPPED
-key 127   SEARCH            WAKE_DROPPED
-key 217   SEARCH            WAKE_DROPPED
+key 158   BACK
+key 230   SOFT_RIGHT
+key 60    SOFT_LEFT
+key 107   ENDCALL
+key 62    ENDCALL
+key 229   MENU
+key 139   MENU
+key 59    MENU
+key 127   SEARCH
+key 217   SEARCH
 key 228   POUND
 key 227   STAR
-key 231   CALL              WAKE_DROPPED
-key 61    CALL              WAKE_DROPPED
-key 232   DPAD_CENTER       WAKE_DROPPED
-key 108   DPAD_DOWN         WAKE_DROPPED
-key 103   DPAD_UP           WAKE_DROPPED
-key 102   HOME              WAKE
-key 105   DPAD_LEFT         WAKE_DROPPED
-key 106   DPAD_RIGHT        WAKE_DROPPED
-key 115   VOLUME_UP         WAKE
-key 114   VOLUME_DOWN       WAKE
-key 116   POWER             WAKE
+key 231   CALL
+key 61    CALL
+key 232   DPAD_CENTER
+key 108   DPAD_DOWN
+key 103   DPAD_UP
+key 102   HOME
+key 105   DPAD_LEFT
+key 106   DPAD_RIGHT
+key 115   VOLUME_UP
+key 114   VOLUME_DOWN
+key 116   POWER
 key 212   CAMERA
 
 key 16    Q
@@ -108,5 +108,5 @@
 key 215   AT
 
 # On an AT keyboard: ESC, F10
-key 1     BACK              WAKE_DROPPED
-key 68    MENU              WAKE_DROPPED
+key 1     BACK
+key 68    MENU
diff --git a/docs/html/design/media/dialogs_examples.png b/docs/html/design/media/dialogs_examples.png
index c136476..6ffcee2 100644
--- a/docs/html/design/media/dialogs_examples.png
+++ b/docs/html/design/media/dialogs_examples.png
Binary files differ
diff --git a/docs/html/design/media/navigation_drawer_titles_icons.png b/docs/html/design/media/navigation_drawer_titles_icons.png
index 7cf1e0c..902a72d 100644
--- a/docs/html/design/media/navigation_drawer_titles_icons.png
+++ b/docs/html/design/media/navigation_drawer_titles_icons.png
Binary files differ
diff --git a/docs/html/design/media/selection_adjusting_actions.png b/docs/html/design/media/selection_adjusting_actions.png
index 0799b6b..32a7fec 100644
--- a/docs/html/design/media/selection_adjusting_actions.png
+++ b/docs/html/design/media/selection_adjusting_actions.png
Binary files differ
diff --git a/docs/html/design/media/touch_feedback_communication.png b/docs/html/design/media/touch_feedback_communication.png
index f8162d0..1d4a9dc 100644
--- a/docs/html/design/media/touch_feedback_communication.png
+++ b/docs/html/design/media/touch_feedback_communication.png
Binary files differ
diff --git a/docs/html/design/media/ui_overview_notifications.png b/docs/html/design/media/ui_overview_notifications.png
index 6043412..7975657 100644
--- a/docs/html/design/media/ui_overview_notifications.png
+++ b/docs/html/design/media/ui_overview_notifications.png
Binary files differ
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index d2177ca..03addfd 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -8,7 +8,7 @@
 <h2>In this document</h2>
 
 <ol class="toc">
-  <li><a href="#usage">How to Use CCS</a>
+  <li><a href="#connecting">Establishing a Connection</a>
     <ol class="toc">
       <li><a href="#auth">Authentication</a></li>
       </ol>
@@ -46,19 +46,20 @@
 <p class="note"><strong>Note:</strong> To try out this feature, sign up using
 <a href="https://services.google.com/fb/forms/gcm/">this form</a>.</p>
 
-<p>The GCM Cloud Connection Server (CCS) is a connection server based on XMPP.
-CCS allows 3rd-party app servers (which you're
-responsible for implementing) to communicate
-with Android devices by  establishing a persistent TCP connection with Google
-servers using the XMPP protocol. This communication is asynchronous and bidirectional.</p>
+<p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
+persistent, asynchronous, bidirectional connection to Google servers. The
+connection can be used to send and receive messages between your server and
+your users' GCM-connected devices.</p>
+
 <p>You can continue to use the HTTP request mechanism to send messages to GCM
 servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
+
 <ul>
   <li>The asynchronous nature of XMPP allows you to send more messages with fewer
 resources.</li>
-  <li>Communication is bidirectional&mdash;not only can the server send messages
-to the device, but the device can send messages back to the server.</li>
-<li>You can send messages back using the same connection used for receiving,
+  <li>Communication is bidirectional&mdash;not only can your server send messages
+to the device, but the device can send messages back to your server.</li>
+  <li>The device can send messages back using the same connection used for receiving,
 thereby improving battery life.</li>
 </ul>
 
@@ -73,22 +74,34 @@
 <a href="server.html#params">Implementing GCM Server</a> for a list of all the message
 parameters and which connection server(s) supports them.</p>
 
+<h2 id="connecting">Establishing a Connection</h2>
 
-<h2 id="usage">How to Use CCS</h2>
+<p>CCS just uses XMPP as an authenticated transport layer, so you can use most
+XMPP libraries to manage the connection. For an example, see <a href="#smack">
+Java sample using the Smack library</a>.</p>
 
-<p>GCM Cloud Connection Server (CCS) is an XMPP endpoint, running on
-{@code http://gcm.googleapis.com} port 5235.</p>
+<p>The CCS XMPP endpoint runs at {@code gcm.googleapis.com:5235}. When testing
+functionality (with non-production users), you should instead connect to
+{@code gcm-staging.googleapis.com:5236} (note the different port). Testing on
+staging (a smaller environment where the latest CCS builds run) is beneficial
+both for isolating real users from test code, as well as for early detection of
+unexpected behavior changes.</p>
 
-<p>CCS requires a Transport Layer Security (TLS) connection. That means the  XMPP
-client must initiate a TLS connection.
-For example in Java, you would call {@code setSocketFactory(SSLSocketFactory)}.</p>
+<p>The connection has two important requirements:</p>
 
-<p>CCS requires a SASL PLAIN authentication mechanism using
-{@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID) and the
-API key as the password, where the sender ID and API key are the same as described
-in <a href="gs.html">Getting Started</a>.</p>
+<ul>
+  <li>You must initiate a Transport Layer Security (TLS) connection. Note that
+  CCS doesn't currently support the <a href="http://xmpp.org/rfcs/rfc3920.html"
+  class="external-link" target="_android">STARTTLS extension</a>.</li>
+  <li>CCS requires a SASL PLAIN authentication mechanism using
+  {@code &lt;your_GCM_Sender_Id&gt;&#64;gcm.googleapis.com} (GCM sender ID)
+  and the API key as the password, where the sender ID and API key are the same
+  as described in <a href="gs.html">Getting Started</a>.</li>
+</ul>
 
-<p> You can use most XMPP libraries to interact with CCS.</p>
+<p>If at any point the connection fails, you should immediately reconnect.
+There is no need to back off after a disconnect that happens after
+authentication.</p>
 
 <h3 id="auth">Authentication</h3>
 
@@ -100,11 +113,11 @@
 </pre>
 <h4>Server</h4>
 <pre>&lt;str:features xmlns:str=&quot;http://etherx.jabber.org/streams&quot;&gt;
- &lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
-   &lt;mechanism&gt;X-OAUTH2&lt;/mechanism&gt;
-   &lt;mechanism&gt;X-GOOGLE-TOKEN&lt;/mechanism&gt;
-   &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
- &lt;/mechanisms&gt;
+ &lt;mechanisms xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;&gt;
+   &lt;mechanism&gt;X-OAUTH2&lt;/mechanism&gt;
+   &lt;mechanism&gt;X-GOOGLE-TOKEN&lt;/mechanism&gt;
+   &lt;mechanism&gt;PLAIN&lt;/mechanism&gt;
+ &lt;/mechanisms&gt;
 &lt;/str:features&gt;
 </pre>
 
@@ -118,16 +131,18 @@
 <pre>&lt;success xmlns=&quot;urn:ietf:params:xml:ns:xmpp-sasl&quot;/&gt;</pre>
 
 <h2 id="format">Message Format</h2>
-<p>CCS uses normal XMPP <code>&lt;message&gt;</code> stanzas. The body of the message must be:
-</p>
+<p>Once the XMPP connection is established, CCS and your server use normal XMPP
+<code>&lt;message&gt;</code> stanzas to send JSON-encoded messages back and
+forth. The body of the <code>&lt;message&gt;</code> must be:</p>
 <pre>
 &lt;gcm xmlns:google:mobile:data&gt;
     <em>JSON payload</em>
 &lt;/gcm&gt;
 </pre>
 
-<p>The JSON payload for server-to-device is similar to what the GCM http endpoint
-uses, with these exceptions:</p>
+<p>The JSON payload for regular GCM messages is similar to
+<a href="http.html#request">what the GCM http endpoint uses</a>, with these
+exceptions:</p>
 <ul>
   <li>There is no support for multiple recipients.</li>
   <li>{@code to} is used instead of {@code registration_ids}.</li>
@@ -136,14 +151,13 @@
 {@code message_id} to identify a message sent from 3rd-party app servers to CCS.
 Therefore, it's important that this {@code message_id} not only be unique, but
 always present.</li>
-
-<li>For ACK/NACK messages that are special control messages, you also need to
-include a {@code message_type} field in the JSON message. The value can be either
-'ack' or 'nack'. For example:
-
-<pre>message_type = ('ack');</pre>
-  </li>
 </ul>
+
+<p>In addition to regular GCM messages, control messages are sent, indicated by
+the {@code message_type} field in the JSON object. The value can be either
+'ack' or 'nack', or 'control' (see formats below). Any GCM message with an
+unknown {@code message_type} can be ignored by your server.</p>
+
 <p>For each device message your app server receives from CCS, it needs to send
 an ACK message.
 It never needs to send a NACK message. If you don't send an ACK for a message,
@@ -251,7 +265,9 @@
 &lt;/message&gt;</pre>
 
 
-<p>The following table lists some of the more common NACK error codes.</p>
+<p>The following table lists NACK error codes. Unless otherwise
+indicated, a NACKed message should not be retried. Unexpected NACK error codes
+should be treated the same as {@code INTERNAL_SERVER_ERROR}.</p>
 
 <p class="table-caption" id="table1">
   <strong>Table 1.</strong> NACK error codes.</p>
@@ -262,8 +278,17 @@
 <th>Description</th>
 </tr>
 <tr>
+<td>{@code BAD_ACK}</td>
+<td>The ACK message is improperly formed.</td>
+</tr>
+<tr>
 <td>{@code BAD_REGISTRATION}</td>
-<td>The device has a registration ID, but it's invalid.</td>
+<td>The device has a registration ID, but it's invalid or expired.</td>
+</tr>
+<tr>
+<td>{@code CONNECTION_DRAINING}</td>
+<td>The message couldn't be processed because the connection is draining. The
+message should be immediately retried over another connection.</td>
 </tr>
 <tr>
 <td>{@code DEVICE_UNREGISTERED}</td>
@@ -274,25 +299,20 @@
 <td>The server encountered an error while trying to process the request.</td>
 </tr>
 <tr>
+<td>{@code INVALID_JSON}</td>
+<td>The JSON message payload was not valid.</td>
+</tr>
+<tr>
+<td>{@code QUOTA_EXCEEDED}</td>
+<td>The rate of messages to a particular registration ID (in other words, to a
+sender/device pair) is too high. If you want to retry the message, try using a slower
+rate.</td>
+</tr>
+<tr>
 <td>{@code SERVICE_UNAVAILABLE}</td>
-<td>The CCS connection server is temporarily unavailable, try again later
-(using exponential backoff, etc.).</td>
-</tr>
-<tr>
-<td>{@code BAD_ACK}</td>
-<td>The ACK message is improperly formed.</td>
-</tr>
-<tr>
-<td>{@code AUTHENTICATION_FAILED}</td>
-<td>This is a 401 error indicating that there was an error authenticating the sender account.</td>
-</tr>
-<tr>
-<td>{@code INVALID_TTL}</td>
-<td>There was an error in the supplied "time to live" value.</td>
-</tr>
-<tr>
-<td>{@code JSON_TYPE_ERROR}</td>
-<td>There was an error in the supplied JSON data type.</td>
+<td>CCS is not currently able to process the message. The
+message should be retried over the same connection using exponential backoff
+with an initial delay of 1 second.</td>
 </tr>
 </table>
 
@@ -319,6 +339,28 @@
 &lt;/message&gt;
 </pre>
 
+<h4 id="control">Control messages</h4>
+
+<p>Periodically, CCS needs to close down a connection to perform load balancing. Before it
+closes the connection, CCS sends a {@code CONNECTION_DRAINING} message to indicate that the connection is being drained
+and will be closed soon. "Draining" refers to shutting off the flow of messages coming into a
+connection, but allowing whatever is already in the pipeline to continue. When you receive
+a {@code CONNECTION_DRAINING} message, you should immediately begin sending messages to another CCS
+connection, opening a new connection if necessary. You should, however, keep the original
+connection open and continue receiving messages that may come over the connection (and
+ACKing them)&mdash;CCS will handle initiating a connection close when it is ready.</p>
+
+<p>The {@code CONNECTION_DRAINING} message looks like this:</p>
+<pre>&lt;message&gt;
+  &lt;data:gcm xmlns:data=&quot;google:mobile:data&quot;&gt;
+  {
+    &quot;message_type&quot;:&quot;control&quot;
+    &quot;control_type&quot;:&quot;CONNECTION_DRAINING&quot;
+  }
+  &lt;/data:gcm&gt;
+&lt;/message&gt;</pre>
+
+<p>{@code CONNECTION_DRAINING} is currently the only {@code control_type} supported.</p>
 
 <h2 id="upstream">Upstream Messages</h2>
 
@@ -381,7 +423,7 @@
 
 <p>Every message sent to CCS receives either an ACK or a NACK response. Messages
 that haven't received one of these responses are considered pending. If the pending
-message count reaches 1000, the 3rd-party app server should stop sending new messages
+message count reaches 100, the 3rd-party app server should stop sending new messages
 and wait for CCS to acknowledge some of the existing pending messages as illustrated in
 figure 1:</p>
 
@@ -395,7 +437,7 @@
 if there are too many unacknowledged messages. Therefore, the 3rd-party app server
 should "ACK" upstream messages, received from the client application via CCS, as soon as possible
 to maintain a constant flow of incoming messages. The aforementioned pending message limit doesn't
-apply to these ACKs. Even if the pending message count reaches 1000, the 3rd-party app server
+apply to these ACKs. Even if the pending message count reaches 100, the 3rd-party app server
 should continue sending ACKs for messages received from CCS to avoid blocking delivery of new
 upstream messages.</p>
 
@@ -795,7 +837,7 @@
 PASSWORD = "API Key"
 REGISTRATION_ID = "Registration Id of the target device"
 
-unacked_messages_quota = 1000
+unacked_messages_quota = 100
 send_queue = []
 
 # Return a random alphanumerical id
diff --git a/docs/html/google/play-services/maps.jd b/docs/html/google/play-services/maps.jd
index c24cc74..c541b08 100644
--- a/docs/html/google/play-services/maps.jd
+++ b/docs/html/google/play-services/maps.jd
@@ -1,4 +1,4 @@
-page.title=Google Maps Android API
+page.title=Google Maps Android API v2
 page.tags=mapview,location
 header.hide=1
 
@@ -12,14 +12,14 @@
 </div>
 <div class="col-6">
 
-  <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API</h1>
+  <h1 itemprop="name" style="margin-bottom:0;">Google Maps Android API v2</h1>
   <p itemprop="description">Allow your users explore the world with rich maps provided by
   Google. Identify locations with <b>custom markers</b>, augment the map data
   with <b>image overlays</b>, embed <b>one or more maps</b> as fragments,
   and much more.</p>
   <p>Explore the <a
 href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html"
->Google Maps Android API reference</a> or visit <a class="external-link"
+>Google Maps Android API v2 reference</a> or visit <a class="external-link"
 href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>
 for more information about adding maps to your app.</p>
 </div>
@@ -31,7 +31,7 @@
   <div class="col-6 normal-links">
     <h3 style="clear:left">Key Developer Features</h3>
     <h4>Add maps to your app</h4>
-    <p>With version 2 of the Google Maps Android API, you can embed maps into an activity
+    <p>With Google Maps Android API v2, you can embed maps into an activity
     as a fragment with a simple XML snippet. The new Maps offer exciting features such as 3D maps;
     indoor, satellite, terrain, and hybrid maps;
     vector-based tiles for efficient caching and drawing; animated transitions; and much more.
@@ -58,7 +58,7 @@
   <div class="col-6 normal-links">
     <h3 style="clear:left">Getting Started</h3>
     <h4>1. Get the Google Play services SDK</h4>
-    <p>The Google Maps Android APIs are part of the Google Play services platform.</p>
+    <p>Google Maps Android API v2 is part of the Google Play services platform.</p>
     <p>To use Google Maps, <a href="{@docRoot}google/play-services/setup.html">set up
       the Google Play services SDK</a>. Then see the <a class="external-link"
       href="https://developers.google.com/maps/documentation/android/start#installing_the_google_maps_android_v2_api">
@@ -69,7 +69,7 @@
     
     <p>Once you've installed the Google Play services package, the Google Maps sample is located in
       <code>&lt;android-sdk&gt;/extras/google-play-services/samples/maps</code> and shows you
-      how to use the major components of the Google Maps Android APIs.
+      how to use the major components of Google Maps Android API v2.
     </p>
     
     <h4>3. Read the documentation</h4>
@@ -79,9 +79,9 @@
     
     <p>For quick access while developing your Android apps, the
       <a href="{@docRoot}reference/com/google/android/gms/maps/package-summary.html">Google Maps
-      Android API reference</a> is available here on developer.android.com.</p>
+      Android API v2 reference</a> is available here on developer.android.com.</p>
 
-    <p>Detailed documentation for the Google Maps Android APIs is available with the rest of the
+    <p>Detailed documentation for Google Maps Android API v2 is available with the rest of the
     Google Maps developer documents at <a class="external-link"
     href="https://developers.google.com/maps/documentation/android/">developers.google.com/maps</a>.
     </p>
diff --git a/docs/html/google/play-services/setup.jd b/docs/html/google/play-services/setup.jd
index 3137890..5df2629 100644
--- a/docs/html/google/play-services/setup.jd
+++ b/docs/html/google/play-services/setup.jd
@@ -104,7 +104,7 @@
 
 dependencies {
     compile 'com.android.support:appcompat-v7:+'
-    <strong>compile 'com.google.android.gms:play-services:4.0.30'</strong>
+    <strong>compile 'com.google.android.gms:play-services:4.3.23'</strong>
 }
 </pre>
 <p>Be sure you update this version number each time Google Play services is updated.</p>
@@ -235,4 +235,4 @@
 
 
 <p>To then begin a connection to Google Play services, read <a
-href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
\ No newline at end of file
+href="{@docRoot}google/auth/api-client.html">Accessing Google Play Services APIs</a>.</p>
diff --git a/docs/html/guide/components/intents-common.jd b/docs/html/guide/components/intents-common.jd
index 826dcff..a0f7ce1 100644
--- a/docs/html/guide/components/intents-common.jd
+++ b/docs/html/guide/components/intents-common.jd
@@ -56,6 +56,7 @@
   <li><a href="#Music">Music or Video</a>
     <ol>
       <li><a href="#PlayMedia">Play a media file</a></li>
+      <li><a href="#PlaySearch">Play music based on a search query</a></li>
     </ol>
   </li>
   <li><a href="#Phone">Phone</a>
@@ -1287,9 +1288,251 @@
 </pre>
 
 
+<h3 id="PlaySearch">Play music based on a search query</h3>
+
+<p>To play music based on a search query, use the
+{@link android.provider.MediaStore#INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH} intent. An app may fire
+this intent in response to the user's voice command to play music. The receiving app for this
+intent performs a search within its inventory to match existing content to the given query and
+starts playing that content.</p>
+
+<p>This intent should include the {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} string
+extra, which specifies the inteded search mode. For example, the search mode can specify whether
+the search is for an artist name or song name.</p>
+
+<dl>
+<dt><b>Action</b></dt>
+<dd>{@link android.provider.MediaStore#INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH}</dd>
+
+<dt><b>Data URI Scheme</b></dt>
+<dd>None</dd>
+
+<dt><b>MIME Type</b></dt>
+<dd>None</dd>
+
+<dt><b>Extras</b></dt>
+<dd>
+<dl>
+<dt>{@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS MediaStore.EXTRA_MEDIA_FOCUS} (required)</dt>
+<dd>
+<p>Indicates the search mode (whether the user is looking for a particular artist, album, song,
+playlist, or radio channel). Most search modes take additional extras. For example, if the user
+is interested in listening to a particular song, the intent might have three additional extras:
+the song title, the artist, and the album. This intent supports the following search modes for
+each value of {@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS}:</p>
+<dl>
+<dt><p><em>Any</em> - <code>"vnd.android.cursor.item/*"</p></code></dt>
+<dd>
+<p>Play any music. The receiving app should play some music based on a smart choice, such
+as the last playlist the user listened to.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.app.SearchManager#QUERY} (required) - An empty string. This extra is always
+      provided for backward compatibility: existing apps that do not know about search modes can
+      process this intent as an unstructured search.</li>
+</ul>
+</dd>
+<dt><p><em>Unstructured</em> - <code>"vnd.android.cursor.item/*"</code></p></dt>
+<dd>
+<p>Play a particular song, album or genre from an unstructured search query. Apps may generate
+an intent with this search mode when they can't identify the type of content the user wants to
+listen to. Apps should use more specific search modes when possible.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination
+      of: the artist, the album, the song name, or the genre.</li>
+</ul>
+</dd>
+<dt><p><em>Genre</em> -
+{@link android.provider.MediaStore.Audio.Genres#ENTRY_CONTENT_TYPE Audio.Genres.ENTRY_CONTENT_TYPE}</p></dt>
+<dd>
+<p>Play music of a particular genre.</p>
+<p>Additional extras:</p>
+<ul>
+  <li><code>"android.intent.extra.genre"</code> (required) - The genre.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - The genre. This extra is always provided
+      for backward compatibility: existing apps that do not know about search modes can process
+      this intent as an unstructured search.</li>
+</ul>
+</dd>
+<dt><p><em>Artist</em> -
+{@link android.provider.MediaStore.Audio.Artists#ENTRY_CONTENT_TYPE Audio.Artists.ENTRY_CONTENT_TYPE}</p></dt>
+<dd>
+<p>Play music from a particular artist.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ARTIST} (required) - The artist.</li>
+  <li><code>"android.intent.extra.genre"</code> - The genre.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination of
+      the artist or the genre. This extra is always provided for backward compatibility:
+      existing apps that do not know about search modes can process this intent as an unstructured
+      search.</li>
+</ul>
+</dd>
+<dt><p><em>Album</em> -
+{@link android.provider.MediaStore.Audio.Albums#ENTRY_CONTENT_TYPE Audio.Albums.ENTRY_CONTENT_TYPE}</p></dt>
+<dd>
+<p>Play music from a particular album.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ALBUM} (required) - The album.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ARTIST} - The artist.</li>
+  <li><code>"android.intent.extra.genre"</code> - The genre.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination of
+      the album or the artist. This extra is always provided for backward
+      compatibility: existing apps that do not know about search modes can process this intent as an
+      unstructured search.</li>
+</ul>
+</dd>
+<dt><p><em>Song</em> - <code>"vnd.android.cursor.item/audio"</code></p></dt>
+<dd>
+<p>Play a particular song.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ALBUM} - The album.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ARTIST} - The artist.</li>
+  <li><code>"android.intent.extra.genre"</code> - The genre.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_TITLE} (required) - The song name.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination of:
+      the album, the artist, the genre, or the title. This extra is always provided for
+      backward compatibility: existing apps that do not know about search modes can process this
+      intent as an unstructured search.</li>
+</ul>
+</dd>
+<dt><p><em>Radio channel</em> - <code>"vnd.android.cursor.item/radio"</code></p></dt>
+<dd>
+<p>Play a particular radio channel or a radio channel that matches some criteria specified
+by additional extras.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ALBUM} - The album.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ARTIST} - The artist.</li>
+  <li><code>"android.intent.extra.genre"</code> - The genre.</li>
+  <li><code>"android.intent.extra.radio_channel"</code> - The radio channel.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_TITLE} - The song name that the radio
+      channel is based on.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination
+      of: the album, the artist, the genre, the radio channel, or the title. This extra is
+      always provided for backward compatibility: existing apps that do not know about search
+      modes can process this intent as an unstructured search.</li>
+</ul>
+</dd>
+<dt><p><em>Playlist</em> - {@link android.provider.MediaStore.Audio.Playlists#ENTRY_CONTENT_TYPE Audio.Playlists.ENTRY_CONTENT_TYPE}</p></dt>
+<dd>
+<p>Play a particular playlist or a playlist that matches some criteria specified
+by additional extras.</p>
+<p>Additional extras:</p>
+<ul>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ALBUM} - The album.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_ARTIST} - The artist.</li>
+  <li><code>"android.intent.extra.genre"</code> - The genre.</li>
+  <li><code>"android.intent.extra.playlist"</code> - The playlist.</li>
+  <li>{@link android.provider.MediaStore#EXTRA_MEDIA_TITLE} - The song name that the playlist is
+      based on.</li>
+  <li>{@link android.app.SearchManager#QUERY} (required) - A string that contains any combination
+      of: the album, the artist, the genre, the playlist, or the title. This extra is always
+      provided for backward compatibility: existing apps that do not know about search modes can
+      process this intent as an unstructured search.</li>
+</ul>
+</dd>
+</dl>
+</dd>
+</dl>
+</dd>
+</dl>
 
 
 
+<p><b>Example intent:</b></p>
+<p>If the user wants to listen to a radio station that plays songs from a particular artist,
+a search app may generate the following intent:</p>
+<pre>
+public void playSearchRadioByArtist(String artist) {
+    Intent intent = new Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH);
+    intent.putExtra(MediaStore.EXTRA_MEDIA_FOCUS,
+                    "vnd.android.cursor.item/radio");
+    intent.putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist);
+    intent.putExtra(SearchManager.QUERY, artist);
+    if (intent.resolveActivity(getPackageManager()) != null) {
+        startActivity(intent);
+    }
+}
+</pre>
+
+<p><b>Example intent filter:</b></p>
+<pre>
+&lt;activity ...>
+    &lt;intent-filter>
+        &lt;action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
+        &lt;category android:name="android.intent.category.DEFAULT" />
+    &lt;/intent-filter>
+&lt;/activity>
+</pre>
+<p>When handling this intent, your activity should check the value of the
+{@link android.provider.MediaStore#EXTRA_MEDIA_FOCUS} extra in the incoming
+{@link android.content.Intent} to determine the search mode. Once your activity has identified
+the search mode, it should read the values of the additional extras for that particular search mode.
+With this information your app can then perform the search within its inventory to play the
+content that matches the search query. For example:</p>
+<pre>
+protected void onCreate(Bundle savedInstanceState) {
+    ...
+    Intent intent = this.getIntent();
+    if (intent.getAction().compareTo(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH) == 0) {
+
+        String mediaFocus = intent.getStringExtra(MediaStore.EXTRA_MEDIA_FOCUS);
+        String query = intent.getStringExtra(SearchManager.QUERY);
+
+        // Some of these extras may not be available depending on the search mode
+        String album = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ALBUM);
+        String artist = intent.getStringExtra(MediaStore.EXTRA_MEDIA_ARTIST);
+        String genre = intent.getStringExtra("android.intent.extra.genre");
+        String playlist = intent.getStringExtra("android.intent.extra.playlist");
+        String rchannel = intent.getStringExtra("android.intent.extra.radio_channel");
+        String title = intent.getStringExtra(MediaStore.EXTRA_MEDIA_TITLE);
+
+        // Determine the search mode and use the corresponding extras
+        if (mediaFocus == null) {
+            // 'Unstructured' search mode (backward compatible)
+            playUnstructuredSearch(query);
+
+        } else if (mediaFocus.compareTo("vnd.android.cursor.item/*") == 0) {
+            if (query.isEmpty()) {
+                // 'Any' search mode
+                playResumeLastPlaylist();
+            } else {
+                // 'Unstructured' search mode
+                playUnstructuredSearch(query);
+            }
+
+        } else if (mediaFocus.compareTo(MediaStore.Audio.Genres.ENTRY_CONTENT_TYPE) == 0) {
+            // 'Genre' search mode
+            playGenre(genre);
+
+        } else if (mediaFocus.compareTo(MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE) == 0) {
+            // 'Artist' search mode
+            playArtist(artist, genre);
+
+        } else if (mediaFocus.compareTo(MediaStore.Audio.Albums.ENTRY_CONTENT_TYPE) == 0) {
+            // 'Album' search mode
+            playAlbum(album, artist);
+
+        } else if (mediaFocus.compareTo("vnd.android.cursor.item/audio") == 0) {
+            // 'Song' search mode
+            playSong(album, artist, genre, title);
+
+        } else if (mediaFocus.compareTo("vnd.android.cursor.item/radio") == 0) {
+            // 'Radio channel' search mode
+            playRadioChannel(album, artist, genre, rchannel, title);
+
+        } else if (mediaFocus.compareTo(MediaStore.Audio.Playlists.ENTRY_CONTENT_TYPE) == 0) {
+            // 'Playlist' search mode
+            playPlaylist(album, artist, genre, playlist, title);
+        }
+    }
+}
+</pre>
+
 
 
 
diff --git a/docs/html/guide/topics/data/backup.jd b/docs/html/guide/topics/data/backup.jd
index 4903852..f09ff9e 100644
--- a/docs/html/guide/topics/data/backup.jd
+++ b/docs/html/guide/topics/data/backup.jd
@@ -899,8 +899,9 @@
 {@code tools/} path:
 <pre class="no-pretty-print">adb shell bmgr enable true</pre>
       </li>
-      <li>If using a device, open the system <b>Settings</b>, select <b>Privacy</b>, then enable
-<b>Back up my data</b> and <b>Automatic restore</b>.
+      <li>If using a device, open the system <b>Settings</b>, select
+      <b>Backup & reset</b>, then enable
+      <b>Back up my data</b> and <b>Automatic restore</b>.</li>
     </ul>
   </li>
   <li>Open your application and initialize some data
diff --git a/docs/html/guide/topics/manifest/manifest-element.jd b/docs/html/guide/topics/manifest/manifest-element.jd
index 20dc4ea..7717696 100644
--- a/docs/html/guide/topics/manifest/manifest-element.jd
+++ b/docs/html/guide/topics/manifest/manifest-element.jd
@@ -30,7 +30,7 @@
 <br/><code><a href="{@docRoot}guide/topics/manifest/permission-element.html">&lt;permission&gt;</a></code>
 <br/><code><a href="{@docRoot}guide/topics/manifest/permission-group-element.html">&lt;permission-group&gt;</a></code>
 <br/><code><a href="{@docRoot}guide/topics/manifest/permission-tree-element.html">&lt;permission-tree&gt;</a></code>
-<br/><code><a href="{@docRoot}guide/topics/manifest/supports-gl-texture.html">&lt;supports-gl-texture&gt;</a></code
+<br/><code><a href="{@docRoot}guide/topics/manifest/supports-gl-texture-element.html">&lt;supports-gl-texture&gt;</a></code>
 <br/><code><a href="{@docRoot}guide/topics/manifest/supports-screens-element.html">&lt;supports-screens&gt;</a></code>
 <br/><code><a href="{@docRoot}guide/topics/manifest/uses-configuration-element.html">&lt;uses-configuration&gt;</a></code>  <!-- ##api level 3## -->
 <br/><code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html">&lt;uses-feature&gt;</a></code>
@@ -193,4 +193,4 @@
 <dd>
 <code><a href="{@docRoot}guide/topics/manifest/application-element.html">&lt;application&gt;</a></code></dd>
 
-</dl>
\ No newline at end of file
+</dl>
diff --git a/docs/html/guide/topics/ui/actionbar.jd b/docs/html/guide/topics/ui/actionbar.jd
index a122443..a61696a 100644
--- a/docs/html/guide/topics/ui/actionbar.jd
+++ b/docs/html/guide/topics/ui/actionbar.jd
@@ -1126,8 +1126,8 @@
 uses a string array as the data source:</p>
 
 <pre>
-SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this, R.array.action_list,
-          android.R.layout.simple_spinner_dropdown_item);
+SpinnerAdapter mSpinnerAdapter = ArrayAdapter.createFromResource(this,
+        R.array.action_list, android.R.layout.simple_spinner_dropdown_item);
 </pre>
 
 <p>The {@link android.widget.ArrayAdapter#createFromResource createFromResource()} method takes
@@ -1145,7 +1145,7 @@
         &lt;item&gt;Venus&lt;/item&gt;
         &lt;item&gt;Earth&lt;/item&gt;
     &lt;/string-array&gt;
-&lt;/pre&gt;
+&lt;/resources&gt;
 </pre>
 
 <p>The {@link android.widget.ArrayAdapter} returned by {@link
@@ -1179,10 +1179,13 @@
   public boolean onNavigationItemSelected(int position, long itemId) {
     // Create new fragment from our own Fragment class
     ListContentFragment newFragment = new ListContentFragment();
-    FragmentTransaction ft = openFragmentTransaction();
+    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
+
     // Replace whatever is in the fragment container with this fragment
-    //  and give the fragment a tag name equal to the string at the position selected
+    // and give the fragment a tag name equal to the string at the position
+    // selected
     ft.replace(R.id.fragment_container, newFragment, strings[position]);
+
     // Apply changes
     ft.commit();
     return true;
@@ -1210,7 +1213,8 @@
     &#64;Override
     public void onAttach(Activity activity) {
       // This is the first callback received; here we can set the text for
-      // the fragment as defined by the tag specified during the fragment transaction
+      // the fragment as defined by the tag specified during the fragment
+      // transaction
       super.onAttach(activity);
       mText = getTag();
     }
diff --git a/docs/html/images/gcm/CCS-ack.png b/docs/html/images/gcm/CCS-ack.png
index bce2ab2..4633157 100644
--- a/docs/html/images/gcm/CCS-ack.png
+++ b/docs/html/images/gcm/CCS-ack.png
Binary files differ
diff --git a/docs/html/images/tools/as-android.png b/docs/html/images/tools/as-android.png
new file mode 100644
index 0000000..7808ed1
--- /dev/null
+++ b/docs/html/images/tools/as-android.png
Binary files differ
diff --git a/docs/html/images/tools/as-breakpointline.png b/docs/html/images/tools/as-breakpointline.png
new file mode 100644
index 0000000..9aea880
--- /dev/null
+++ b/docs/html/images/tools/as-breakpointline.png
Binary files differ
diff --git a/docs/html/images/tools/as-breakpointswindow.png b/docs/html/images/tools/as-breakpointswindow.png
new file mode 100644
index 0000000..a40b459
--- /dev/null
+++ b/docs/html/images/tools/as-breakpointswindow.png
Binary files differ
diff --git a/docs/html/images/tools/as-capture.png b/docs/html/images/tools/as-capture.png
new file mode 100644
index 0000000..02f9f6f
--- /dev/null
+++ b/docs/html/images/tools/as-capture.png
Binary files differ
diff --git a/docs/html/images/tools/as-currentproc.png b/docs/html/images/tools/as-currentproc.png
new file mode 100644
index 0000000..4be8305
--- /dev/null
+++ b/docs/html/images/tools/as-currentproc.png
Binary files differ
diff --git a/docs/html/images/tools/as-ddmslog.png b/docs/html/images/tools/as-ddmslog.png
new file mode 100644
index 0000000..b53b8fe
--- /dev/null
+++ b/docs/html/images/tools/as-ddmslog.png
Binary files differ
diff --git a/docs/html/images/tools/as-debugbutton.png b/docs/html/images/tools/as-debugbutton.png
new file mode 100644
index 0000000..55e95d1
--- /dev/null
+++ b/docs/html/images/tools/as-debugbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-debugdevices.png b/docs/html/images/tools/as-debugdevices.png
new file mode 100644
index 0000000..09a9d0e
--- /dev/null
+++ b/docs/html/images/tools/as-debugdevices.png
Binary files differ
diff --git a/docs/html/images/tools/as-debugview.png b/docs/html/images/tools/as-debugview.png
new file mode 100644
index 0000000..0349147
--- /dev/null
+++ b/docs/html/images/tools/as-debugview.png
Binary files differ
diff --git a/docs/html/images/tools/as-debugwindowbutton.png b/docs/html/images/tools/as-debugwindowbutton.png
new file mode 100644
index 0000000..9016778
--- /dev/null
+++ b/docs/html/images/tools/as-debugwindowbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-devicecapture.png b/docs/html/images/tools/as-devicecapture.png
new file mode 100644
index 0000000..3236a89
--- /dev/null
+++ b/docs/html/images/tools/as-devicecapture.png
Binary files differ
diff --git a/docs/html/images/tools/as-evalexpbutton.png b/docs/html/images/tools/as-evalexpbutton.png
new file mode 100644
index 0000000..85b3c74
--- /dev/null
+++ b/docs/html/images/tools/as-evalexpbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-launchavdm.png b/docs/html/images/tools/as-launchavdm.png
new file mode 100644
index 0000000..bf15981
--- /dev/null
+++ b/docs/html/images/tools/as-launchavdm.png
Binary files differ
diff --git a/docs/html/images/tools/as-monitorbutton.png b/docs/html/images/tools/as-monitorbutton.png
new file mode 100644
index 0000000..6bdc3a5
--- /dev/null
+++ b/docs/html/images/tools/as-monitorbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-record.png b/docs/html/images/tools/as-record.png
new file mode 100644
index 0000000..5f7fa99
--- /dev/null
+++ b/docs/html/images/tools/as-record.png
Binary files differ
diff --git a/docs/html/images/tools/as-restart.png b/docs/html/images/tools/as-restart.png
new file mode 100644
index 0000000..12d2923
--- /dev/null
+++ b/docs/html/images/tools/as-restart.png
Binary files differ
diff --git a/docs/html/images/tools/as-resumeprogrambutton.png b/docs/html/images/tools/as-resumeprogrambutton.png
new file mode 100644
index 0000000..8096937
--- /dev/null
+++ b/docs/html/images/tools/as-resumeprogrambutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-showdevview.png b/docs/html/images/tools/as-showdevview.png
new file mode 100644
index 0000000..602a6ad
--- /dev/null
+++ b/docs/html/images/tools/as-showdevview.png
Binary files differ
diff --git a/docs/html/images/tools/as-stepintobutton.png b/docs/html/images/tools/as-stepintobutton.png
new file mode 100644
index 0000000..569d4ed
--- /dev/null
+++ b/docs/html/images/tools/as-stepintobutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-stepoutbutton.png b/docs/html/images/tools/as-stepoutbutton.png
new file mode 100644
index 0000000..ef8871f
--- /dev/null
+++ b/docs/html/images/tools/as-stepoutbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-stepoverbutton.png b/docs/html/images/tools/as-stepoverbutton.png
new file mode 100644
index 0000000..1c487df
--- /dev/null
+++ b/docs/html/images/tools/as-stepoverbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-variablesview.png b/docs/html/images/tools/as-variablesview.png
new file mode 100644
index 0000000..6a0b987
--- /dev/null
+++ b/docs/html/images/tools/as-variablesview.png
Binary files differ
diff --git a/docs/html/images/tools/as-varviewbutton.png b/docs/html/images/tools/as-varviewbutton.png
new file mode 100644
index 0000000..2ad4c58
--- /dev/null
+++ b/docs/html/images/tools/as-varviewbutton.png
Binary files differ
diff --git a/docs/html/images/tools/as-viewbreakbutton.png b/docs/html/images/tools/as-viewbreakbutton.png
new file mode 100644
index 0000000..22723d4
--- /dev/null
+++ b/docs/html/images/tools/as-viewbreakbutton.png
Binary files differ
diff --git a/docs/html/sdk/installing/index.jd b/docs/html/sdk/installing/index.jd
index 9d5e8c1..6b63ba7 100644
--- a/docs/html/sdk/installing/index.jd
+++ b/docs/html/sdk/installing/index.jd
@@ -35,10 +35,10 @@
 
 </div>
 
-  
+
 
 <div id="mac" class="docs" style="display:none">
-  
+
 <h3>Getting started on Mac</h3>
 
 <ol>
@@ -62,7 +62,7 @@
 
 
 <div id="linux" class="docs" style="display:none">
-  
+
 <h3>Getting started on Linux</h3>
 
 <ol>
@@ -97,17 +97,23 @@
   <li>Here are the steps to install Java and Eclipse, prior to installing
   the Android SDK and ADT Plugin.
     <ol>
-      <li>If you are running a 64-bit distribution on your development
-      machine, you need to install the <code>ia32-libs</code> package using
-      <code>apt-get:</code>:
-      <pre>apt-get install ia32-libs</pre>
+      <li><p>If you are running a 64-bit distribution on your development
+      machine, you need to install additional packages first. For Ubuntu 13.10 (Saucy Salamander)
+      and above, install the <code>libncurses5:i386</code>, <code>libstdc++6:i386</code>, and
+      <code>zlib1g:i386</code> packages using <code>apt-get</code>:</p>
+      <pre class="no-pretty-print">sudo dpkg --add-architecture i386
+sudo apt-get update
+sudo apt-get install libncurses5:i386 libstdc++6:i386 zlib1g:i386</pre>
+      <p>For earlier versions of Ubuntu, install the <code>ia32-libs</code> package using
+      <code>apt-get</code>:</p>
+      <pre class="no-pretty-print">apt-get install ia32-libs</pre>
       </li>
-      <li>Next, install Java: <pre>apt-get install sun-java6-jdk</pre></li>
-      <li>The Ubuntu package manager does not currently offer an Eclipse 3.6
+      <li>Next, install Java: <pre class="no-pretty-print">apt-get install sun-java6-jdk</pre></li>
+      <li>The Ubuntu package manager does not currently offer an Eclipse 3.7
       version for download, so we recommend that you download Eclipse from
       eclipse.org (<a
-      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/
-      downloads/</a>). A Java or RCP version of Eclipse is recommended.</li>
+      href="http://www.eclipse.org/downloads/">http://www.eclipse.org/downloads/</a>).
+      A Java or RCP version of Eclipse is recommended.</li>
       <li>Follow the steps given in previous sections to install the SDK
       and the ADT plugin. </li>
     </ol>
@@ -137,7 +143,7 @@
     // not running a compatible OS, so just show all the docs
     $('.docs').show();
   }
-  
+
   function showAll() {
     $('.docs').each(function() {
       if (!$(this).is(':visible')) {
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index e4cf1bc..e12dfd8 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.6.2
-adt.zip.download=ADT-22.6.2.zip
-adt.zip.bytes=14586842
-adt.zip.checksum=f660959fa71262b4285bcb64be284bf5
+adt.zip.version=22.6.3
+adt.zip.download=ADT-22.6.3.zip
+adt.zip.bytes=14590813
+adt.zip.checksum=3982259fd2cc81e53bbbe05dcd6529a7
 
 @jd:body
 
diff --git a/docs/html/sdk/installing/studio-debug.jd b/docs/html/sdk/installing/studio-debug.jd
new file mode 100644
index 0000000..7e2efe3
--- /dev/null
+++ b/docs/html/sdk/installing/studio-debug.jd
@@ -0,0 +1,346 @@
+page.title=Debugging with Android Studio
+
+@jd:body
+
+<div id="qv-wrapper">
+<div id="qv">
+<h2>In this document</h2>
+<ol>
+  <li><a href="#runDebug">Run your App in Debug Mode</a></li>
+  <li><a href="#systemLog">Use the System Log</a>
+    <ol>
+      <li><a href="#systemLogWrite">Write log messages in your code</a></li>
+      <li><a href="#systemLogView">View the system log</a></li>
+    </ol>
+  </li>
+  <li><a href="#breakPoints">Work with Breakpoints</a>
+    <ol>
+        <li><a href="#breakPointsView">View and configure breakpoints</a></li>
+        <li><a href="#breakPointsDebug">Debug your app with breakpoints</a></li>
+    </ol>
+  </li>
+  <li><a href="#deviceMonitor">Analyze Runtime Metrics to Optimize your App</a></li>
+  <li><a href="#screenCap">Capture Screenshots and Videos</a></li>
+</ol>
+<h2>See also</h2>
+<ul>
+<li><a href="{@docRoot}sdk/installing/studio-tips.html">
+Android Studio Tips and Tricks</a></li>
+<li><a href="{@docRoot}tools/debugging/index.html">Debugging</a></li>
+<li><a href="{@docRoot}tools/help/monitor.html">Device Monitor</a></li>
+<li><a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a></li>
+</div>
+</div>
+
+<p>Android Studio enables you to debug apps running on the emulator or on an Android device.
+With Android Studio, you can:</p>
+
+<ul>
+    <li>Select a device to debug your app on.</li>
+    <li>View the system log.</li>
+    <li>Set breakpoints in your code.</li>
+    <li>Examine variables and evaluate expressions at run time.</li>
+    <li>Run the debugging tools from the Android SDK.</li>
+    <li>Capture screenshots and videos of your app.</li>
+</ul>
+
+<p>To debug your app, Android Studio builds a debuggable version of your app, connects
+to a device or to the emulator, installs the app and runs it. The IDE shows the system log
+while your app is running and provides debugging tools to filter log messages, work with
+breakpoints, and control the execution flow.</p>
+
+
+<h2 id="runDebug">Run your App in Debug Mode</h2>
+
+<div class="figure" style="width:419px">
+    <img src="{@docRoot}images/tools/as-debugdevices.png" alt=""/>
+    <p class="img-caption"><strong>Figure 1.</strong> The Choose Device window enables you to
+    select a physical Android device or a virtual device to debug your app.</p>
+</div>
+
+<p>To run your app in debug mode, you build an APK signed with a debug key and install it on a
+physical Android device or on the Android emulator.
+To set up an Android device for development, see <a href="{@docRoot}tools/device.html">Using
+Hardware Devices</a>. For more information about the emulator provided by the Android SDK, see
+<a href="{@docRoot}tools/devices/emulator.html">Using the Emulator.</a></p>
+
+<p>To debug your app in Android Studio:</p>
+
+<ol>
+    <li>Open your project in Android Studio.</li>
+    <li>Click <strong>Debug</strong> <img src="{@docRoot}images/tools/as-debugbutton.png"
+        style="vertical-align:bottom;margin:0;height:22px"  alt=""/> in the toolbar.</li>
+    <li>On the <em>Choose Device</em> window, select a hardware device from the list or
+        choose a virtual device.</li>
+    <li>Click <strong>OK</strong>. Your app starts on the selected device.</li>
+</ol>
+
+<p>Figure 1 shows the <em>Choose Device</em> window. The list shows all the Android devices
+connected to your computer. Select <strong>Launch Emulator</strong> to use an Android virtual device
+instead. Click the ellipsis <img src="{@docRoot}images/tools/as-launchavdm.png"
+style="vertical-align:bottom;margin:0;height:19px" alt=""/> to open the
+<a href="{@docRoot}tools/devices/managing-avds.html">Android Virtual Device Manager</a>.</p>
+
+<p>Android Studio opens the <em>Debug</em> tool window when you debug your app. To open the
+<em>Debug</em> window manually, click <strong>Debug</strong>
+<img src="{@docRoot}images/tools/as-debugwindowbutton.png"
+alt="" style="vertical-align:bottom;margin:0;height:20px"/>.
+This window shows threads and variables in the <em>Debugger</em> tab, the device status in the
+<em>Console</em> tab, and the system log in the <em>Logcat</em> tab. The <em>Debug</em> tool
+window also provides other debugging tools covered in the following sections.</p>
+
+<img src="{@docRoot}images/tools/as-debugview.png" alt="" />
+<p class="img-caption"><strong>Figure 2.</strong> The Debug tool window in Android Studio showing
+the current thread and the object tree for a variable.</p>
+
+
+<h2 id="systemLog">Use the System Log</h2>
+
+<p>The system log shows system messages while you debug your app. These messages include
+information from apps running on the device. If you want to use the
+system log to debug your app, make sure your code writes log messages and prints the stack
+trace for exceptions while your app is in the development phase.</p>
+
+<h3 id="systemLogWrite">Write log messages in your code</h3>
+
+<p>To write log messages in your code, use the {@link android.util.Log} class. Log messages
+help you understand the execution flow by collecting the system debug output while you interact
+with your app. Log messages can tell you what part of your application failed. For more
+information about logging, see <a href="{@docRoot}tools/debugging/debugging-log.html">
+Reading and Writing Logs</a>.</p>
+
+<p>The following example shows how you might add log messages to determine if previous state
+information is available when your activity starts:</p>
+
+<pre>
+import android.util.Log;
+...
+public class MyActivity extends Activity {
+    private static final String TAG = MyActivity.class.getSimpleName();
+    ...
+    &#64;Override
+    public void onCreate(Bundle savedInstanceState) {
+        if (savedInstanceState != null) {
+            Log.d(TAG, "onCreate() Restoring previous state");
+            /* restore state */
+        } else {
+            Log.d(TAG, "onCreate() No saved state available");
+            /* initialize app */
+        }
+    }
+}
+</pre>
+
+<p>During development, your code can also catch exceptions and write the stack trace to the system
+log:</p>
+
+<pre>
+void someOtherMethod() {
+    try {
+        ...
+    } catch (SomeException e) {
+        Log.d(TAG, "someOtherMethod()", e);
+    }
+}
+</pre>
+
+<p class="note"><strong>Note:</strong> Remove debug log messages and stack trace print calls from
+your code when you are ready to publish your app. You could do this by setting a <code>DEBUG</code>
+flag and placing debug log messages inside conditional statements.</p>
+
+
+<h3 id="systemLogView">View the system log</h3>
+
+<p>Both the <em>Android DDMS</em> (Dalvik Debug Monitor Server) and the <em>Debug</em> tool windows
+show the system log; however, the <em>Android DDMS</em> tool window lets you view only log messages
+for a particular process. To view the system log on the <em>Android DDMS</em> tool window:</p>
+
+<ol>
+    <li>Start your app as described in <a href="#runDebug">Run your App in Debug Mode</a>.</li>
+    <li>Click <strong>Android</strong> <img src="{@docRoot}images/tools/as-android.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/> to open the <em>Android DDMS</em>
+        tool window.</li>
+    <li>If the system log is empty in the <em>Logcat view</em>, click <strong>Restart</strong>
+        <img src="{@docRoot}images/tools/as-restart.png" alt=""
+        style="vertical-align:bottom;margin:0;height:22px"/>.</li>
+</ol>
+
+<img src="{@docRoot}images/tools/as-ddmslog.png" alt="" />
+<p class="img-caption"><strong>Figure 4.</strong> The system log in the Android DDMS tool
+window.</p>
+
+<p>The <em>Android DDMS</em> tool window gives you access to some DDMS features from Android Studio.
+For more information about DDMS, see <a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.
+</p>
+
+<p>The system log shows messages from Android services and other Android apps. To filter the log
+messages to view only the ones you are interested in, use the tools in the <em>Android DDMS</em>
+window:</p>
+
+<ul>
+    <li>To show only log messages for a particular process, select the process in the
+        <em>Devices</em> view and then click <strong>Only Show Logcat from Selected
+        Process</strong> <img src="{@docRoot}images/tools/as-currentproc.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>. If the <em>Devices</em> view
+        is not available, click <strong>Restore Devices View</strong>
+        <img src="{@docRoot}images/tools/as-showdevview.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/> on the right of the <em>Android
+        DDMS</em> tool window. This button is only visible when you hide the <em>Devices</em>
+        window.</li>
+    <li>To filter log messages by log level, select a level under <em>Log Level</em> on the top
+        of the <em>Android DDMS</em> window.</li>
+    <li>To show only log messages that contain a particular string, enter the string in the search
+        box and press <strong>Enter</strong>.</li>
+</ul>
+
+
+<h2 id="breakPoints">Work with Breakpoints</h2>
+
+<p>Breakpoints enable you to pause the execution of your app at a particular line of code, examine
+variables, evaluate expressions, and continue the execution line by line. Use breakpoints to
+determine the causes of run-time errors that you can't fix by looking at your code only. To debug
+your app using breakpoints:</p>
+
+<ol>
+    <li>Open the source file in which you want to set a breakpoint.</li>
+    <li>Locate the line where you want to set a breakpoint and click on it.</li>
+    <li>Click on the yellow portion of the side bar to the left of this line, as shown in figure 5.</li>
+    <li>Start your app as described in <a href="#runDebug">Run your App in Debug Mode</a>.</li>
+</ol>
+
+<p>Android Studio pauses the execution of your app when it reaches the breakpoint. You can then
+use the tools in the <em>Debug</em> tool window to identify the cause of the error.</p>
+
+<img src="{@docRoot}images/tools/as-breakpointline.png" alt="" />
+<p class="img-caption"><strong>Figure 5.</strong> A red dot appears next to the line when you set
+a breakpoint.</p>
+
+<h3 id="breakPointsView">View and configure breakpoints</h3>
+
+<p>To view all the breakpoints and configure breakpoint settings, click <strong>View
+Breakpoints</strong> <img src="{@docRoot}images/tools/as-viewbreakbutton.png" alt=""
+style="vertical-align:bottom;margin:0;height:20px"/> on the left side of the <em>Debug</em> tool
+window. The <em>Breakpoints</em> window appears, as shown in figure 6.</p>
+
+<img src="{@docRoot}images/tools/as-breakpointswindow.png" alt="" />
+<p class="img-caption"><strong>Figure 6.</strong> The Breakpoints window lists all the current
+breakpoints and includes behavior settings for each.</p>
+
+<p>The <em>Breakpoints</em> window lets you enable or disable each breakpoint from the
+list on the left. If a breakpoint is disabled, Android Studio does not pause your app when
+it hits that breakpoint. Select a breakpoint from the list to configure its settings.
+You can configure a breakpoint to be disabled at first and have the system enable it after a
+different breakpoint is hit. You can also configure whether a breakpoint should be disabled after
+it is hit. To set a breakpoint for any exception, select <strong>Exception Breakpoints</strong>
+in the list of breakpoints.</p>
+
+<h3 id="breakPointsDebug">Debug your app with breakpoints</h3>
+
+<p>After you set breakpoints in your code, click <strong>Rerun</strong>
+<img src="{@docRoot}images/tools/as-restart.png" alt=""
+style="vertical-align:bottom;margin:0;height:20px"/> to start the app again. When a breakpoint is
+hit, Android Studio pauses the app and highlights the breakpoint in the source code. The
+<em>Debug</em> tool window lets you examine variables and control the execution step by
+step:</p>
+
+<ul>
+    <li>
+        <p>To examine the object tree for a variable, expand it in the <em>Variables</em> view. If
+        the <em>Variables</em> view is not visible, click <strong>Restore Variables View</strong>
+        <img src="{@docRoot}images/tools/as-varviewbutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+    <li>
+        <p>To evaluate an expression at the current execution point, click <strong>Evaluate
+        Expression</strong> <img src="{@docRoot}images/tools/as-evalexpbutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+    <li>
+        <p>To advance to the next line in the code (without entering a method), click <strong>Step
+        Over</strong> <img src="{@docRoot}images/tools/as-stepoverbutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+    <li>
+        <p>To advance to the first line inside a method call, click <strong>Step
+        Into</strong> <img src="{@docRoot}images/tools/as-stepintobutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+    <li>
+        <p>To advance to the next line outside the current method, click <strong>Step
+        Out</strong> <img src="{@docRoot}images/tools/as-stepoutbutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+    <li>
+        <p>To continue running the app normally, click <strong>Resume Program</strong>
+        <img src="{@docRoot}images/tools/as-resumeprogrambutton.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/>.</p>
+    </li>
+</ul>
+
+<img src="{@docRoot}images/tools/as-variablesview.png" alt="" />
+<p class="img-caption"><strong>Figure 7.</strong> The Variables view in the Debug tool window.</p>
+
+
+<h2 id="deviceMonitor">Analyze Runtime Metrics to Optimize your App</h2>
+
+<p>Even if your application does not generate runtime errors, this does not mean it is free of
+problems. You should also consider the following issues:</p>
+
+<ul>
+    <li>Does your app use memory efficiently?</li>
+    <li>Does your app generate unnecessary network traffic?</li>
+    <li>What methods should you focus your attention on to improve the performance of your app?</li>
+    <li>Does your app behave properly when the user receives a phone call or a message?</li>
+</ul>
+
+<p>The Android Device Monitor is a stand-alone tool with a graphical user interface for serveral
+Android application debugging and analysis tools, including the Dalvik Debug Monitor Server (DDMS).
+You can use the Android Device Monitor to analyze memory usage, profile methods,
+monitor network traffic and simulate incoming calls and messages.</p>
+
+<p>To open the Android Device Monitor from Android Studio, click
+<strong>Monitor</strong> <img src="{@docRoot}images/tools/as-monitorbutton.png" alt=""
+style="vertical-align:bottom;margin:0;height:20px"/> on the toolbar. The Android Device Monitor
+opens in a new window.</p>
+
+<p>For more information about the Android Device Monitor and DDMS, see
+<a href="{@docRoot}tools/help/monitor.html">Device Monitor</a> and
+<a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p>
+
+
+<h2 id="screenCap">Capture Screenshots and Videos</h2>
+
+<p>Android Studio enables you to capture a screenshot or a short video of the device screen
+while your app is running. Screenshots and videos are useful as promotional materials for your
+app, and you can also attach them to bug reports that you send to your development team.</p>
+
+<p>To take a screenshot of your app:</p>
+
+<ol>
+    <li>Start your app as described in <a href="#runDebug">Run your App in Debug Mode</a>.</li>
+    <li>Click <strong>Android</strong> <img src="{@docRoot}images/tools/as-android.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/> to open the <em>Android DDMS</em>
+        tool window.</li>
+    <li>Click <strong>Screen Capture</strong> <img src="{@docRoot}images/tools/as-capture.png"
+        style="vertical-align:bottom;margin:0;height:22px" alt=""/> on the left side of the
+        <em>Android DDMS</em> tool window.</li>
+    <li>Optional: To add a device frame around your screenshot, enable the <em>Frame screenshot</em>
+        option.</li>
+    <li>Click <strong>Save</strong>.</li>
+</ol>
+
+<p>To take a video recording of your app:</p>
+
+<ol>
+    <li>Start your app as described in <a href="#runDebug">Run your App in Debug Mode</a>.</li>
+    <li>Click <strong>Android</strong> <img src="{@docRoot}images/tools/as-android.png" alt=""
+        style="vertical-align:bottom;margin:0;height:20px"/> to open the <em>Android DDMS</em>
+        tool window.</li>
+    <li>Click <strong>Screen Record</strong> <img src="{@docRoot}images/tools/as-record.png"
+        style="vertical-align:bottom;margin:0;height:22px" alt=""/> on the left side of the
+        <em>Android DDMS</em> tool window.</li>
+    <li>Click <strong>Start Recording</strong>.</li>
+    <li>Interact with your app.</li>
+    <li>Click <strong>Stop Recording</strong>.</li>
+    <li>Enter a file name for the recording and click <strong>OK</strong>.</li>
+</ol>
\ No newline at end of file
diff --git a/docs/html/sdk/installing/studio.jd b/docs/html/sdk/installing/studio.jd
index 071492d..8ea5e7e 100644
--- a/docs/html/sdk/installing/studio.jd
+++ b/docs/html/sdk/installing/studio.jd
@@ -253,36 +253,36 @@
     <td>Windows</td>
     <td>
   <a onclick="return onDownload(this)" id="win-studio"
-      href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-windows.exe">
-      android-studio-bundle-133.1028713-windows.exe
+      href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-windows.exe">
+      android-studio-bundle-135.1078000-windows.exe
       </a>
     </td>
-    <td>519592042 bytes</td>
-    <td>9029c18738a75830786326d62c96d557</td>
+    <td>519082997 bytes</td>
+    <td>ac69889210c4d02ee3ccc1c0f3c5cf3c</td>
   </tr>
 
   <tr>
     <td><nobr>Mac OS X</nobr></td>
     <td>
   <a onclick="return onDownload(this)" id="mac-studio"
-    href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-mac.dmg">
-    android-studio-bundle-133.1028713-mac.dmg
+    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-mac.dmg">
+    android-studio-bundle-135.1078000-mac.dmg
     </a>
     </td>
-    <td>497595811 bytes</td>
-    <td>eb2474e6d17537ddfa535e6fe8adcf0d</td>
+    <td>495989974 bytes</td>
+    <td>8c7b1ef376b8ca206c99823d9e8fd54d</td>
   </tr>
 
   <tr>
     <td>Linux</td>
     <td>
   <a onclick="return onDownload(this)" id="linux-studio"
-    href="http://dl.google.com/android/studio/install/0.4.6/android-studio-bundle-133.1028713-linux.tgz">
-    android-studio-bundle-133.1028713-linux.tgz
+    href="http://dl.google.com/android/studio/install/0.5.2/android-studio-bundle-135.1078000-linux.tgz">
+    android-studio-bundle-135.1078000-linux.tgz
     </a>
     </td>
-    <td>522177460 bytes</td>
-    <td>cc847dd6249b3033737dabe0377c8c66</td>
+    <td>520523870 bytes</td>
+    <td>689238d5e632fd236b13f9c6d49f0cb4</td>
   </tr>
   </table>
 
@@ -430,6 +430,19 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>Android Studio v0.5.2</a> <em>(May 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+  <ul>
+    <li>See <a href="http://tools.android.com/recent">tools.android.com</a> for a full list of changes.</li>
+  </ul>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>Android Studio v0.4.6</a> <em>(March 2014)</em>
   </p>
 
@@ -650,7 +663,7 @@
   if (os) {
     /* set up primary ACE download button */
     $('#download-ide-button').show();
-    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.4.6</span>"
+    $('#download-ide-button').append("Download Android Studio <span class='small'>v0.5.2</span>"
         + "<br/> <span class='small'>for " + os + "</span>");
     $('#download-ide-button').click(function() {return onDownload(this,true);}).attr('href', bundlename);
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index d106f4a..124e58d 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,10 +53,49 @@
 <p>For a summary of all known issues in ADT, see <a
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
 
-
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 22.6.3</a> <em>(April 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.6.3</a>.
+        If you haven't already installed SDK Tools r22.6.3 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed a problem where the AVD manager allowed creating Android Wear virtual devices
+          with a target API Level lower than 19.</li>
+      <li>Fixed the description of Android Wear system images in the SDK Manager.</li>
+    </ul>
+  </dd>
+
+  <dt>Known Issues:</dt>
+  <dd>
+    <p>When you create an Android Wear virtual device in the AVD manager, a target API Level
+       lower than 19 may be selected by default. Make sure you select the target API Level 19
+       when creating Android Wear virtual devices.</p>
+  </dd>
+</dl>
+</div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.6.2</a> <em>(March 2014)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/ndk/index.jd b/docs/html/tools/sdk/ndk/index.jd
index a22dc90..0ac1881 100644
--- a/docs/html/tools/sdk/ndk/index.jd
+++ b/docs/html/tools/sdk/ndk/index.jd
@@ -245,8 +245,8 @@
   but it always increases your app complexity. In general, you should only use the NDK
   if it is essential to your app&mdash;never because you simply prefer to program in C/C++.</p>
 
-  <p>Typical good candidates for the NDK are self-contained, CPU-intensive operations that don't
-  allocate much memory, such as signal processing, physics simulation, and so on. When examining
+  <p>Typical good candidates for the NDK are CPU-intensive workloads such as game engines,
+  signal processing, physics simulation, and so on. When examining
   whether or not you should develop in native code, think about your requirements and see if the
   Android framework APIs provide the functionality that you need.</p>
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 14b5505..9b06a9d 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -28,6 +28,46 @@
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 22.6.3</a> <em>(April 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 18 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 22.6.3 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.3.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Fixed a problem where the AVD manager allowed creating Android Wear virtual devices
+            with a target API Level lower than 19.</li>
+        <li>Fixed the description of Android Wear system images in the SDK Manager.</li>
+      </ul>
+    </dd>
+
+    <dt>Known Issues:</dt>
+    <dd>
+      <p>When you create an Android Wear virtual device in the AVD manager, a target API Level
+         lower than 19 may be selected by default. Make sure you select the target API Level 19
+         when creating Android Wear virtual devices.</p>
+    </dd>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.6.2</a> <em>(March 2014)</em>
   </p>
 
diff --git a/docs/html/tools/tools_toc.cs b/docs/html/tools/tools_toc.cs
index c281644..b29b87c 100644
--- a/docs/html/tools/tools_toc.cs
+++ b/docs/html/tools/tools_toc.cs
@@ -38,6 +38,8 @@
               Using the Layout Editor</a></li>
           <li><a href="<?cs var:toroot ?>sdk/installing/studio-build.html">
               Building Your Project with Gradle</a></li>
+          <li><a href="<?cs var:toroot ?>sdk/installing/studio-debug.html">
+              Debugging with Android Studio</a></li>
           </ul>
       </li>
       <li><a href="<?cs var:toroot ?>sdk/exploring.html">
diff --git a/docs/html/wear/images/11_bundles_A.png b/docs/html/wear/images/11_bundles_A.png
index 7199a1f..0ffc6ec 100644
--- a/docs/html/wear/images/11_bundles_A.png
+++ b/docs/html/wear/images/11_bundles_A.png
Binary files differ
diff --git a/docs/html/wear/images/11_bundles_B.png b/docs/html/wear/images/11_bundles_B.png
index bb751a2..c188d3d 100644
--- a/docs/html/wear/images/11_bundles_B.png
+++ b/docs/html/wear/images/11_bundles_B.png
Binary files differ
diff --git a/docs/html/wear/images/11_bundles_C.png b/docs/html/wear/images/11_bundles_C.png
new file mode 100644
index 0000000..de71c59
--- /dev/null
+++ b/docs/html/wear/images/11_bundles_C.png
Binary files differ
diff --git a/docs/html/wear/index.jd b/docs/html/wear/index.jd
index a6a6460..659e9f2 100644
--- a/docs/html/wear/index.jd
+++ b/docs/html/wear/index.jd
@@ -121,13 +121,13 @@
                 </p>
               </div>
               <div class="col-3-wide">
-                <img src="/wear/images/screens/circle_message2.png" alt="Image of a Hangouts message">
+                <img src="/wear/images/screens/circle_message2.png" itemprop="image" alt="" >
                 <p class="wear-small">
                   Get glanceable, actionable information at just the right time throughout the day.
                 </p>
               </div>
               <div class="col-3-wide">
-                <img src="/wear/images/screens/fitness-24.png" alt="Image showing ">
+                <img src="/wear/images/screens/fitness-24.png" alt="">
                 <p class="wear-small">
                   A wide range of sensors is available to your applications, from accelerometers to heart rate monitors.
                 </p>
diff --git a/docs/html/wear/notifications/stacks.jd b/docs/html/wear/notifications/stacks.jd
index 7f955f6..83e11c1 100644
--- a/docs/html/wear/notifications/stacks.jd
+++ b/docs/html/wear/notifications/stacks.jd
@@ -2,7 +2,8 @@
 
 @jd:body
 
-<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
+<img src="{@docRoot}wear/images/11_bundles_C.png" height="154" width="273" style="float:right;margin:0 0 20px 40px"/>
+<img src="{@docRoot}wear/images/11_bundles_B.png" height="200" width="169" style="clear:both;float:right;margin:0 0 20px 40px" />
 <img src="{@docRoot}wear/images/11_bundles_A.png" height="200" width="169" style="float:right;margin:0 0 20px 40px" />
 
 <p>When creating notifications for a handheld device, you should always aggregate similar
@@ -10,7 +11,7 @@
 for received messages, you should not show more than one notification
 on a handheld device&mdash;when more than one is message is received, use a single notification
 to provide a summary such as "2 new messages."</p>
-
+<br />
 <p>However, a summary notification is less useful on an Android wearable because users
 are not able to read details from each message on the wearable (they must open your app on the
 handheld to view more information). So for the wearable device, you should
@@ -25,25 +26,50 @@
 Wear</a>.</p>
 
 
-<h2 id="AddGroup">Add Each Notification to a Group</h2>
+<h2 id="AddGroup">Create notifications in stacks</h2>
+
+<div style="float:right">
+  <script src="//ajax.googleapis.com/ajax/libs/swfobject/2.2/swfobject.js"></script>
+  <div style="width:440;height:246; padding-left:20px">
+    <object type="application/x-shockwave-flash" id="ytapiplayer" data="//www.youtube.com/v/L4LvKOTkZ7Q?enablejsapi=1&amp;playerapiid=ytplayer&amp;version=3&amp;HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1" width="440" height="246" style="visibility: visible;"><param name="allowScriptAccess" value="always"></object>
+    <script type="text/javascript">
+        var params = { allowScriptAccess: "always" };
+        var atts = { id: "ytapiplayer" };
+        swfobject.embedSWF("//www.youtube.com/v/L4LvKOTkZ7Q?enablejsapi=1&playerapiid=ytplayer&version=3&HD=1;rel=0;showinfo=0;modestbranding;origin=developer.android.com;autohide=1",
+          "ytapiplayer", "440", "246", "8", null, null, params, atts);
+
+        // Callback used to pause/resume carousel based on video state
+        function onytplayerStateChange(newState) {
+           var isPaused = $("#pauseButton").hasClass("paused");
+           if ((newState == 1) || (newState == 3)) {
+           // if playing or buffering, pause the carousel
+             if (!isPaused) {
+                $("#pauseButton").click();
+             }
+           } else {
+           // otherwise, make sure carousel is running
+             if (isPaused) {
+                $("#pauseButton").click();
+             }
+           }
+        }
+
+        // Callback received when YouTube player loads to setup callback (above)
+        function onYouTubePlayerReady(playerId) {
+          var ytplayer = document.getElementById("ytapiplayer");
+          ytplayer.addEventListener("onStateChange", "onytplayerStateChange");
+        }
+
+    </script>
+  </div>
+</div>
+
 
 <p>To create a stack, call <a
 href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.Builder.html#setGroup(java.lang.String, int)">
 <code>setGroup()</code></a> for each notification you want in the stack, passing the same
-group key. For example:</p>
+group key.</p>
 
-<pre style="clear:right">
-final static String GROUP_KEY_EMAILS = "group_key_emails";
-
-NotificationCompat.Builder builder = new NotificationCompat.Builder(mContext)
-         .setContentTitle("New mail from " + sender)
-         .setContentText(subject)
-         .setSmallIcon(R.drawable.new_mail);
-
-Notification notif = new WearableNotifications.Builder(builder)
-         .setGroup(GROUP_KEY_EMAILS)
-         .build();
-</pre>
 
 <p>By default, notifications appear in the order in which you added them, with the most recent
   notification visible at the top.  You can define a specific position in the group
@@ -52,21 +78,82 @@
 <code>setGroup()</code></a>.</p>
 
 
-<h2 id="AddSummary">Add a Summary Notification</h2>
-
-<p>It's important that you still provide a summary notification that appears on handheld devices.
+<p>It's also important that you still provide a summary notification that appears on handheld devices.
 So in addition to adding each unique notification to the same stack group, also add a summary
 notification, but set its order position to be <a
 href="{@docRoot}reference/android/preview/support/wearable/notifications/WearableNotifications.html#GROUP_ORDER_SUMMARY"><code>GROUP_ORDER_SUMMARY</code></a>.</p>
 
-<pre>
-Notification summaryNotification = new WearableNotifications.Builder(builder)
-         .setGroup(GROUP_KEY_EMAILS, WearableNotifications.GROUP_ORDER_SUMMARY)
-         .build();
-</pre>
-
 <p>This notification will not appear in your stack of notifications on the wearable, but
 appears as the only notification on the handheld device.
+</p>
+
+
+<p>Here's an example that creates a stack notification for a wearable and
+a summary notification for a handset device:</p>
+
+<pre style="clear:right">
+public void sendNotifications() {
+    Bitmap bitmapMila = BitmapFactory.decodeResource(getResources(),
+    		R.drawable.mila128);
+
+    // Nuke all previous notifications and generate unique ids
+    NotificationManagerCompat.from(this).cancelAll();
+    int notificationId = 0;
+
+    // String to represent the group all the notifications will be a part of
+    final String GROUP_KEY_EMAILS = "group_key_messages";
+
+    // Group notification that will be visible on the phone
+    NotificationCompat.Builder builderG = new NotificationCompat.Builder(this)
+            .setContentTitle("2 Pet Notifications")
+            .setContentText("Mila and Dylan both sent messages")
+            .setSmallIcon(R.drawable.ic_launcher)
+            .setLargeIcon(bitmapMila);
+    Notification summaryNotification = new WearableNotifications
+    		.Builder(builderG)
+            .setGroup(GROUP_KEY_EMAILS, 
+            		WearableNotifications.GROUP_ORDER_SUMMARY)
+            .build();
+
+    // Separate notifications that will be visible on the watch
+    Intent viewIntent1 = new Intent(this, MainActivity.class);
+    PendingIntent viewPendingIntent1 =
+          PendingIntent.getActivity(this, notificationId+1, viewIntent1, 0);
+    NotificationCompat.Builder builder1 = new NotificationCompat.Builder(this)
+            .addAction(R.drawable.ic_action_done, "Treat Fed",
+            		viewPendingIntent1)
+            .setContentTitle("Message from Mila")
+            .setContentText("What's for dinner? "
+                            + "Can we have steak?")
+            .setSmallIcon(R.drawable.ic_launcher);
+    Notification notification1 = new WearableNotifications.Builder(builder1)
+            .setGroup(GROUP_KEY_EMAILS)
+            .build();
+
+    Intent viewIntent2 = new Intent(this, MainActivity.class);
+    PendingIntent viewPendingIntent2 =
+          PendingIntent.getActivity(this, notificationId+2, viewIntent2, 0);
+    NotificationCompat.Builder builder2 = new NotificationCompat.Builder(this)
+            .addAction(R.drawable.ic_action_done, "Water Filled",
+            		viewPendingIntent2)
+            .setContentTitle("Message from Dylan")
+            .setContentText("Can you refill our water bowl?")
+            .setSmallIcon(R.drawable.ic_launcher);
+    Notification notification2 = new WearableNotifications.Builder(builder2)
+            .setGroup(GROUP_KEY_EMAILS)
+            .build();
+
+    // Issue the group notification
+    NotificationManagerCompat notificationManager =
+    		NotificationManagerCompat.from(this);
+    notificationManager.notify(notificationId+0, summaryNotification);
+
+    // Issue the separate wear notifications
+    notificationManager.notify(notificationId+2, notification2);
+    notificationManager.notify(notificationId+1, notification1);
+}
+</pre>
+
 
 </body>
 </html>
diff --git a/docs/image_sources/gcm/CCS-ack.graffle b/docs/image_sources/gcm/CCS-ack.graffle
new file mode 100644
index 0000000..addd456
--- /dev/null
+++ b/docs/image_sources/gcm/CCS-ack.graffle
@@ -0,0 +1,1580 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>ActiveLayerIndex</key>
+	<integer>0</integer>
+	<key>ApplicationVersion</key>
+	<array>
+		<string>com.omnigroup.OmniGrafflePro</string>
+		<string>139.18.0.187838</string>
+	</array>
+	<key>AutoAdjust</key>
+	<true/>
+	<key>BackgroundGraphic</key>
+	<dict>
+		<key>Bounds</key>
+		<string>{{0, 0}, {576.00002479553223, 733}}</string>
+		<key>Class</key>
+		<string>SolidGraphic</string>
+		<key>FontInfo</key>
+		<dict>
+			<key>Font</key>
+			<string>Helvetica</string>
+			<key>Size</key>
+			<real>12</real>
+		</dict>
+		<key>ID</key>
+		<integer>2</integer>
+		<key>Style</key>
+		<dict>
+			<key>shadow</key>
+			<dict>
+				<key>Draws</key>
+				<string>NO</string>
+			</dict>
+			<key>stroke</key>
+			<dict>
+				<key>Draws</key>
+				<string>NO</string>
+			</dict>
+		</dict>
+	</dict>
+	<key>BaseZoom</key>
+	<integer>0</integer>
+	<key>CanvasOrigin</key>
+	<string>{0, 0}</string>
+	<key>ColumnAlign</key>
+	<integer>1</integer>
+	<key>ColumnSpacing</key>
+	<real>36</real>
+	<key>CreationDate</key>
+	<string>2013-08-08 01:54:22 +0000</string>
+	<key>Creator</key>
+	<string>Katie McCormick</string>
+	<key>DisplayScale</key>
+	<string>1 0/72 in = 1.0000 in</string>
+	<key>GraphDocumentVersion</key>
+	<integer>8</integer>
+	<key>GraphicsList</key>
+	<array>
+		<dict>
+			<key>Bounds</key>
+			<string>{{89, 329}, {169, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>250</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Now app server can send\
+message no. 101}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{102, 266}, {114, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>249</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 App server waits\
+for ack 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{153, 154}, {98, 44}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>244</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 Average\
+response time}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>226</integer>
+				<key>Position</key>
+				<real>0.375</real>
+			</dict>
+			<key>ID</key>
+			<integer>242</integer>
+			<key>Points</key>
+			<array>
+				<string>{263.00000095367432, 314.5}</string>
+				<string>{261, 99}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+				<key>Position</key>
+				<real>0.34722220897674561</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+				<key>Position</key>
+				<real>0.3541666567325592</real>
+			</dict>
+			<key>ID</key>
+			<integer>241</integer>
+			<key>Points</key>
+			<array>
+				<string>{261, 99}</string>
+				<string>{262.50000071525574, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>226</integer>
+				<key>Position</key>
+				<real>0.375</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>227</integer>
+			</dict>
+			<key>ID</key>
+			<integer>240</integer>
+			<key>Points</key>
+			<array>
+				<string>{257.5, 336.5}</string>
+				<string>{288, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>239</integer>
+			<key>Points</key>
+			<array>
+				<string>{231, 288.50000116229057}</string>
+				<string>{231, 251.25}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>238</integer>
+				<key>Position</key>
+				<real>0.56800001859664917</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>238</integer>
+			<key>Points</key>
+			<array>
+				<string>{231, 253}</string>
+				<string>{231, 315.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.112257</string>
+						<key>g</key>
+						<string>0.107007</string>
+						<key>r</key>
+						<string>0.934433</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{476, 33}, {49, 32}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>18</real>
+			</dict>
+			<key>ID</key>
+			<integer>230</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 CCS}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{243, 35}, {101, 32}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>18</real>
+			</dict>
+			<key>ID</key>
+			<integer>229</integer>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs36 \cf0 App Server}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>228</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 252}</string>
+				<string>{216, 252}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>227</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 314.5}</string>
+				<string>{216, 314.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>226</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 99}</string>
+				<string>{216, 99}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{393.69128000000001, 348.37441999999999}, {57, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>223</integer>
+			<key>Rotation</key>
+			<real>23</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 101}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{290.12054000000001, 420.17102}, {60, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>222</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 100}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>220</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 351}</string>
+				<string>{288, 463}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{430.51697000000001, 279.19488999999999}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>219</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack.. }</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{390.63733000000002, 258.42700000000002}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>218</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 2}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{290.74178999999998, 239.21059}, {57, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>217</integer>
+			<key>Rotation</key>
+			<real>23</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 100}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{342.63623000000001, 185.82861}, {38, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>216</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no...}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{361.60431, 234}, {44, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>FontInfo</key>
+			<dict>
+				<key>Font</key>
+				<string>Helvetica</string>
+				<key>Size</key>
+				<real>14</real>
+			</dict>
+			<key>ID</key>
+			<integer>209</integer>
+			<key>Rotation</key>
+			<real>341</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 ack 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{351.16005999999999, 153.43960999999999}, {42, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>172</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 2}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Bounds</key>
+			<string>{{363, 117}, {42, 27}}</string>
+			<key>Class</key>
+			<string>ShapedGraphic</string>
+			<key>FitText</key>
+			<string>YES</string>
+			<key>Flow</key>
+			<string>Resize</string>
+			<key>ID</key>
+			<integer>171</integer>
+			<key>Rotation</key>
+			<real>18</real>
+			<key>Shape</key>
+			<string>Rectangle</string>
+			<key>Style</key>
+			<dict>
+				<key>fill</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>shadow</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+				<key>stroke</key>
+				<dict>
+					<key>Draws</key>
+					<string>NO</string>
+				</dict>
+			</dict>
+			<key>Text</key>
+			<dict>
+				<key>Text</key>
+				<string>{\rtf1\ansi\ansicpg1252\cocoartf1187\cocoasubrtf400
+\cocoascreenfonts1{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
+{\colortbl;\red255\green255\blue255;}
+\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\pardirnatural\qc
+
+\f0\fs28 \cf0 no. 1}</string>
+			</dict>
+			<key>Wrap</key>
+			<string>NO</string>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>169</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 200.62189000000001}</string>
+				<string>{288, 312.62189000000001}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>168</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 241.00763000000001}</string>
+				<string>{288, 353.00763000000001}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>167</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 279}</string>
+				<string>{288, 391}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>165</integer>
+			<key>Points</key>
+			<array>
+				<string>{289, 391}</string>
+				<string>{505, 492}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>164</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 353}</string>
+				<string>{504, 454}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>163</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 313}</string>
+				<string>{504, 414}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>162</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 180}</string>
+				<string>{504, 281}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>161</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 252}</string>
+				<string>{504, 353}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>160</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 139.5}</string>
+				<string>{504, 240.5}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>Head</key>
+			<dict>
+				<key>ID</key>
+				<integer>158</integer>
+				<key>Position</key>
+				<real>0.29398149251937866</real>
+			</dict>
+			<key>ID</key>
+			<integer>159</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 98.000000596046448}</string>
+				<string>{504, 199.00000476837158}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>Color</key>
+					<dict>
+						<key>b</key>
+						<string>0.934433</string>
+						<key>g</key>
+						<string>0</string>
+						<key>r</key>
+						<string>0.122713</string>
+					</dict>
+					<key>HeadArrow</key>
+					<string>FilledArrow</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+			<key>Tail</key>
+			<dict>
+				<key>ID</key>
+				<integer>157</integer>
+				<key>Position</key>
+				<real>0.060185186564922333</real>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>158</integer>
+			<key>Points</key>
+			<array>
+				<string>{504, 72}</string>
+				<string>{504, 504}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+		<dict>
+			<key>Class</key>
+			<string>LineGraphic</string>
+			<key>ID</key>
+			<integer>157</integer>
+			<key>Points</key>
+			<array>
+				<string>{288, 72}</string>
+				<string>{288, 504}</string>
+			</array>
+			<key>Style</key>
+			<dict>
+				<key>stroke</key>
+				<dict>
+					<key>HeadArrow</key>
+					<string>0</string>
+					<key>Legacy</key>
+					<true/>
+					<key>TailArrow</key>
+					<string>0</string>
+				</dict>
+			</dict>
+		</dict>
+	</array>
+	<key>GridInfo</key>
+	<dict>
+		<key>ShowsGrid</key>
+		<string>YES</string>
+	</dict>
+	<key>GuidesLocked</key>
+	<string>NO</string>
+	<key>GuidesVisible</key>
+	<string>YES</string>
+	<key>HPages</key>
+	<integer>1</integer>
+	<key>ImageCounter</key>
+	<integer>1</integer>
+	<key>KeepToScale</key>
+	<false/>
+	<key>Layers</key>
+	<array>
+		<dict>
+			<key>Lock</key>
+			<string>NO</string>
+			<key>Name</key>
+			<string>Layer 1</string>
+			<key>Print</key>
+			<string>YES</string>
+			<key>View</key>
+			<string>YES</string>
+		</dict>
+	</array>
+	<key>LayoutInfo</key>
+	<dict>
+		<key>Animate</key>
+		<string>NO</string>
+		<key>circoMinDist</key>
+		<real>18</real>
+		<key>circoSeparation</key>
+		<real>0.0</real>
+		<key>layoutEngine</key>
+		<string>dot</string>
+		<key>neatoSeparation</key>
+		<real>0.0</real>
+		<key>twopiSeparation</key>
+		<real>0.0</real>
+	</dict>
+	<key>LinksVisible</key>
+	<string>NO</string>
+	<key>MagnetsVisible</key>
+	<string>NO</string>
+	<key>MasterSheets</key>
+	<array/>
+	<key>ModificationDate</key>
+	<string>2014-01-22 22:42:38 +0000</string>
+	<key>Modifier</key>
+	<string>Katie McCormick</string>
+	<key>NotesVisible</key>
+	<string>NO</string>
+	<key>Orientation</key>
+	<integer>2</integer>
+	<key>OriginVisible</key>
+	<string>NO</string>
+	<key>PageBreaks</key>
+	<string>YES</string>
+	<key>PrintInfo</key>
+	<dict>
+		<key>NSBottomMargin</key>
+		<array>
+			<string>float</string>
+			<string>41</string>
+		</array>
+		<key>NSHorizonalPagination</key>
+		<array>
+			<string>int</string>
+			<string>0</string>
+		</array>
+		<key>NSLeftMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+		<key>NSPaperSize</key>
+		<array>
+			<string>size</string>
+			<string>{612.00002479553223, 792}</string>
+		</array>
+		<key>NSPrintReverseOrientation</key>
+		<array>
+			<string>int</string>
+			<string>0</string>
+		</array>
+		<key>NSRightMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+		<key>NSTopMargin</key>
+		<array>
+			<string>float</string>
+			<string>18</string>
+		</array>
+	</dict>
+	<key>PrintOnePage</key>
+	<false/>
+	<key>ReadOnly</key>
+	<string>NO</string>
+	<key>RowAlign</key>
+	<integer>1</integer>
+	<key>RowSpacing</key>
+	<real>36</real>
+	<key>SheetTitle</key>
+	<string>Canvas 1</string>
+	<key>SmartAlignmentGuidesActive</key>
+	<string>YES</string>
+	<key>SmartDistanceGuidesActive</key>
+	<string>YES</string>
+	<key>UniqueID</key>
+	<integer>1</integer>
+	<key>UseEntirePage</key>
+	<false/>
+	<key>VPages</key>
+	<integer>1</integer>
+	<key>WindowInfo</key>
+	<dict>
+		<key>CurrentSheet</key>
+		<integer>0</integer>
+		<key>ExpandedCanvases</key>
+		<array>
+			<dict>
+				<key>name</key>
+				<string>Canvas 1</string>
+			</dict>
+		</array>
+		<key>Frame</key>
+		<string>{{170, 139}, {1218, 882}}</string>
+		<key>ListView</key>
+		<true/>
+		<key>OutlineWidth</key>
+		<integer>142</integer>
+		<key>RightSidebar</key>
+		<false/>
+		<key>ShowRuler</key>
+		<true/>
+		<key>Sidebar</key>
+		<true/>
+		<key>SidebarWidth</key>
+		<integer>120</integer>
+		<key>VisibleRegion</key>
+		<string>{{40.5, 0}, {534.5, 364}}</string>
+		<key>Zoom</key>
+		<real>2</real>
+		<key>ZoomValues</key>
+		<array>
+			<array>
+				<string>Canvas 1</string>
+				<real>2</real>
+				<real>1</real>
+			</array>
+		</array>
+	</dict>
+</dict>
+</plist>
diff --git a/drm/java/android/drm/DrmOutputStream.java b/drm/java/android/drm/DrmOutputStream.java
index 22e7ac2..ba1c56f 100644
--- a/drm/java/android/drm/DrmOutputStream.java
+++ b/drm/java/android/drm/DrmOutputStream.java
@@ -18,14 +18,14 @@
 
 import static android.drm.DrmConvertedStatus.STATUS_OK;
 import static android.drm.DrmManagerClient.INVALID_SESSION;
-import static libcore.io.OsConstants.SEEK_SET;
+import static android.system.OsConstants.SEEK_SET;
 
 import android.os.ParcelFileDescriptor;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Log;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoBridge;
-import libcore.io.Libcore;
 import libcore.io.Streams;
 
 import java.io.FileDescriptor;
@@ -69,7 +69,7 @@
         final DrmConvertedStatus status = mClient.closeConvertSession(mSessionId);
         if (status.statusCode == STATUS_OK) {
             try {
-                Libcore.os.lseek(mFd, status.offset, SEEK_SET);
+                Os.lseek(mFd, status.offset, SEEK_SET);
             } catch (ErrnoException e) {
                 e.rethrowAsIOException();
             }
diff --git a/graphics/java/android/graphics/Canvas.java b/graphics/java/android/graphics/Canvas.java
index 2b72b93..ae3eae1 100644
--- a/graphics/java/android/graphics/Canvas.java
+++ b/graphics/java/android/graphics/Canvas.java
@@ -168,21 +168,10 @@
     }
 
     /**
-     * Gets the native canvas pointer.
-     *
-     * @return The native pointer.
-     *
-     * @hide
-     */
-    public long getNativeCanvas() {
-        return mNativeCanvas;
-    }
-
-    /**
      * Returns null.
-     * 
+     *
      * @deprecated This method is not supported and should not be invoked.
-     * 
+     *
      * @hide
      */
     @Deprecated
@@ -233,14 +222,14 @@
 
         mBitmap = bitmap;
     }
-    
+
     /**
      * Set the viewport dimensions if this canvas is GL based. If it is not,
      * this method is ignored and no exception is thrown.
      *
      * @param width The width of the viewport
      * @param height The height of the viewport
-     * 
+     *
      * @hide
      */
     public void setViewport(int width, int height) {
@@ -389,7 +378,14 @@
                 paint != null ? paint.mNativePaint : 0,
                 saveFlags);
     }
-    
+
+    /**
+     * Convenience for saveLayer(bounds, paint, {@link #ALL_SAVE_FLAG})
+     */
+    public int saveLayer(RectF bounds, Paint paint) {
+        return saveLayer(bounds, paint, ALL_SAVE_FLAG);
+    }
+
     /**
      * Helper version of saveLayer() that takes 4 values rather than a RectF.
      */
@@ -401,6 +397,13 @@
     }
 
     /**
+     * Convenience for saveLayer(left, top, right, bottom, paint, {@link #ALL_SAVE_FLAG})
+     */
+    public int saveLayer(float left, float top, float right, float bottom, Paint paint) {
+        return saveLayer(left, top, right, bottom, paint, ALL_SAVE_FLAG);
+    }
+
+    /**
      * This behaves the same as save(), but in addition it allocates an
      * offscreen bitmap. All drawing calls are directed there, and only when
      * the balancing call to restore() is made is that offscreen transfered to
@@ -420,7 +423,14 @@
         alpha = Math.min(255, Math.max(0, alpha));
         return native_saveLayerAlpha(mNativeCanvas, bounds, alpha, saveFlags);
     }
-    
+
+    /**
+     * Convenience for saveLayerAlpha(bounds, alpha, {@link #ALL_SAVE_FLAG})
+     */
+    public int saveLayerAlpha(RectF bounds, int alpha) {
+        return saveLayerAlpha(bounds, alpha, ALL_SAVE_FLAG);
+    }
+
     /**
      * Helper for saveLayerAlpha() that takes 4 values instead of a RectF.
      */
@@ -431,6 +441,13 @@
     }
 
     /**
+     * Helper for saveLayerAlpha(left, top, right, bottom, alpha, {@link #ALL_SAVE_FLAG})
+     */
+    public int saveLayerAlpha(float left, float top, float right, float bottom, int alpha) {
+        return saveLayerAlpha(left, top, right, bottom, alpha, ALL_SAVE_FLAG);
+    }
+
+    /**
      * This call balances a previous call to save(), and is used to remove all
      * modifications to the matrix/clip state since the last save call. It is
      * an error to call restore() more times than save() was called.
@@ -1058,11 +1075,20 @@
      * @param paint The paint used to draw the roundRect
      */
     public void drawRoundRect(RectF rect, float rx, float ry, Paint paint) {
-        if (rect == null) {
-            throw new NullPointerException();
-        }
-        native_drawRoundRect(mNativeCanvas, rect, rx, ry,
-                             paint.mNativePaint);
+        drawRoundRect(rect.left, rect.top, rect.right, rect.bottom, rx, ry, paint);
+    }
+
+    /**
+     * Draw the specified round-rect using the specified paint. The roundrect
+     * will be filled or framed based on the Style in the paint.
+     *
+     * @param rx    The x-radius of the oval used to round the corners
+     * @param ry    The y-radius of the oval used to round the corners
+     * @param paint The paint used to draw the roundRect
+     */
+    public void drawRoundRect(float left, float top, float right, float bottom, float rx, float ry,
+            Paint paint) {
+        native_drawRoundRect(mNativeCanvas, left, top, right, bottom, rx, ry, paint.mNativePaint);
     }
 
     /**
@@ -1221,7 +1247,13 @@
      *                 values. If false, the alpha byte is ignored (assumed to
      *                 be 0xFF for every pixel).
      * @param paint  May be null. The paint used to draw the bitmap
+     *
+     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
+     * requires an internal copy of color buffer contents every time this method is called. Using a
+     * Bitmap avoids this copy, and allows the application to more explicitly control the lifetime
+     * and copies of pixel data.
      */
+    @Deprecated
     public void drawBitmap(int[] colors, int offset, int stride, float x, float y,
             int width, int height, boolean hasAlpha, Paint paint) {
         // check for valid input
@@ -1248,16 +1280,23 @@
         native_drawBitmap(mNativeCanvas, colors, offset, stride, x, y, width, height, hasAlpha,
                 paint != null ? paint.mNativePaint : 0);
     }
-    
-    /** Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y
+
+    /**
+     * Legacy version of drawBitmap(int[] colors, ...) that took ints for x,y
+     *
+     * @deprecated Usage with a {@link #isHardwareAccelerated() hardware accelerated} canvas
+     * requires an internal copy of color buffer contents every time this method is called. Using a
+     * Bitmap avoids this copy, and allows the application to more explicitly control the lifetime
+     * and copies of pixel data.
      */
+    @Deprecated
     public void drawBitmap(int[] colors, int offset, int stride, int x, int y,
             int width, int height, boolean hasAlpha, Paint paint) {
         // call through to the common float version
         drawBitmap(colors, offset, stride, (float)x, (float)y, width, height,
                    hasAlpha, paint);
     }
-        
+
     /**
      * Draw the bitmap using the specified matrix.
      *
@@ -1786,8 +1825,8 @@
                                               boolean useCenter,
                                               long nativePaint);
     private static native void native_drawRoundRect(long nativeCanvas,
-                                                    RectF rect, float rx,
-                                                    float ry, long nativePaint);
+            float left, float top, float right, float bottom,
+            float rx, float ry, long nativePaint);
     private static native void native_drawPath(long nativeCanvas,
                                                long nativePath,
                                                long nativePaint);
diff --git a/graphics/java/android/graphics/Outline.java b/graphics/java/android/graphics/Outline.java
index 4ea7ec7..b5c0801 100644
--- a/graphics/java/android/graphics/Outline.java
+++ b/graphics/java/android/graphics/Outline.java
@@ -16,18 +16,21 @@
 
 package android.graphics;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.graphics.drawable.Drawable;
 import android.view.View;
 
 /**
- * Defines an area of content.
+ * Defines a simple shape, used for bounding graphical regions.
  *
- * Can be used with a View or Drawable to drive the shape of shadows cast by a
- * View, and allowing Views to clip inner content.
+ * Can be used with a View, or computed by a Drawable, to drive the shape of shadows cast by a
+ * View.
  *
  * @see View#setOutline(Outline)
- * @see View#setClipToOutline(boolean)
+ * @see Drawable#getOutline(Outline)
  */
-public class Outline {
+public final class Outline {
     /** @hide */
     public Rect mRect;
 
@@ -44,46 +47,74 @@
     public Outline() {}
 
     /**
+     * Constructs an Outline with a copy of the data in src.
+     */
+    public Outline(@Nullable Outline src) {
+        set(src);
+    }
+
+    /** @hide */
+    public void markInvalid() {
+        mRadius = 0;
+        mRect = null;
+        mPath = null;
+    }
+
+    /**
      * Returns whether the Outline is valid for use with a View.
      * <p>
      * Outlines are invalid when constructed until a setter method is called.
      */
-    public final boolean isValid() {
+    public boolean isValid() {
         return mRect != null || mPath != null;
     }
 
     /**
-     * @hide
-     */
-    public final boolean canClip() {
-        return mPath == null;
-    }
-
-    /**
      * Replace the contents of this Outline with the contents of src.
+     *
+     * @param src Source outline to copy from.
      */
-    public void set(Outline src) {
-        if (src.mPath != null) {
-            if (mPath == null) {
-                mPath = new Path();
-            }
-            mPath.set(src.mPath);
+    public void set(@Nullable Outline src) {
+        if (src == null) {
+            mRadius = 0;
             mRect = null;
-        }
-        if (src.mRect != null) {
-            if (mRect == null) {
-                mRect = new Rect();
+            mPath = null;
+        } else {
+            if (src.mPath != null) {
+                if (mPath == null) {
+                    mPath = new Path();
+                }
+                mPath.set(src.mPath);
+                mRect = null;
             }
-            mRect.set(src.mRect);
+            if (src.mRect != null) {
+                if (mRect == null) {
+                    mRect = new Rect();
+                }
+                mRect.set(src.mRect);
+            }
+            mRadius = src.mRadius;
         }
-        mRadius = src.mRadius;
     }
 
     /**
      * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
-     * <p>
-     * Outlines produced by this method support
-     * {@link View#setClipToOutline(boolean) View clipping.}
+     */
+    public void setRect(int left, int top, int right, int bottom) {
+        setRoundRect(left, top, right, bottom, 0.0f);
+    }
+
+    /**
+     * Convenience for {@link #setRect(int, int, int, int)}
+     */
+    public void setRect(@NonNull Rect rect) {
+        setRect(rect.left, rect.top, rect.right, rect.bottom);
+    }
+
+    /**
+     * Sets the Outline to the rounded rect defined by the input rect, and corner radius.
+     *
+     * Passing a zero radius is equivalent to calling {@link #setRect(int, int, int, int)}
      */
     public void setRoundRect(int left, int top, int right, int bottom, float radius) {
         if (mRect == null) mRect = new Rect();
@@ -93,11 +124,33 @@
     }
 
     /**
-     * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
-     *
-     * @hide
+     * Convenience for {@link #setRoundRect(int, int, int, int, float)}
      */
-    public void setConvexPath(Path convexPath) {
+    public void setRoundRect(@NonNull Rect rect, float radius) {
+        setRoundRect(rect.left, rect.top, rect.right, rect.bottom, radius);
+    }
+
+    /**
+     * Sets the outline to the oval defined by input rect.
+     */
+    public void setOval(int left, int top, int right, int bottom) {
+        mRect = null;
+        if (mPath == null) mPath = new Path();
+        mPath.reset();
+        mPath.addOval(left, top, right, bottom, Path.Direction.CW);
+    }
+
+    /**
+     * Convenience for {@link #setOval(int, int, int, int)}
+     */
+    public void setOval(@NonNull Rect rect) {
+        setOval(rect.left, rect.top, rect.right, rect.bottom);
+    }
+
+    /**
+     * Sets the Constructs an Outline from a {@link android.graphics.Path#isConvex() convex path}.
+     */
+    public void setConvexPath(@NonNull Path convexPath) {
         if (!convexPath.isConvex()) {
             throw new IllegalArgumentException("path must be convex");
         }
diff --git a/graphics/java/android/graphics/Paint.java b/graphics/java/android/graphics/Paint.java
index 916cb5a..1e1128e 100644
--- a/graphics/java/android/graphics/Paint.java
+++ b/graphics/java/android/graphics/Paint.java
@@ -500,6 +500,7 @@
 
         mBidiFlags = BIDI_DEFAULT_LTR;
         setTextLocale(Locale.getDefault());
+        setElegantTextHeight(false);
     }
     
     /**
@@ -1221,6 +1222,22 @@
     }
 
     /**
+     * Get the elegant metrics flag.
+     *
+     * @return true if elegant metrics are enabled for text drawing.
+     */
+    public native boolean isElegantTextHeight();
+
+    /**
+     * Set the paint's elegant height metrics flag. This setting selects font
+     * variants that have not been compacted to fit Latin-based vertical
+     * metrics, and also increases top and bottom bounds to provide more space.
+     *
+     * @param elegant set the paint's elegant metrics flag for drawing text.
+     */
+    public native void setElegantTextHeight(boolean elegant);
+
+    /**
      * Return the paint's text size.
      *
      * @return the paint's text size.
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index c07a6da..c600f47 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -499,11 +499,7 @@
      * @param dir  The direction to wind the rectangle's contour
      */
     public void addRect(RectF rect, Direction dir) {
-        if (rect == null) {
-            throw new NullPointerException("need rect parameter");
-        }
-        detectSimplePath(rect.left, rect.top, rect.right, rect.bottom, dir);
-        native_addRect(mNativePath, rect, dir.nativeInt);
+        addRect(rect.left, rect.top, rect.right, rect.bottom, dir);
     }
 
     /**
@@ -527,11 +523,17 @@
      * @param dir  The direction to wind the oval's contour
      */
     public void addOval(RectF oval, Direction dir) {
-        if (oval == null) {
-            throw new NullPointerException("need oval parameter");
-        }
+        addOval(oval.left, oval.top, oval.right, oval.bottom, dir);
+    }
+
+    /**
+     * Add a closed oval contour to the path
+     *
+     * @param dir The direction to wind the oval's contour
+     */
+    public void addOval(float left, float top, float right, float bottom, Direction dir) {
         isSimplePath = false;
-        native_addOval(mNativePath, oval, dir.nativeInt);
+        native_addOval(mNativePath, left, top, right, bottom, dir.nativeInt);
     }
 
     /**
@@ -756,10 +758,10 @@
     private static native void native_arcTo(long nPath, RectF oval,
                     float startAngle, float sweepAngle, boolean forceMoveTo);
     private static native void native_close(long nPath);
-    private static native void native_addRect(long nPath, RectF rect, int dir);
     private static native void native_addRect(long nPath, float left, float top,
                                             float right, float bottom, int dir);
-    private static native void native_addOval(long nPath, RectF oval, int dir);
+    private static native void native_addOval(long nPath, float left, float top,
+            float right, float bottom, int dir);
     private static native void native_addCircle(long nPath, float x, float y, float radius, int dir);
     private static native void native_addArc(long nPath, RectF oval,
                                             float startAngle, float sweepAngle);
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 66a88a2..60b4615 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -484,6 +484,15 @@
             copyBounds(mDstRect);
         }
 
+        final int restoreAlpha;
+        if (state.mBaseAlpha != 1.0f) {
+            final Paint p = getPaint();
+            restoreAlpha = p.getAlpha();
+            p.setAlpha((int) (restoreAlpha * state.mBaseAlpha + 0.5f));
+        } else {
+            restoreAlpha = -1;
+        }
+
         final boolean clearColorFilter;
         if (mTintFilter != null && paint.getColorFilter() == null) {
             paint.setColorFilter(mTintFilter);
@@ -537,6 +546,10 @@
         if (clearColorFilter) {
             paint.setColorFilter(null);
         }
+
+        if (restoreAlpha >= 0) {
+            paint.setAlpha(restoreAlpha);
+        }
     }
 
     @Override
@@ -762,6 +775,10 @@
             paint.setDither(dither);
         }
 
+        if (themeAttrs == null || themeAttrs[R.styleable.BitmapDrawable_alpha] == 0) {
+            state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, 1.0f);
+        }
+
         if (themeAttrs == null || themeAttrs[R.styleable.BitmapDrawable_gravity] == 0) {
             final int gravity = a.getInt(
                     R.styleable.BitmapDrawable_gravity, Gravity.FILL);
@@ -818,6 +835,10 @@
             paint.setDither(dither);
         }
 
+        if (a.hasValue(R.styleable.BitmapDrawable_alpha)) {
+            state.mBaseAlpha = a.getFloat(R.styleable.BitmapDrawable_alpha, state.mBaseAlpha);
+        }
+
         if (a.hasValue(R.styleable.BitmapDrawable_gravity)) {
             final int gravity = a.getInt(
                     R.styleable.BitmapDrawable_gravity, Gravity.FILL);
@@ -933,6 +954,7 @@
         int[] mThemeAttrs;
         int mChangingConfigurations;
         int mGravity = Gravity.FILL;
+        float mBaseAlpha = 1.0f;
         Paint mPaint = new Paint(DEFAULT_PAINT_FLAGS);
         Shader.TileMode mTileModeX = null;
         Shader.TileMode mTileModeY = null;
@@ -954,6 +976,7 @@
             mTileModeX = bitmapState.mTileModeX;
             mTileModeY = bitmapState.mTileModeY;
             mTargetDensity = bitmapState.mTargetDensity;
+            mBaseAlpha = bitmapState.mBaseAlpha;
             mPaint = new Paint(bitmapState.mPaint);
             mRebuildShader = bitmapState.mRebuildShader;
             mAutoMirrored = bitmapState.mAutoMirrored;
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 21cd5db..b9d5e19 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -518,9 +518,16 @@
     public void removeHotspot(int key) {}
 
     /**
-     * Removes all hotspots from the drawable.
+     * Immediately removes all hotspots from the drawable.
      */
     public void clearHotspots() {}
+    
+    /**
+     * Sets the bounds to which hotspots are constrained.
+     *
+     * @hide until we finalize these APIs
+     */
+    public void setHotspotBounds(int left, int top, int right, int bottom) {}
 
     /**
      * Whether this drawable requests projection.
@@ -857,22 +864,21 @@
     }
 
     /**
-     * Returns the outline for this drawable if defined, null if not.
+     * Called to get the drawable to populate the Outline.
      * <p>
-     * This method will be called by a View on its background Drawable after
-     * bounds change, if the View's Outline isn't set explicitly. This allows
-     * the background Drawable to provide the shape of the shadow casting
-     * portion of the View. It can also serve to clip the area of the View if
-     * if {@link View#setClipToOutline(boolean)} is set on the View.
-     * <p>
-     * The Outline queried by the View will not be modified, and is treated as
-     * a static shape that only needs to be requeried when the drawable's bounds
-     * change.
+     * This method will be called by a View on its background Drawable after bounds change, or its
+     * Drawable is invalidated, if the View's Outline isn't set explicitly. This allows the
+     * background Drawable to define the shape of the shadow cast by the View.
      *
-     * @see View#setOutline(android.view.Outline)
-     * @see View#setClipToOutline(boolean)
+     * The default behavior defines the outline to be the bounding rectangle. Subclasses that wish
+     * to convey a different shape must override this method.
+     *
+     * @see View#setOutline(android.graphics.Outline)
      */
-    public Outline getOutline() { return null; }
+    public boolean getOutline(Outline outline) {
+        outline.setRect(getBounds());
+        return true;
+    }
 
     /**
      * Make this drawable mutable. This operation cannot be reversed. A mutable
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index 05df3bc..1f8b51d 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -238,6 +238,35 @@
     }
 
     @Override
+    public void setHotspot(int key, float x, float y) {
+        if (mCurrDrawable != null) {
+            mCurrDrawable.setHotspot(key, x, y);
+        }
+    }
+
+    @Override
+    public void removeHotspot(int key) {
+        if (mCurrDrawable != null) {
+            mCurrDrawable.removeHotspot(key);
+        }
+    }
+
+    @Override
+    public void clearHotspots() {
+        if (mCurrDrawable != null) {
+            mCurrDrawable.clearHotspots();
+        }
+    }
+
+    @Override
+    public boolean supportsHotspots() {
+        if (mCurrDrawable != null) {
+            return mCurrDrawable.supportsHotspots();
+        }
+        return false;
+    }
+
+    @Override
     protected boolean onStateChange(int[] state) {
         if (mLastDrawable != null) {
             return mLastDrawable.setState(state);
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 1b5cefe..dc06350 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -139,8 +139,7 @@
 
     private final Path mPath = new Path();
     private final RectF mRect = new RectF();
-    private Outline mOutline;
-    
+
     private Paint mLayerPaint;    // internal, used if we use saveLayer()
     private boolean mRectIsDirty;   // internal state
     private boolean mMutated;
@@ -573,15 +572,11 @@
                 mStrokePaint.setColorFilter(mColorFilter);
             }
         }
-        
+
         switch (st.mShape) {
             case RECTANGLE:
                 if (st.mRadiusArray != null) {
-                    if (mPathIsDirty || mRectIsDirty) {
-                        mPath.reset();
-                        mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
-                        mPathIsDirty = mRectIsDirty = false;
-                    }
+                    buildPathIfDirty();
                     canvas.drawPath(mPath, mFillPaint);
                     if (haveStroke) {
                         canvas.drawPath(mPath, mStrokePaint);
@@ -638,7 +633,16 @@
             }
         }
     }
-    
+
+    private void buildPathIfDirty() {
+        final GradientState st = mGradientState;
+        if (mPathIsDirty || mRectIsDirty) {
+            mPath.reset();
+            mPath.addRoundRect(mRect, st.mRadiusArray, Path.Direction.CW);
+            mPathIsDirty = mRectIsDirty = false;
+        }
+    }
+
     private Path buildRing(GradientState st) {
         if (mRingPath != null && (!st.mUseLevelForShape || !mPathIsDirty)) return mRingPath;
         mPathIsDirty = false;
@@ -862,7 +866,7 @@
                 float x0, x1, y0, y1;
 
                 if (st.mGradient == LINEAR_GRADIENT) {
-                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;                    
+                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
                     switch (st.mOrientation) {
                     case TOP_BOTTOM:
                         x0 = r.left;            y0 = r.top;
@@ -1428,42 +1432,40 @@
     }
 
     @Override
-    public Outline getOutline() {
+    public boolean getOutline(Outline outline) {
         final GradientState st = mGradientState;
         final Rect bounds = getBounds();
 
         switch (st.mShape) {
             case RECTANGLE:
                 if (st.mRadiusArray != null) {
-                    return null;
+                    buildPathIfDirty();
+                    outline.setConvexPath(mPath);
+                    return true;
                 }
+
                 float rad = 0;
                 if (st.mRadius > 0.0f) {
                     // clamp the radius based on width & height, matching behavior in draw()
                     rad = Math.min(st.mRadius,
                             Math.min(bounds.width(), bounds.height()) * 0.5f);
                 }
-                if (mOutline == null) {
-                    mOutline = new Outline();
-                }
-                mOutline.setRoundRect(bounds.left, bounds.top,
-                        bounds.right, bounds.bottom, rad);
-                return mOutline;
-            case LINE: {
+                outline.setRoundRect(bounds, rad);
+                return true;
+            case OVAL:
+                outline.setOval(bounds);
+                return true;
+            case LINE:
                 float halfStrokeWidth = mStrokePaint.getStrokeWidth() * 0.5f;
                 float centerY = bounds.centerY();
                 int top = (int) Math.floor(centerY - halfStrokeWidth);
                 int bottom = (int) Math.ceil(centerY + halfStrokeWidth);
 
-                if (mOutline == null) {
-                    mOutline = new Outline();
-                }
-                mOutline.setRoundRect(bounds.left, top, bounds.right, bottom, 0);
-                return mOutline;
-            }
+                outline.setRect(bounds.left, top, bounds.right, bottom);
+                return true;
             default:
                 // TODO: investigate
-                return null;
+                return false;
         }
     }
 
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index b366987..639d719 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -290,6 +290,26 @@
 
         return false;
     }
+    
+    /**
+     * @hide
+     */
+    @Override
+    public boolean isProjected() {
+        if (super.isProjected()) {
+            return true;
+        }
+
+        final ChildDrawable[] layers = mLayerState.mChildren;
+        final int N = mLayerState.mNum;
+        for (int i = 0; i < N; i++) {
+            if (layers[i].mDrawable.isProjected()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 
     /**
      * Add a new layer to this drawable. The new layer is identified by an id.
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 3e9ca0a..21992ce 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -241,6 +241,15 @@
             canvas.scale(-1.0f, 1.0f);
         }
 
+        final int restoreAlpha;
+        if (mNinePatchState.mBaseAlpha != 1.0f) {
+            final Paint p = getPaint();
+            restoreAlpha = p.getAlpha();
+            p.setAlpha((int) (restoreAlpha * mNinePatchState.mBaseAlpha + 0.5f));
+        } else {
+            restoreAlpha = -1;
+        }
+
         mNinePatch.draw(canvas, bounds, mPaint);
 
         if (needsMirroring) {
@@ -250,6 +259,10 @@
         if (clearColorFilter) {
             mPaint.setColorFilter(null);
         }
+
+        if (restoreAlpha >= 0) {
+            mPaint.setAlpha(restoreAlpha);
+        }
     }
 
     @Override
@@ -491,6 +504,10 @@
             }
         }
 
+        if (themeAttrs == null || themeAttrs[R.styleable.NinePatchDrawable_alpha] == 0) {
+            ninePatchState.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, 1.0f);
+        }
+
         // Apply the constant state to the paint.
         initializeWithState(ninePatchState, r);
 
@@ -584,6 +601,10 @@
             }
         }
 
+        if (a.hasValue(R.styleable.NinePatchDrawable_alpha)) {
+            state.mBaseAlpha = a.getFloat(R.styleable.NinePatchDrawable_alpha, 1.0f);
+        }
+
         // Apply the constant state to the paint.
         initializeWithState(state, r);
 
@@ -689,12 +710,13 @@
         Mode mTintMode = Mode.SRC_IN;
         Rect mPadding;
         Insets mOpticalInsets;
+        float mBaseAlpha = 1.0f;
         boolean mDither;
         int[] mThemeAttrs;
         int mChangingConfigurations;
         int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
         boolean mAutoMirrored;
-        
+
         NinePatchState() {
             // Empty constructor.
         }
@@ -726,6 +748,7 @@
             mThemeAttrs = state.mThemeAttrs;
             mPadding = state.mPadding;
             mOpticalInsets = state.mOpticalInsets;
+            mBaseAlpha = state.mBaseAlpha;
             mDither = state.mDither;
             mChangingConfigurations = state.mChangingConfigurations;
             mTargetDensity = state.mTargetDensity;
diff --git a/graphics/java/android/graphics/drawable/Ripple.java b/graphics/java/android/graphics/drawable/Ripple.java
index 03dd841..e3f57e9 100644
--- a/graphics/java/android/graphics/drawable/Ripple.java
+++ b/graphics/java/android/graphics/drawable/Ripple.java
@@ -62,27 +62,31 @@
 
     /** Whether the center is within the parent bounds. */
     private boolean mInside;
+
+    /** Whether to pulse this ripple. */
+    boolean mPulse;
     
     /** Enter state. A value in [0...1] or -1 if not set. */
-    private float mEnterState = -1;
+    float mEnterState = -1;
 
     /** Exit state. A value in [0...1] or -1 if not set. */
-    private float mExitState = -1;
+    float mExitState = -1;
 
     /** Outside state. A value in [0...1] or -1 if not set. */
-    private float mOutsideState = -1;
+    float mOutsideState = -1;
 
     /** Pulse state. A value in [0...1] or -1 if not set. */
-    private float mPulseState = -1;
+    float mPulseState = -1;
 
     /**
      * Creates a new ripple with the specified parent bounds, padding, initial
      * position, and screen density.
      */
-    public Ripple(Rect bounds, Rect padding, float x, float y, float density) {
+    public Ripple(Rect bounds, Rect padding, float x, float y, float density, boolean pulse) {
         mBounds = bounds;
         mPadding = padding;
         mInside = mBounds.contains((int) x, (int) y);
+        mPulse = pulse;
 
         mX = x;
         mY = y;
@@ -115,6 +119,16 @@
         }
     }
 
+    public void onBoundsChanged() {
+        final boolean inside = mBounds.contains((int) mX, (int) mY);
+        if (mInside != inside) {
+            if (mAnimator != null) {
+                mAnimator.outside();
+            }
+            mInside = inside;
+        }
+    }
+
     public RippleAnimator animate() {
         if (mAnimator == null) {
             mAnimator = new RippleAnimator(this);
@@ -125,8 +139,8 @@
     public boolean draw(Canvas c, Paint p) {
         final Rect bounds = mBounds;
         final Rect padding = mPadding;
-        final float dX = Math.max(mX, bounds.right - mX);
-        final float dY = Math.max(mY, bounds.bottom - mY);
+        final float dX = Math.max(mX - bounds.left, bounds.right - mX);
+        final float dY = Math.max(mY - bounds.top, bounds.bottom - mY);
         final int maxRadius = (int) Math.ceil(Math.sqrt(dX * dX + dY * dY));
 
         final float enterState = mEnterState;
@@ -308,9 +322,11 @@
                     MathUtils.constrain((currentTime - mOutsideTime) / (float) OUTSIDE_DURATION, 0, 1));
 
             // Pulse is a little more complicated.
-            final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
-            mTarget.mPulseState = pulseTime < 0 ? -1
-                    : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+            if (mTarget.mPulse) {
+                final long pulseTime = (currentTime - mEnterTime - ENTER_DURATION - PULSE_DELAY);
+                mTarget.mPulseState = pulseTime < 0 ? -1
+                        : (pulseTime % (PULSE_INTERVAL + PULSE_DURATION)) / (float) PULSE_DURATION;
+            }
         }
     }
 }
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 96309f9..61b1b85 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -21,6 +21,7 @@
 import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff.Mode;
@@ -496,6 +497,16 @@
     }
 
     @Override
+    public boolean getOutline(Outline outline) {
+        if (mShapeState.mShape == null) {
+            // don't publish outline without a shape
+            return false;
+        }
+
+        return mShapeState.mShape.getOutline(outline);
+    }
+
+    @Override
     public ConstantState getConstantState() {
         mShapeState.mChangingConfigurations = getChangingConfigurations();
         return mShapeState;
diff --git a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
index 2810c43..0e8831f 100644
--- a/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
+++ b/graphics/java/android/graphics/drawable/TouchFeedbackDrawable.java
@@ -25,12 +25,13 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.PorterDuff.Mode;
-import android.graphics.drawable.Ripple.RippleAnimator;
 import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
+import android.graphics.drawable.Ripple.RippleAnimator;
 import android.os.SystemClock;
 import android.util.AttributeSet;
 import android.util.DisplayMetrics;
+import android.util.Log;
 import android.util.SparseArray;
 
 import com.android.internal.R;
@@ -39,13 +40,15 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.IOException;
+import java.util.Arrays;
 
 /**
  * Documentation pending.
  */
 public class TouchFeedbackDrawable extends LayerDrawable {
-    private static final PorterDuffXfermode DST_ATOP = new PorterDuffXfermode(Mode.DST_ATOP);
+    private static final String LOG_TAG = TouchFeedbackDrawable.class.getSimpleName();
     private static final PorterDuffXfermode DST_IN = new PorterDuffXfermode(Mode.DST_IN);
+    private static final PorterDuffXfermode SRC_OVER = new PorterDuffXfermode(Mode.SRC_OVER);
 
     /** The maximum number of ripples supported. */
     private static final int MAX_RIPPLES = 10;
@@ -53,6 +56,9 @@
     private final Rect mTempRect = new Rect();
     private final Rect mPaddingRect = new Rect();
 
+    /** Current ripple effect bounds, used to constrain ripple effects. */
+    private final Rect mHotspotBounds = new Rect();
+
     /** Current drawing bounds, used to compute dirty region. */
     private final Rect mDrawingBounds = new Rect();
 
@@ -83,6 +89,9 @@
     /** Whether the animation runnable has been posted. */
     private boolean mAnimating;
 
+    /** Whether bounds are being overridden. */
+    private boolean mOverrideBounds;
+
     TouchFeedbackDrawable() {
         this(new TouchFeedbackState(null, null, null), null, null);
     }
@@ -97,6 +106,26 @@
     protected boolean onStateChange(int[] stateSet) {
         super.onStateChange(stateSet);
 
+        // TODO: Implicitly tie states to ripple IDs. For now, just clear
+        // focused and pressed if they aren't in the state set.
+        boolean hasFocused = false;
+        boolean hasPressed = false;
+        for (int i = 0; i < stateSet.length; i++) {
+            if (stateSet[i] == R.attr.state_pressed) {
+                hasPressed = true;
+            } else if (stateSet[i] == R.attr.state_focused) {
+                hasFocused = true;
+            }
+        }
+
+        if (!hasPressed) {
+            removeHotspot(R.attr.state_pressed);
+        }
+
+        if (!hasFocused) {
+            removeHotspot(R.attr.state_focused);
+        }
+
         if (mRipplePaint != null && mState.mTint != null) {
             final ColorStateList stateList = mState.mTint;
             final int newColor = stateList.getColorForState(stateSet, 0);
@@ -111,6 +140,47 @@
         return false;
     }
 
+    @Override
+    protected void onBoundsChange(Rect bounds) {
+        super.onBoundsChange(bounds);
+
+        if (!mOverrideBounds) {
+            mHotspotBounds.set(bounds);
+        }
+
+        onHotspotBoundsChange();
+    }
+
+    private void onHotspotBoundsChange() {
+        final int x = mHotspotBounds.centerX();
+        final int y = mHotspotBounds.centerY();
+        final int N = mActiveRipplesCount;
+        for (int i = 0; i < N; i++) {
+            if (mState.mPinned) {
+                mActiveRipples[i].move(x, y);
+            }
+            mActiveRipples[i].onBoundsChanged();
+        }
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        if (!visible) {
+            if (mTouchedRipples != null) {
+                mTouchedRipples.clear();
+            }
+
+            if (mActiveRipplesCount > 0) {
+                Arrays.fill(mActiveRipples, null);
+                mActiveRipplesCount = 0;
+                mAnimating = false;
+                unscheduleSelf(mAnimationRunnable);
+            }
+        }
+
+        return super.setVisible(visible, restart);
+    }
+
     /**
      * @hide
      */
@@ -153,10 +223,8 @@
      * @param tintMode A Porter-Duff blending mode
      */
     public void setTintMode(Mode tintMode) {
-        if (mState.mTintMode != tintMode) {
-            mState.mTintMode = tintMode;
-            invalidateSelf();
-        }
+        mState.setTintMode(tintMode);
+        invalidateSelf();
     }
 
     @Override
@@ -170,6 +238,27 @@
         super.inflate(r, parser, attrs, theme);
 
         setTargetDensity(r.getDisplayMetrics());
+
+        // Find the mask
+        final int N = getNumberOfLayers();
+        for (int i = 0; i < N; i++) {
+            if (mLayerState.mChildren[i].mId == R.id.mask) {
+                mState.mMask = mLayerState.mChildren[i].mDrawable;
+            }
+        }
+    }
+
+    @Override
+    public boolean setDrawableByLayerId(int id, Drawable drawable) {
+        if (super.setDrawableByLayerId(id, drawable)) {
+            if (id == R.id.mask) {
+                mState.mMask = drawable;
+            }
+
+            return true;
+        }
+
+        return false;
     }
 
     /**
@@ -187,8 +276,8 @@
         }
 
         if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_tintMode] == 0) {
-            mState.mTintMode = Drawable.parseTintMode(
-                    a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP);
+            mState.setTintMode(Drawable.parseTintMode(
+                    a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP));
         }
 
         if (themeAttrs == null || themeAttrs[R.styleable.TouchFeedbackDrawable_pinned] == 0) {
@@ -238,8 +327,8 @@
         }
 
         if (a.hasValue(R.styleable.TouchFeedbackDrawable_tintMode)) {
-            mState.mTintMode = Drawable.parseTintMode(
-                    a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP);
+            mState.setTintMode(Drawable.parseTintMode(
+                    a.getInt(R.styleable.TouchFeedbackDrawable_tintMode, -1), Mode.SRC_ATOP));
         }
 
         if (a.hasValue(R.styleable.TouchFeedbackDrawable_pinned)) {
@@ -264,23 +353,35 @@
             mActiveRipples = new Ripple[MAX_RIPPLES];
         }
 
+        if (mActiveRipplesCount >= MAX_RIPPLES) {
+            Log.e(LOG_TAG, "Max ripple count exceeded", new RuntimeException());
+            return;
+        }
+
         final Ripple ripple = mTouchedRipples.get(id);
         if (ripple == null) {
-            final Rect bounds = getBounds();
             final Rect padding = mPaddingRect;
             getPadding(padding);
 
+            final Rect bounds = mHotspotBounds;
             if (mState.mPinned) {
                 x = bounds.exactCenterX();
                 y = bounds.exactCenterY();
             }
 
-            final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity);
+            // TODO: Clean this up in the API.
+            final boolean pulse = (id != R.attr.state_focused);
+            final Ripple newRipple = new Ripple(bounds, padding, x, y, mDensity, pulse);
             newRipple.animate().enter();
 
             mActiveRipples[mActiveRipplesCount++] = newRipple;
             mTouchedRipples.put(id, newRipple);
-        } else if (!mState.mPinned) {
+        } else if (mState.mPinned) {
+            final Rect bounds = mHotspotBounds;
+            x = bounds.exactCenterX();
+            y = bounds.exactCenterY();
+            ripple.move(x, y);
+        } else {
             ripple.move(x, y);
         }
 
@@ -310,6 +411,7 @@
 
         final int n = mTouchedRipples.size();
         for (int i = 0; i < n; i++) {
+            // TODO: Use a fast exit, maybe just fade out?
             mTouchedRipples.valueAt(i).animate().exit();
         }
 
@@ -320,6 +422,16 @@
     }
 
     /**
+     * @hide
+     */
+    @Override
+    public void setHotspotBounds(int left, int top, int right, int bottom) {
+        mOverrideBounds = true;
+        mHotspotBounds.set(left, top, right, bottom);
+        onHotspotBoundsChange();
+    }
+
+    /**
      * Schedules the next animation, if necessary.
      */
     private void scheduleAnimation() {
@@ -345,99 +457,144 @@
 
     @Override
     public void draw(Canvas canvas) {
-        final boolean projected = getNumberOfLayers() == 0;
-        final Ripple[] activeRipples = mActiveRipples;
-        final int ripplesCount = mActiveRipplesCount;
+        final int N = mLayerState.mNum;
         final Rect bounds = getBounds();
+        final ChildDrawable[] array = mLayerState.mChildren;
+        final boolean maskOnly = mState.mMask != null && N == 1;
+
+        int restoreToCount = drawRippleLayer(canvas, bounds, maskOnly);
+
+        if (restoreToCount >= 0) { 
+            // We have a ripple layer that contains ripples. If we also have an
+            // explicit mask drawable, apply it now using DST_IN blending.
+            if (mState.mMask != null) {
+                canvas.saveLayer(bounds.left, bounds.top, bounds.right,
+                        bounds.bottom, getMaskingPaint(DST_IN));
+                mState.mMask.draw(canvas);
+                canvas.restoreToCount(restoreToCount);
+                restoreToCount = -1;
+            }
+
+            // If there's more content, we need an extra masking layer to merge
+            // the ripples over the content.
+            if (!maskOnly) {
+                final PorterDuffXfermode xfermode = mState.getTintXfermodeInverse();
+                final int count = canvas.saveLayer(bounds.left, bounds.top,
+                        bounds.right, bounds.bottom, getMaskingPaint(xfermode));
+                if (restoreToCount < 0) {
+                    restoreToCount = count;
+                }
+            }
+        }
+
+        // Draw everything except the mask.
+        for (int i = 0; i < N; i++) {
+            if (array[i].mId != R.id.mask) {
+                array[i].mDrawable.draw(canvas);
+            }
+        }
+
+        // Composite the layers if needed.
+        if (restoreToCount >= 0) {
+            canvas.restoreToCount(restoreToCount);
+        }
+    }
+
+    private int drawRippleLayer(Canvas canvas, Rect bounds, boolean maskOnly) {
+        final int ripplesCount = mActiveRipplesCount;
+        if (ripplesCount == 0) {
+            return -1;
+        }
+
+        final Ripple[] activeRipples = mActiveRipples;
+        final boolean projected = isProjected();
+        final Rect layerBounds = projected ? getDirtyBounds() : bounds;
+
+        // Separate the ripple color and alpha channel. The alpha will be
+        // applied when we merge the ripples down to the canvas.
+        final int rippleColor;
+        if (mState.mTint != null) {
+            rippleColor = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
+        } else {
+            rippleColor = Color.TRANSPARENT;
+        }
+        final int rippleAlpha = Color.alpha(rippleColor);
+
+        if (mRipplePaint == null) {
+            mRipplePaint = new Paint();
+            mRipplePaint.setAntiAlias(true);
+        }
+        final Paint ripplePaint = mRipplePaint;
+        ripplePaint.setColor(rippleColor);
+
+        boolean drewRipples = false;
+        int restoreToCount = -1;
+        int activeRipplesCount = 0;
 
         // Draw ripples.
-        boolean drewRipples = false;
-        int rippleRestoreCount = -1;
-        int activeRipplesCount = 0;
         for (int i = 0; i < ripplesCount; i++) {
             final Ripple ripple = activeRipples[i];
             final RippleAnimator animator = ripple.animate();
             animator.update();
+
+            // Mark and skip inactive ripples.
             if (!animator.isRunning()) {
                 activeRipples[i] = null;
-            } else {
-                // If we're masking the ripple layer, make sure we have a layer
-                // first. This will merge SRC_OVER (directly) onto the canvas.
-                if (!projected && rippleRestoreCount < 0) {
-                    rippleRestoreCount = canvas.saveLayer(bounds.left, bounds.top,
-                            bounds.right, bounds.bottom, null, 0);
-                    canvas.clipRect(bounds);
+                continue;
+            }
+
+            // If we're masking the ripple layer, make sure we have a layer
+            // first. This will merge SRC_OVER (directly) onto the canvas.
+            if (restoreToCount < 0) {
+                // If we're projecting or we only have a mask, we want to treat the
+                // underlying canvas as our content and merge the ripple layer down
+                // using the tint xfermode.
+                final PorterDuffXfermode xfermode;
+                if (projected || maskOnly) {
+                    xfermode = mState.getTintXfermode();
+                } else {
+                    xfermode = SRC_OVER;
                 }
 
-                drewRipples |= ripple.draw(canvas, getRipplePaint());
-
-                activeRipples[activeRipplesCount] = activeRipples[i];
-                activeRipplesCount++;
+                final Paint layerPaint = getMaskingPaint(xfermode);
+                layerPaint.setAlpha(rippleAlpha);
+                restoreToCount = canvas.saveLayer(layerBounds.left, layerBounds.top,
+                        layerBounds.right, layerBounds.bottom, layerPaint);
+                layerPaint.setAlpha(255);
             }
+
+            drewRipples |= ripple.draw(canvas, ripplePaint);
+
+            activeRipples[activeRipplesCount] = activeRipples[i];
+            activeRipplesCount++;
         }
+
         mActiveRipplesCount = activeRipplesCount;
 
-        // TODO: Use the masking layer first, if there is one.
-
-        // If we have ripples and content, we need a masking layer. This will
-        // merge DST_ATOP onto (effectively under) the ripple layer.
-        if (drewRipples && !projected && rippleRestoreCount >= 0) {
-            canvas.saveLayer(bounds.left, bounds.top,
-                    bounds.right, bounds.bottom, getMaskingPaint(DST_ATOP), 0);
+        // If we created a layer with no content, merge it immediately.
+        if (restoreToCount >= 0 && !drewRipples) {
+            canvas.restoreToCount(restoreToCount);
+            restoreToCount = -1;
         }
 
-        Drawable mask = null;
-        final ChildDrawable[] array = mLayerState.mChildren;
-        final int N = mLayerState.mNum;
-        for (int i = 0; i < N; i++) {
-            if (array[i].mId != R.id.mask) {
-                array[i].mDrawable.draw(canvas);
-            } else {
-                mask = array[i].mDrawable;
-            }
-        }
-
-        // If we have ripples, mask them.
-        if (mask != null && drewRipples) {
-            // TODO: This will also mask the lower layer, which is bad.
-            canvas.saveLayer(bounds.left, bounds.top, bounds.right,
-                    bounds.bottom, getMaskingPaint(DST_IN), 0);
-            mask.draw(canvas);
-        }
-
-        // Composite the layers if needed.
-        if (rippleRestoreCount >= 0) {
-            canvas.restoreToCount(rippleRestoreCount);
-        }
+        return restoreToCount;
     }
 
-    private Paint getRipplePaint() {
-        if (mRipplePaint == null) {
-            mRipplePaint = new Paint();
-            mRipplePaint.setAntiAlias(true);
-
-            if (mState.mTint != null) {
-                final int color = mState.mTint.getColorForState(getState(), Color.TRANSPARENT);
-                mRipplePaint.setColor(color);
-            }
-        }
-        return mRipplePaint;
-    }
-
-    private Paint getMaskingPaint(PorterDuffXfermode mode) {
+    private Paint getMaskingPaint(PorterDuffXfermode xfermode) {
         if (mMaskingPaint == null) {
             mMaskingPaint = new Paint();
         }
-        mMaskingPaint.setXfermode(mode);
+        mMaskingPaint.setXfermode(xfermode);
         return mMaskingPaint;
     }
 
     @Override
     public Rect getDirtyBounds() {
-        final Rect dirtyBounds = mDirtyBounds;
         final Rect drawingBounds = mDrawingBounds;
+        final Rect dirtyBounds = mDirtyBounds;
         dirtyBounds.set(drawingBounds);
         drawingBounds.setEmpty();
+
         final Rect rippleBounds = mTempRect;
         final Ripple[] activeRipples = mActiveRipples;
         final int N = mActiveRipplesCount;
@@ -459,7 +616,9 @@
     static class TouchFeedbackState extends LayerState {
         int[] mTouchThemeAttrs;
         ColorStateList mTint;
-        Mode mTintMode;
+        PorterDuffXfermode mTintXfermode;
+        PorterDuffXfermode mTintXfermodeInverse;
+        Drawable mMask;
         boolean mPinned;
 
         public TouchFeedbackState(
@@ -469,11 +628,27 @@
             if (orig != null) {
                 mTouchThemeAttrs = orig.mTouchThemeAttrs;
                 mTint = orig.mTint;
-                mTintMode = orig.mTintMode;
+                mTintXfermode = orig.mTintXfermode;
+                mTintXfermodeInverse = orig.mTintXfermodeInverse;
                 mPinned = orig.mPinned;
+                mMask = orig.mMask;
             }
         }
 
+        public void setTintMode(Mode mode) {
+            final Mode invertedMode = TouchFeedbackState.invertPorterDuffMode(mode);
+            mTintXfermodeInverse = new PorterDuffXfermode(invertedMode);
+            mTintXfermode = new PorterDuffXfermode(mode);
+        }
+
+        public PorterDuffXfermode getTintXfermode() {
+            return mTintXfermode;
+        }
+
+        public PorterDuffXfermode getTintXfermodeInverse() {
+            return mTintXfermodeInverse;
+        }
+
         @Override
         public boolean canApplyTheme() {
             return mTouchThemeAttrs != null || super.canApplyTheme();
@@ -493,6 +668,33 @@
         public Drawable newDrawable(Resources res, Theme theme) {
             return new TouchFeedbackDrawable(this, res, theme);
         }
+
+        /**
+         * Inverts SRC and DST in PorterDuff blending modes.
+         */
+        private static Mode invertPorterDuffMode(Mode src) {
+            switch (src) {
+                case SRC_ATOP:
+                    return Mode.DST_ATOP;
+                case SRC_IN:
+                    return Mode.DST_IN;
+                case SRC_OUT:
+                    return Mode.DST_OUT;
+                case SRC_OVER:
+                    return Mode.DST_OVER;
+                case DST_ATOP:
+                    return Mode.SRC_ATOP;
+                case DST_IN:
+                    return Mode.SRC_IN;
+                case DST_OUT:
+                    return Mode.SRC_OUT;
+                case DST_OVER:
+                    return Mode.SRC_OVER;
+                default:
+                    // Everything else is agnostic to SRC versus DST.
+                    return src;
+            }
+        }
     }
 
     private TouchFeedbackDrawable(TouchFeedbackState state, Resources res, Theme theme) {
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 6c0b722..0992717 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -17,8 +17,8 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.content.res.Resources.Theme;
+import android.content.res.TypedArray;
 import android.graphics.Canvas;
 import android.graphics.ColorFilter;
 import android.graphics.Matrix;
@@ -47,25 +47,26 @@
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
+
 /**
- * This lets you create a drawable based on an XML vector graphic
- * It can be defined in an XML file with the <code>&lt;vector></code> element.
+ * This lets you create a drawable based on an XML vector graphic It can be
+ * defined in an XML file with the <code>&lt;vector></code> element.
  * <p/>
  * The vector drawable has 6 elements:
  * <p/>
  * <dl>
  * <dt><code>&lt;vector></code></dt>
  * <dd>The attribute <code>android:trigger</code> defines a state change that
- * will drive the animation </dd>
+ * will drive the animation</dd>
  * <dd>The attribute <code>android:versionCode</code> defines the version of
- * VectorDrawable </dd>
+ * VectorDrawable</dd>
  * <dt><code>&lt;size></code></dt>
  * <dd>Used to defined the intrinsic Width Height size of the drawable using
- * <code>android:width</code> and <code>android:height</code> </dd>
+ * <code>android:width</code> and <code>android:height</code></dd>
  * <dt><code>&lt;viewport></code></dt>
  * <dd>Used to defined the size of the virtual canvas the paths are drawn on.
- * The size is defined using the attributes <code>android:viewportHeight
- * </code> <code>android:viewportWidth</code></dd>
+ * The size is defined using the attributes <code>android:viewportHeight</code>
+ * <code>android:viewportWidth</code></dd>
  * <dt><code>&lt;group></code></dt>
  * <dd>Defines a "key frame" in the animation if there is only one group the
  * drawable is static 2D image that has no animation.</dd>
@@ -79,7 +80,8 @@
  * <dt><code>android:fill</code>
  * <dd>Defines the color to fill the path (none if not present).</dd></dt>
  * <dt><code>android:stroke</code>
- * <dd>Defines the color to draw the path outline (none if not present).</dd></dt>
+ * <dd>Defines the color to draw the path outline (none if not present).</dd>
+ * </dt>
  * <dt><code>android:strokeWidth</code>
  * <dd>The width a path stroke</dd></dt>
  * <dt><code>android:strokeOpacity</code>
@@ -97,7 +99,8 @@
  * <dt><code>android:trimPathEnd</code>
  * <dd>The fraction of the path to trim from the end from 0 to 1</dd></dt>
  * <dt><code>android:trimPathOffset</code>
- * <dd>Shift trim region (allows showed region to include the start and end) from 0 to 1</dd></dt>
+ * <dd>Shift trim region (allows showed region to include the start and end)
+ * from 0 to 1</dd></dt>
  * <dt><code>android:clipToPath</code>
  * <dd>Path will set the clip path</dd></dt>
  * <dt><code>android:strokeLineCap</code>
@@ -134,19 +137,20 @@
  * <dt><code>android:sequence</code>
  * <dd>Configures this animation sequence between the named paths.</dd></dt>
  * <dt><code>android:limitTo</code>
- * <dd>Limits an animation to only interpolate the selected variable
- * unlimited, path, rotation, trimPathStart, trimPathEnd, trimPathOffset</dd></dt>
+ * <dd>Limits an animation to only interpolate the selected variable unlimited,
+ * path, rotation, trimPathStart, trimPathEnd, trimPathOffset</dd></dt>
  * <dt><code>android:repeatCount</code>
  * <dd>Number of times to loop this aspect of the animation</dd></dt>
  * <dt><code>android:durations</code>
- * <dd>The duration of each step in the animation in milliseconds
- * Must contain the number of named paths - 1</dd></dt>
+ * <dd>The duration of each step in the animation in milliseconds Must contain
+ * the number of named paths - 1</dd></dt>
  * <dt><code>android:startDelay</code>
  * <dd></dd></dt>
  * <dt><code>android:repeatStyle</code>
- *  <dd>when repeating how does it repeat back and forth or a to b: forward, inAndOut</dd></dt>
+ * <dd>when repeating how does it repeat back and forth or a to b: forward,
+ * inAndOut</dd></dt>
  * <dt><code>android:animate</code>
- *  <dd>linear, accelerate, decelerate, easing</dd></dt>
+ * <dd>linear, accelerate, decelerate, easing</dd></dt>
  * </dl>
  * </dd>
  */
@@ -172,27 +176,30 @@
     private static final int DEFAULT_DURATION = 1000;
     private static final long DEFAULT_INFINITE_DURATION = 60 * 60 * 1000;
 
-    private VectorDrawableState mVectorState;
+    private final VectorDrawableState mVectorState;
+
     private int mAlpha = 0xFF;
 
     public VectorDrawable() {
         mVectorState = new VectorDrawableState(null);
-        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
 
         setDuration(DEFAULT_DURATION);
     }
 
     private VectorDrawable(VectorDrawableState state, Resources res, Theme theme) {
         mVectorState = new VectorDrawableState(state);
-        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 1);
+        mVectorState.mBasicAnimator = ObjectAnimator.ofFloat(this, "AnimationFraction", 0, 0);
 
         if (theme != null && canApplyTheme()) {
             applyTheme(theme);
         }
 
         long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
-        if (duration == -1) { // if it set to infinite set to 1 hour
-            duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+        if (duration == -1) {
+            // If duration is infinite, set to 1 hour.
+            // TODO: Define correct approach for infinite.
+            duration = DEFAULT_INFINITE_DURATION;
             mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
             mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
         }
@@ -204,6 +211,11 @@
         return mVectorState;
     }
 
+    @Override
+    public void jumpToCurrentState() {
+        stop();
+    }
+
     /**
      * Starts the animation.
      */
@@ -212,7 +224,7 @@
     }
 
     /**
-     * Stops the animation.
+     * Stops the animation and moves to the end state.
      */
     public void stop() {
         mVectorState.mBasicAnimator.end();
@@ -248,11 +260,11 @@
 
     /**
      * Defines what this animation should do when it reaches the end. This
-     * setting is applied only when the repeat count is either greater than
-     * 0 or {@link ValueAnimator#INFINITE}.
+     * setting is applied only when the repeat count is either greater than 0 or
+     * {@link ValueAnimator#INFINITE}.
      *
-     * @param mode the animation mode, either {@link ValueAnimator#RESTART}
-     *        or {@link ValueAnimator#REVERSE}
+     * @param mode the animation mode, either {@link ValueAnimator#RESTART} or
+     *            {@link ValueAnimator#REVERSE}
      */
     public void setRepeatMode(int mode) {
         mVectorState.mBasicAnimator.setRepeatMode(mode);
@@ -282,35 +294,42 @@
 
     @Override
     protected boolean onStateChange(int[] state) {
+        super.onStateChange(state);
+
         mVectorState.mVAnimatedPath.setState(state);
-        int direction = mVectorState.mVAnimatedPath.getTrigger(state);
-        if (direction>0) {
+
+        final int direction = mVectorState.mVAnimatedPath.getTrigger(state);
+        if (direction > 0) {
             animateForward();
-        } else if (direction<0) {
+        } else if (direction < 0) {
             animateBackward();
         }
-        super.onStateChange(state);
+
         invalidateSelf();
         return true;
     }
 
-    private void animateForward(){
+    private void animateForward() {
         if (!mVectorState.mBasicAnimator.isStarted()) {
-            mVectorState.mBasicAnimator.setFloatValues(0,1);
+            mVectorState.mBasicAnimator.setFloatValues(0, 1);
             start();
         }
     }
 
-    private void animateBackward(){
+    private void animateBackward() {
         if (!mVectorState.mBasicAnimator.isStarted()) {
-            mVectorState.mBasicAnimator.setFloatValues(.99f,0);
+            mVectorState.mBasicAnimator.setFloatValues(1, 0);
             start();
         }
     }
 
     @Override
     public void draw(Canvas canvas) {
-        mVectorState.mVAnimatedPath.draw(canvas);
+        final int saveCount = canvas.save();
+        final Rect bounds = getBounds();
+        canvas.translate(bounds.left, bounds.top);
+        mVectorState.mVAnimatedPath.draw(canvas, bounds.width(), bounds.height());
+        canvas.restoreToCount(saveCount);
     }
 
     @Override
@@ -327,18 +346,14 @@
         // TODO: support color filter
     }
 
-    /**
-     * Returns a {@link android.graphics.PixelFormat graphics.PixelFormat}
-     * value of TRANSLUCENT.
-     */
     @Override
     public int getOpacity() {
         return PixelFormat.TRANSLUCENT;
     }
 
     /**
-     * Sets padding for this shape, defined by a Rect object. Define the padding in the Rect object
-     * as: left, top, right, bottom.
+     * Sets padding for this shape, defined by a Rect object. Define the padding
+     * in the Rect object as: left, top, right, bottom.
      */
     public void setPadding(Rect padding) {
         setPadding(padding.left, padding.top, padding.right, padding.bottom);
@@ -364,38 +379,14 @@
         invalidateSelf();
     }
 
-    /**
-     * Sets the intrinsic (default) width for this shape.
-     *
-     * @param width the intrinsic width (in pixels)
-     */
-    public void setIntrinsicWidth(int width) {
-        if (mVectorState.mIntrinsicWidth != width) {
-            mVectorState.mIntrinsicWidth = width;
-            invalidateSelf();
-        }
-    }
-
-    /**
-     * Sets the intrinsic (default) height for this shape.
-     *
-     * @param height the intrinsic height (in pixels)
-     */
-    public void setIntrinsicHeight(int height) {
-        if (mVectorState.mIntrinsicHeight != height) {
-            mVectorState.mIntrinsicHeight = height;
-            invalidateSelf();
-        }
-    }
-
     @Override
     public int getIntrinsicWidth() {
-        return mVectorState.mIntrinsicWidth;
+        return (int) mVectorState.mVAnimatedPath.mBaseWidth;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mVectorState.mIntrinsicHeight;
+        return (int) mVectorState.mVAnimatedPath.mBaseHeight;
     }
 
     @Override
@@ -408,25 +399,6 @@
         }
     }
 
-    /** @hide */
-    public static VectorDrawable create(Resources resources, int rid) {
-        try {
-            VectorDrawable drawable = new VectorDrawable();
-            XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
-            factory.setNamespaceAware(true);
-            XmlPullParser xpp = resources.getXml(rid);
-            AttributeSet attrs = Xml.asAttributeSet(xpp);
-            drawable.inflate(resources, xpp, attrs);
-            drawable.setAnimationFraction(0);
-            return drawable;
-        } catch (XmlPullParserException e) {
-            Log.e(LOGTAG, "parser error", e);
-        } catch (IOException e) {
-            Log.e(LOGTAG, "parser error", e);
-        }
-        return null;
-    }
-
     @Override
     public void inflate(Resources res, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
@@ -450,6 +422,27 @@
         }
     }
 
+    /** @hide */
+    public static VectorDrawable create(Resources resources, int rid) {
+        try {
+            final XmlPullParser xpp = resources.getXml(rid);
+            final AttributeSet attrs = Xml.asAttributeSet(xpp);
+            final XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
+            factory.setNamespaceAware(true);
+
+            final VectorDrawable drawable = new VectorDrawable();
+            drawable.inflate(resources, xpp, attrs);
+            drawable.setAnimationFraction(0);
+
+            return drawable;
+        } catch (XmlPullParserException e) {
+            Log.e(LOGTAG, "parser error", e);
+        } catch (IOException e) {
+            Log.e(LOGTAG, "parser error", e);
+        }
+        return null;
+    }
+
     private VAnimatedPath inflateInternal(Resources res, XmlPullParser parser, AttributeSet attrs,
             Theme theme) throws XmlPullParserException, IOException {
         final VAnimatedPath animatedPath = new VAnimatedPath();
@@ -484,13 +477,14 @@
                     currentGroup = new VGroup();
                     animatedPath.mGroupList.add(currentGroup);
                     noGroupTag = false;
-                }  else if (SHAPE_VECTOR.equals(tagName)) {
+                } else if (SHAPE_VECTOR.equals(tagName)) {
                     final TypedArray a = res.obtainAttributes(attrs, R.styleable.VectorDrawable);
                     animatedPath.setTrigger(a.getInteger(R.styleable.VectorDrawable_trigger, 0));
 
                     // Parsing the version information.
                     // Right now, we only support version "1".
-                    // If the xml didn't specify the version number, the default version is "1".
+                    // If the xml didn't specify the version number, the default
+                    // version is "1".
                     final int versionCode = a.getInt(R.styleable.VectorDrawable_versionCode, 1);
                     if (versionCode != 1) {
                         throw new IllegalArgumentException(
@@ -511,22 +505,22 @@
                 tag.append(SHAPE_SIZE);
             }
 
-            if  (noViewportTag){
-                if (tag.length()>0) {
+            if (noViewportTag) {
+                if (tag.length() > 0) {
                     tag.append(" & ");
                 }
                 tag.append(SHAPE_SIZE);
             }
 
-            if  (noGroupTag){
-                if (tag.length()>0) {
+            if (noGroupTag) {
+                if (tag.length() > 0) {
                     tag.append(" & ");
                 }
                 tag.append(SHAPE_GROUP);
             }
 
-            if  (noPathTag){
-                if (tag.length()>0) {
+            if (noPathTag) {
+                if (tag.length() > 0) {
                     tag.append(" or ");
                 }
                 tag.append(SHAPE_PATH);
@@ -543,12 +537,10 @@
     private void setAnimatedPath(VAnimatedPath animatedPath) {
         mVectorState.mVAnimatedPath = animatedPath;
 
-        setIntrinsicWidth((int) mVectorState.mVAnimatedPath.mBaseWidth);
-        setIntrinsicHeight((int) mVectorState.mVAnimatedPath.mBaseHeight);
-
         long duration = mVectorState.mVAnimatedPath.getTotalAnimationDuration();
         if (duration == -1) { // if it set to infinite set to 1 hour
-            duration = DEFAULT_INFINITE_DURATION; // TODO define correct approach for infinite
+            duration = DEFAULT_INFINITE_DURATION; // TODO define correct
+                                                  // approach for infinite
             mVectorState.mBasicAnimator.setFloatValues(0, duration / 1000);
             mVectorState.mBasicAnimator.setInterpolator(new LinearInterpolator());
         }
@@ -575,18 +567,12 @@
         ValueAnimator mBasicAnimator;
         VAnimatedPath mVAnimatedPath;
         Rect mPadding;
-        int mIntrinsicHeight;
-        int mIntrinsicWidth;
 
         public VectorDrawableState(VectorDrawableState copy) {
             if (copy != null) {
                 mChangingConfigurations = copy.mChangingConfigurations;
                 mVAnimatedPath = new VAnimatedPath(copy.mVAnimatedPath);
                 mPadding = new Rect(copy.mPadding);
-                mIntrinsicHeight = copy.mIntrinsicHeight;
-                mIntrinsicWidth = copy.mIntrinsicWidth;
-            } else {
-                mVAnimatedPath = new VAnimatedPath();
             }
         }
 
@@ -612,17 +598,31 @@
     }
 
     private static class VAnimatedPath {
-        private ArrayList<VAnimation> mCurrentAnimList = null;
+        private static final int [] TRIGGER_MAP = {
+                0,
+                R.attr.state_pressed,
+                R.attr.state_focused,
+                R.attr.state_hovered,
+                R.attr.state_selected,
+                R.attr.state_checkable,
+                R.attr.state_checked,
+                R.attr.state_activated,
+                R.attr.state_focused
+        };
+
+        private final Path mPath = new Path();
+        private final Path mRenderPath = new Path();
+        private final Matrix mMatrix = new Matrix();
+
+        private ArrayList<VAnimation> mCurrentAnimList;
         private VPath[] mCurrentPaths;
-        private float mAnimationValue = 0; // value goes from 0 to 1
-        private Paint mStrokePaint = null;
-        private Paint mFillPaint = null;
+        private Paint mStrokePaint;
+        private Paint mFillPaint;
         private PathMeasure mPathMeasure;
-        private Path mPath = new Path();
-        private Path mRenderPath = new Path();
-        private Matrix mMatrix = new Matrix();
-        private long mTotalDuration;
+
         private int[] mCurrentState = new int[0];
+        private float mAnimationValue;
+        private long mTotalDuration;
         private int mTrigger;
         private boolean mTriggerState;
 
@@ -634,11 +634,9 @@
         float mViewportHeight;
 
         public VAnimatedPath() {
-            setup();
         }
 
         public VAnimatedPath(VAnimatedPath copy) {
-            setup();
             mCurrentAnimList = new ArrayList<VAnimation>(copy.mCurrentAnimList);
             mGroupList.addAll(copy.mGroupList);
             if (copy.mCurrentPaths != null) {
@@ -703,28 +701,7 @@
         }
 
         public void setTrigger(int trigger){
-            final int [] lut = {
-                    0,
-                    R.attr.state_pressed,
-                    R.attr.state_focused,
-                    R.attr.state_hovered,
-                    R.attr.state_selected,
-                    R.attr.state_checkable,
-                    R.attr.state_checked,
-                    R.attr.state_activated,
-                    R.attr.state_focused
-            };
-
-            mTrigger = lut[trigger];
-         }
-
-        private void setup(){
-            mStrokePaint = new Paint();
-            mStrokePaint.setStyle(Paint.Style.STROKE);
-            mStrokePaint.setAntiAlias(true);
-            mFillPaint = new Paint();
-            mFillPaint.setStyle(Paint.Style.FILL);
-            mFillPaint.setAntiAlias(true);
+            mTrigger = VAnimatedPath.getStateForTrigger(trigger);
         }
 
         public long getTotalAnimationDuration() {
@@ -780,16 +757,12 @@
             }
         }
 
-        public void draw(Canvas canvas) {
+        public void draw(Canvas canvas, int w, int h) {
             if (mCurrentPaths == null) {
                 Log.e(LOGTAG,"mCurrentPaths == null");
                 return;
             }
 
-            // TODO: This should probably use getBounds().
-            final int w = canvas.getWidth();
-            final int h = canvas.getHeight();
-
             for (int i = 0; i < mCurrentPaths.length; i++) {
                 if (mCurrentPaths[i] != null && mCurrentPaths[i].isVisible(mCurrentState)) {
                     drawPath(mCurrentPaths[i], canvas, w, h);
@@ -801,7 +774,7 @@
             final float scale = Math.min(h / mViewportHeight, w / mViewportWidth);
 
             vPath.toPath(mPath);
-            Path path = mPath;
+            final Path path = mPath;
 
             if (vPath.mTrimPathStart != 0.0f || vPath.mTrimPathEnd != 1.0f) {
                 float start = (vPath.mTrimPathStart + vPath.mTrimPathOffset) % 1.0f;
@@ -839,24 +812,36 @@
             }
 
             if (vPath.mFillColor != 0) {
+                if (mFillPaint == null) {
+                    mFillPaint = new Paint();
+                    mFillPaint.setStyle(Paint.Style.FILL);
+                    mFillPaint.setAntiAlias(true);
+                }
+
                 mFillPaint.setColor(vPath.mFillColor);
-                int alpha = 0xFF & (vPath.mFillColor >> 24);
-                mFillPaint.setAlpha(alpha);
                 canvas.drawPath(mRenderPath, mFillPaint);
             }
 
             if (vPath.mStrokeColor != 0) {
+                if (mStrokePaint == null) {
+                    mStrokePaint = new Paint();
+                    mStrokePaint.setStyle(Paint.Style.STROKE);
+                    mStrokePaint.setAntiAlias(true);
+                }
+
+                final Paint strokePaint = mStrokePaint;
                 if (vPath.mStrokeLineJoin != null) {
-                    mStrokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
+                    strokePaint.setStrokeJoin(vPath.mStrokeLineJoin);
                 }
+
                 if (vPath.mStrokeLineCap != null) {
-                    mStrokePaint.setStrokeCap(vPath.mStrokeLineCap);
+                    strokePaint.setStrokeCap(vPath.mStrokeLineCap);
                 }
-                mStrokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
-                mStrokePaint.setColor(vPath.mStrokeColor);
-                mStrokePaint.setAlpha(0xFF & (vPath.mStrokeColor >> 24));
-                mStrokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
-                canvas.drawPath(mRenderPath, mStrokePaint);
+
+                strokePaint.setStrokeMiter(vPath.mStrokeMiterlimit * scale);
+                strokePaint.setColor(vPath.mStrokeColor);
+                strokePaint.setStrokeWidth(vPath.mStrokeWidth * scale);
+                canvas.drawPath(mRenderPath, strokePaint);
             }
         }
 
@@ -926,7 +911,7 @@
 
         private void parseViewport(Resources r, AttributeSet attrs)
                 throws XmlPullParserException {
-            TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
+            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableViewport);
             mViewportWidth = a.getFloat(R.styleable.VectorDrawableViewport_viewportWidth, 0);
             mViewportHeight = a.getFloat(R.styleable.VectorDrawableViewport_viewportHeight, 0);
             if (mViewportWidth == 0 || mViewportHeight == 0) {
@@ -938,7 +923,7 @@
 
         private void parseSize(Resources r, AttributeSet attrs)
                 throws XmlPullParserException  {
-            TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
+            final TypedArray a = r.obtainAttributes(attrs, R.styleable.VectorDrawableSize);
             mBaseWidth = a.getDimension(R.styleable.VectorDrawableSize_width, 0);
             mBaseHeight = a.getDimension(R.styleable.VectorDrawableSize_height, 0);
             if (mBaseWidth == 0 || mBaseHeight == 0) {
@@ -947,6 +932,10 @@
             }
             a.recycle();
         }
+
+        private static final int getStateForTrigger(int trigger) {
+            return TRIGGER_MAP[trigger];
+        }
     }
 
     private static class VAnimation {
@@ -996,7 +985,13 @@
 
                 for (int j = 0; j < sp.length; j++) {
                     mSeqMap.add(sp[j].trim());
-                    VectorDrawable.VPath path = groups.get(j).get(sp[j]);
+
+                    final VectorDrawable.VPath path = groups.get(j).get(sp[j]);
+                    if (path == null) {
+                        throw new XmlPullParserException(a.getPositionDescription()
+                                + " missing path with name: " + sp[j]);
+                    }
+
                     path.mAnimated = true;
                     paths[j] = path;
                 }
@@ -1324,8 +1319,8 @@
 
         boolean mAnimated = false;
         boolean mClip = false;
-        Paint.Cap mStrokeLineCap = null;
-        Paint.Join mStrokeLineJoin = null;
+        Paint.Cap mStrokeLineCap = Paint.Cap.BUTT;
+        Paint.Join mStrokeLineJoin = Paint.Join.MITER;
         float mStrokeMiterlimit = 4;
 
         private VNode[] mNode = null;
@@ -1775,32 +1770,29 @@
             return returnPath;
         }
 
-        private static int rgbInterpolate(float t, int color1, int color2) {
-            int ret;
-            if (color1 == color2) {
-                return color2;
-            }
-            if (color1 == 0) {
-                return color2;
-            }
-            if (color2 == 0) {
-                return color1;
+        private static int rgbInterpolate(float fraction, int startColor, int endColor) {
+            if (startColor == endColor) {
+                return startColor;
+            } else if (startColor == 0) {
+                return endColor;
+            } else if (endColor == 0) {
+                return startColor;
             }
 
-            float t1 = 1 - t;
-            ret = 0xFF & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)));
-            color1 >>= 8;
-                    color2 >>= 8;
+            final int startA = (startColor >> 24) & 0xff;
+            final int startR = (startColor >> 16) & 0xff;
+            final int startG = (startColor >> 8) & 0xff;
+            final int startB = startColor & 0xff;
 
-                    ret |= 0xFF00 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 8);
-                    color1 >>= 8;
-                    color2 >>= 8;
-            ret |= 0xFF0000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 16);
-            color1 >>= 8;
-            color2 >>= 8;
-            ret |= 0xFF000000 & (((int) ((color1 & 0xFF) * t1 + (color2 & 0xFF) * t)) << 24);
+            final int endA = (endColor >> 24) & 0xff;
+            final int endR = (endColor >> 16) & 0xff;
+            final int endG = (endColor >> 8) & 0xff;
+            final int endB = endColor & 0xff;
 
-            return ret;
+            return ((startA + (int)(fraction * (endA - startA))) << 24) |
+                    ((startR + (int)(fraction * (endR - startR))) << 16) |
+                    ((startG + (int)(fraction * (endG - startG))) << 8) |
+                    ((startB + (int)(fraction * (endB - startB))));
         }
 
         public boolean isVisible(int[] state) {
@@ -1852,27 +1844,25 @@
             }
         }
 
-        private void nodeListToPath(VNode[] node, Path path) {
-            float[] current = new float[4];
-            for (int i = 0; i < node.length; i++) {
-                addCommand(path, current, node[i].mType, node[i].mParams);
-            }
-        }
-
         public static void createPath(VNode[] node, Path path) {
             float[] current = new float[4];
+            char previousCommand = 'm';
             for (int i = 0; i < node.length; i++) {
-                addCommand(path, current, node[i].mType, node[i].mParams);
+                addCommand(path, current, previousCommand, node[i].mType, node[i].mParams);
+                previousCommand = node[i].mType;
             }
         }
 
-        private static void addCommand(Path path, float[] current, char cmd, float[] val) {
+        private static void addCommand(Path path, float[] current,
+                char previousCmd, char cmd, float[] val) {
 
             int incr = 2;
             float currentX = current[0];
             float currentY = current[1];
             float ctrlPointX = current[2];
             float ctrlPointY = current[3];
+            float reflectiveCtrlPointX;
+            float reflectiveCtrlPointY;
 
             switch (cmd) {
                 case 'z':
@@ -1952,12 +1942,8 @@
                         currentY = val[k + 0];
                         break;
                     case 'c': // curveto - Draws a cubic Bézier curve (relative)
-                        path.rCubicTo(val[k + 0],
-                                val[k + 1],
-                                val[k + 2],
-                                val[k + 3],
-                                val[k + 4],
-                                val[k + 5]);
+                        path.rCubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
 
                         ctrlPointX = currentX + val[k + 2];
                         ctrlPointY = currentY + val[k + 3];
@@ -1966,20 +1952,22 @@
 
                         break;
                     case 'C': // curveto - Draws a cubic Bézier curve
-                        path.cubicTo(val[k + 0],
-                                val[k + 1],
-                                val[k + 2],
-                                val[k + 3],
-                                val[k + 4],
-                                val[k + 5]);
+                        path.cubicTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3],
+                                val[k + 4], val[k + 5]);
                         currentX = val[k + 4];
                         currentY = val[k + 5];
                         ctrlPointX = val[k + 2];
                         ctrlPointY = val[k + 3];
-
                         break;
                     case 's': // smooth curveto - Draws a cubic Bézier curve (reflective cp)
-                        path.rCubicTo(currentX - ctrlPointX, currentY  - ctrlPointY,
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rCubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
                                 val[k + 0], val[k + 1],
                                 val[k + 2], val[k + 3]);
 
@@ -1989,47 +1977,63 @@
                         currentY += val[k + 3];
                         break;
                     case 'S': // shorthand/smooth curveto Draws a cubic Bézier curve(reflective cp)
-                        path.cubicTo(2 * currentX - ctrlPointX,
-                                2 * currentY - ctrlPointY,
-                                val[k + 0],
-                                val[k + 1],
-                                val[k + 2],
-                                val[k + 3]);
-                        currentX = val[k + 2];
-                        currentY = val[k + 3];
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'c' || previousCmd == 's'
+                                || previousCmd == 'C' || previousCmd == 'S') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.cubicTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
+                                val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
                         ctrlPointX = val[k + 0];
                         ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
                         break;
                     case 'q': // Draws a quadratic Bézier (relative)
                         path.rQuadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
+                        ctrlPointX = currentX + val[k + 0];
+                        ctrlPointY = currentY + val[k + 1];
                         currentX += val[k + 2];
                         currentY += val[k + 3];
-                        ctrlPointX = val[k + 0];
-                        ctrlPointY = val[k + 1];
                         break;
                     case 'Q': // Draws a quadratic Bézier
                         path.quadTo(val[k + 0], val[k + 1], val[k + 2], val[k + 3]);
-                        currentX = val[k + 2];
-                        currentY = val[k + 3];
                         ctrlPointX = val[k + 0];
                         ctrlPointY = val[k + 1];
+                        currentX = val[k + 2];
+                        currentY = val[k + 3];
                         break;
                     case 't': // Draws a quadratic Bézier curve(reflective control point)(relative)
-                        path.rQuadTo(currentX - ctrlPointX, currentY - ctrlPointY,
+                        reflectiveCtrlPointX = 0;
+                        reflectiveCtrlPointY = 0;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = currentX - ctrlPointX;
+                            reflectiveCtrlPointY = currentY - ctrlPointY;
+                        }
+                        path.rQuadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
                                 val[k + 0], val[k + 1]);
-                        ctrlPointX = ctrlPointX + currentX;
-                        ctrlPointY = ctrlPointY + currentY;
+                        ctrlPointX = currentX + reflectiveCtrlPointX;
+                        ctrlPointY = currentY + reflectiveCtrlPointY;
                         currentX += val[k + 0];
                         currentY += val[k + 1];
-
                         break;
                     case 'T': // Draws a quadratic Bézier curve (reflective control point)
-                        path.quadTo(currentX * 2 - ctrlPointX, currentY * 2 - ctrlPointY,
+                        reflectiveCtrlPointX = currentX;
+                        reflectiveCtrlPointY = currentY;
+                        if (previousCmd == 'q' || previousCmd == 't'
+                                || previousCmd == 'Q' || previousCmd == 'T') {
+                            reflectiveCtrlPointX = 2 * currentX - ctrlPointX;
+                            reflectiveCtrlPointY = 2 * currentY - ctrlPointY;
+                        }
+                        path.quadTo(reflectiveCtrlPointX, reflectiveCtrlPointY,
                                 val[k + 0], val[k + 1]);
+                        ctrlPointX = reflectiveCtrlPointX;
+                        ctrlPointY = reflectiveCtrlPointY;
                         currentX = val[k + 0];
-                        currentY = val[k + 1]; // TODO: Check this logic
-                        ctrlPointX = -(val[k + 0] - currentX);
-                        ctrlPointY = -(val[k + 1] - currentY);
+                        currentY = val[k + 1];
                         break;
                     case 'a': // Draws an elliptical arc
                         // (rx ry x-axis-rotation large-arc-flag sweep-flag x y)
@@ -2047,7 +2051,6 @@
                         currentY += val[k + 6];
                         ctrlPointX = currentX;
                         ctrlPointY = currentY;
-
                         break;
                     case 'A': // Draws an elliptical arc
                         drawArc(path,
@@ -2066,6 +2069,7 @@
                         ctrlPointY = currentY;
                         break;
                 }
+                previousCmd = cmd;
             }
             current[0] = currentX;
             current[1] = currentY;
diff --git a/graphics/java/android/graphics/drawable/shapes/OvalShape.java b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
index c914999..198dcc1 100644
--- a/graphics/java/android/graphics/drawable/shapes/OvalShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/OvalShape.java
@@ -17,7 +17,9 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
+import android.graphics.RectF;
 
 /**
  * Defines an oval shape. 
@@ -36,5 +38,13 @@
     public void draw(Canvas canvas, Paint paint) {
         canvas.drawOval(rect(), paint);
     }
+
+    @Override
+    public boolean getOutline(Outline outline) {
+        final RectF rect = rect();
+        outline.setOval((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
+                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
+        return true;
+    }
 }
 
diff --git a/graphics/java/android/graphics/drawable/shapes/RectShape.java b/graphics/java/android/graphics/drawable/shapes/RectShape.java
index a3d2654..2a0256c 100644
--- a/graphics/java/android/graphics/drawable/shapes/RectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RectShape.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.RectF;
 
@@ -40,10 +41,18 @@
     }
 
     @Override
+    public boolean getOutline(Outline outline) {
+        final RectF rect = rect();
+        outline.setRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
+                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom));
+        return true;
+    }
+
+    @Override
     protected void onResize(float width, float height) {
         mRect.set(0, 0, width, height);
     }
-    
+
     /**
      * Returns the RectF that defines this rectangle's bounds.
      */
diff --git a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
index b469d2a..a6bb1bb 100644
--- a/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
+++ b/graphics/java/android/graphics/drawable/shapes/RoundRectShape.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.RectF;
@@ -77,11 +78,34 @@
     public void draw(Canvas canvas, Paint paint) {
         canvas.drawPath(mPath, paint);
     }
-    
+
+    @Override
+    public boolean getOutline(Outline outline) {
+        if (mInnerRect != null) return false; // have a hole, can't produce valid outline
+
+        float radius = 0;
+        if (mOuterRadii != null) {
+            radius = mOuterRadii[0];
+            for (int i = 1; i < 8; i++) {
+                if (mOuterRadii[i] != radius) {
+                    // can't call simple constructors, use path
+                    outline.setConvexPath(mPath);
+                    return true;
+                }
+            }
+        }
+
+        final RectF rect = rect();
+        outline.setRoundRect((int) Math.ceil(rect.left), (int) Math.ceil(rect.top),
+                (int) Math.floor(rect.right), (int) Math.floor(rect.bottom),
+                radius);
+        return true;
+    }
+
     @Override
     protected void onResize(float w, float h) {
         super.onResize(w, h);
-        
+
         RectF r = rect();
         mPath.reset();
 
diff --git a/graphics/java/android/graphics/drawable/shapes/Shape.java b/graphics/java/android/graphics/drawable/shapes/Shape.java
index 4e192f95..1a20e8b 100644
--- a/graphics/java/android/graphics/drawable/shapes/Shape.java
+++ b/graphics/java/android/graphics/drawable/shapes/Shape.java
@@ -17,6 +17,7 @@
 package android.graphics.drawable.shapes;
 
 import android.graphics.Canvas;
+import android.graphics.Outline;
 import android.graphics.Paint;
 
 /**
@@ -43,7 +44,6 @@
         return mHeight;
     }
 
-
     /**
      * Draw this shape into the provided Canvas, with the provided Paint.
      * Before calling this, you must call {@link #resize(float,float)}.
@@ -52,7 +52,6 @@
      * @param paint  the Paint object that defines this shape's characteristics
      */
     public abstract void draw(Canvas canvas, Paint paint);
-    
 
     /**
      * Resizes the dimensions of this shape.
@@ -93,8 +92,20 @@
      */
     protected void onResize(float width, float height) {}
 
+    /**
+     * Compute the Outline of the shape.
+     *
+     * The default implementation does not supply an outline.
+     *
+     * @return True if a valid outline has been computed, false otherwise.
+     */
+    public boolean getOutline(Outline outline) {
+        return false;
+    }
+
     @Override
     public Shape clone() throws CloneNotSupportedException {
         return (Shape) super.clone();
     }
+
 }
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index c0b5402..c1af5f5 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -62,7 +62,7 @@
     dir.setCapacity(rays);
     float rayDist[rays];
     float rayHeight[rays];
-    calculateRayDirections(rays, dir.editArray());
+    calculateRayDirections(rays, vertices, vertexCount, centroid3d, dir.editArray());
 
     // Calculate the length and height of the points along the edge.
     //
@@ -147,16 +147,97 @@
 
 /**
  * Generate an array of rays' direction vectors.
+ * To make sure the vertices generated are clockwise, the directions are from PI
+ * to -PI.
  *
  * @param rays The number of rays shooting out from the centroid.
+ * @param vertices Vertices of the polygon.
+ * @param vertexCount The number of vertices.
+ * @param centroid3d The centroid of the polygon.
  * @param dir Return the array of ray vectors.
  */
-void AmbientShadow::calculateRayDirections(int rays, Vector2* dir) {
-    float deltaAngle = 2 * M_PI / rays;
+void AmbientShadow::calculateRayDirections(const int rays, const Vector3* vertices,
+        const int vertexCount, const Vector3& centroid3d, Vector2* dir) {
+    // If we don't have enough rays, then fall back to the uniform distribution.
+    if (vertexCount * 2 > rays) {
+        float deltaAngle = 2 * M_PI / rays;
+        for (int i = 0; i < rays; i++) {
+            dir[i].x = cosf(M_PI - deltaAngle * i);
+            dir[i].y = sinf(M_PI - deltaAngle * i);
+        }
+        return;
+    }
+
+    // If we have enough rays, then we assign each vertices a ray, and distribute
+    // the rest uniformly.
+    float rayThetas[rays];
+
+    const int uniformRayCount = rays - vertexCount;
+    const float deltaAngle = 2 * M_PI / uniformRayCount;
+
+    // We have to generate all the vertices' theta anyway and we also need to
+    // find the minimal, so let's precompute it first.
+    // Since the incoming polygon is clockwise, we can find the dip to identify
+    // the minimal theta.
+    float polyThetas[vertexCount];
+    int maxPolyThetaIndex = 0;
+    for (int i = 0; i < vertexCount; i++) {
+        polyThetas[i] = atan2(vertices[i].y - centroid3d.y,
+                vertices[i].x - centroid3d.x);
+        if (i > 0 && polyThetas[i] > polyThetas[i - 1]) {
+            maxPolyThetaIndex = i;
+        }
+    }
+
+    // Both poly's thetas and uniform thetas are in decrease order(clockwise)
+    // from PI to -PI.
+    int polyThetaIndex = maxPolyThetaIndex;
+    float polyTheta = polyThetas[maxPolyThetaIndex];
+    int uniformThetaIndex = 0;
+    float uniformTheta = M_PI;
+    for (int i = 0; i < rays; i++) {
+        // Compare both thetas and pick the smaller one and move on.
+        bool hasThetaCollision = abs(polyTheta - uniformTheta) < MINIMAL_DELTA_THETA;
+        if (polyTheta > uniformTheta || hasThetaCollision) {
+            if (hasThetaCollision) {
+                // Shift the uniformTheta to middle way between current polyTheta
+                // and next uniform theta. The next uniform theta can wrap around
+                // to exactly PI safely here.
+                // Note that neither polyTheta nor uniformTheta can be FLT_MAX
+                // due to the hasThetaCollision is true.
+                uniformTheta = (polyTheta +  M_PI - deltaAngle * (uniformThetaIndex + 1)) / 2;
+#if DEBUG_SHADOW
+                ALOGD("Shifted uniformTheta to %f", uniformTheta);
+#endif
+            }
+            rayThetas[i] = polyTheta;
+            polyThetaIndex = (polyThetaIndex + 1) % vertexCount;
+            if (polyThetaIndex != maxPolyThetaIndex) {
+                polyTheta = polyThetas[polyThetaIndex];
+            } else {
+                // out of poly points.
+                polyTheta = - FLT_MAX;
+            }
+        } else {
+            rayThetas[i] = uniformTheta;
+            uniformThetaIndex++;
+            if (uniformThetaIndex < uniformRayCount) {
+                uniformTheta = M_PI - deltaAngle * uniformThetaIndex;
+            } else {
+                // out of uniform points.
+                uniformTheta = - FLT_MAX;
+            }
+        }
+    }
 
     for (int i = 0; i < rays; i++) {
-        dir[i].x = sinf(deltaAngle * i);
-        dir[i].y = cosf(deltaAngle * i);
+#if DEBUG_SHADOW
+        ALOGD("No. %d : %f", i, rayThetas[i] * 180 / M_PI);
+#endif
+        // TODO: Fix the intersection precision problem and remvoe the delta added
+        // here.
+        dir[i].x = cosf(rayThetas[i] + MINIMAL_DELTA_THETA);
+        dir[i].y = sinf(rayThetas[i] + MINIMAL_DELTA_THETA);
     }
 }
 
@@ -231,13 +312,12 @@
     Vector2 p1 = dir[preIndex] * rayDist[preIndex];
     Vector2 p2 = dir[postIndex] * rayDist[postIndex];
 
-    // Now the V (deltaX, deltaY) is the vector going CW around the poly.
+    // Now the rays are going CW around the poly.
     Vector2 delta = p2 - p1;
     if (delta.length() != 0) {
         delta.normalize();
-        // Calculate the normal , which is CCW 90 rotate to the V.
-        // 90 degrees CCW about z-axis: (x, y, z) -> (-y, x, z)
-        normal.x = -delta.y;
+        // Calculate the normal , which is CCW 90 rotate to the delta.
+        normal.x = - delta.y;
         normal.y = delta.x;
     }
 }
diff --git a/libs/hwui/AmbientShadow.h b/libs/hwui/AmbientShadow.h
index 45b8bef..451bfbe 100644
--- a/libs/hwui/AmbientShadow.h
+++ b/libs/hwui/AmbientShadow.h
@@ -40,7 +40,8 @@
             float geomFactor, VertexBuffer& shadowVertexBuffer);
 
 private:
-    static void calculateRayDirections(int rays, Vector2* dir);
+    static void calculateRayDirections(const int rays, const Vector3* vertices,
+            const int vertexCount, const Vector3& centroid3d, Vector2* dir);
 
     static void calculateIntersection(const Vector3* poly, int nbVertices,
             const Vector3& start, const Vector2& dir, int& outEdgeIndex,
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index 52be531..d324439 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -11,6 +11,7 @@
 		font/CacheTexture.cpp \
 		font/Font.cpp \
 		AmbientShadow.cpp \
+		Animator.cpp \
 		AssetAtlas.cpp \
 		FontRenderer.cpp \
 		GammaFontRenderer.cpp \
@@ -25,6 +26,7 @@
 		FboCache.cpp \
 		GradientCache.cpp \
 		Image.cpp \
+		Interpolator.cpp \
 		Layer.cpp \
 		LayerCache.cpp \
 		LayerRenderer.cpp \
@@ -66,6 +68,8 @@
 		$(LOCAL_PATH)/../../include/utils \
 		external/skia/src/core
 
+	include external/stlport/libstlport.mk
+
 	LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DEGL_EGLEXT_PROTOTYPES -DGL_GLEXT_PROTOTYPES
 	LOCAL_CFLAGS += -Wno-unused-parameter
 	LOCAL_MODULE_CLASS := SHARED_LIBRARIES
diff --git a/libs/hwui/Animator.cpp b/libs/hwui/Animator.cpp
new file mode 100644
index 0000000..ee16586
--- /dev/null
+++ b/libs/hwui/Animator.cpp
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "RT-Animator"
+
+#include "Animator.h"
+
+#include <set>
+
+#include "RenderProperties.h"
+
+namespace android {
+namespace uirenderer {
+
+/************************************************************
+ *  Private header
+ ************************************************************/
+
+typedef void (RenderProperties::*SetFloatProperty)(float value);
+typedef float (RenderProperties::*GetFloatProperty)() const;
+
+struct PropertyAccessors {
+    GetFloatProperty getter;
+    SetFloatProperty setter;
+};
+
+// Maps RenderProperty enum to accessors
+static const PropertyAccessors PROPERTY_ACCESSOR_LUT[] = {
+    {&RenderProperties::getTranslationX, &RenderProperties::setTranslationX },
+    {&RenderProperties::getTranslationY, &RenderProperties::setTranslationY },
+    {&RenderProperties::getTranslationZ, &RenderProperties::setTranslationZ },
+    {&RenderProperties::getScaleX, &RenderProperties::setScaleX },
+    {&RenderProperties::getScaleY, &RenderProperties::setScaleY },
+    {&RenderProperties::getRotation, &RenderProperties::setRotation },
+    {&RenderProperties::getRotationX, &RenderProperties::setRotationX },
+    {&RenderProperties::getRotationY, &RenderProperties::setRotationY },
+    {&RenderProperties::getX, &RenderProperties::setX },
+    {&RenderProperties::getY, &RenderProperties::setY },
+    {&RenderProperties::getZ, &RenderProperties::setZ },
+    {&RenderProperties::getAlpha, &RenderProperties::setAlpha },
+};
+
+// Helper class to contain generic animator helpers
+class BaseAnimator {
+public:
+    BaseAnimator();
+    virtual ~BaseAnimator();
+
+    void setInterpolator(Interpolator* interpolator);
+    void setDuration(nsecs_t durationInMs);
+
+    bool isFinished() { return mPlayState == FINISHED; }
+
+protected:
+    // This is the main animation entrypoint that subclasses should call
+    // to generate the onAnimation* lifecycle events
+    // Returns true if the animation has finished, false otherwise
+    bool animateFrame(nsecs_t frameTime);
+
+    // Called when PlayState switches from PENDING to RUNNING
+    virtual void onAnimationStarted() {}
+    virtual void onAnimationUpdated(float fraction) = 0;
+    virtual void onAnimationFinished() {}
+
+private:
+    enum PlayState {
+        PENDING,
+        RUNNING,
+        FINISHED,
+    };
+
+    Interpolator* mInterpolator;
+    PlayState mPlayState;
+    long mStartTime;
+    long mDuration;
+};
+
+// Hide the base classes & private bits from the exported RenderPropertyAnimator
+// in this Impl class so that subclasses of RenderPropertyAnimator don't require
+// knowledge of the inner guts but only the public virtual methods.
+// Animates a single property
+class RenderPropertyAnimatorImpl : public BaseAnimator {
+public:
+    RenderPropertyAnimatorImpl(GetFloatProperty getter, SetFloatProperty setter,
+            RenderPropertyAnimator::DeltaValueType deltaType, float delta);
+    ~RenderPropertyAnimatorImpl();
+
+    bool animate(RenderProperties* target, TreeInfo& info);
+
+protected:
+    virtual void onAnimationStarted();
+    virtual void onAnimationUpdated(float fraction);
+
+private:
+    // mTarget is only valid inside animate()
+    RenderProperties* mTarget;
+    GetFloatProperty mGetter;
+    SetFloatProperty mSetter;
+
+    RenderPropertyAnimator::DeltaValueType mDeltaValueType;
+    float mDeltaValue;
+    float mFromValue;
+};
+
+RenderPropertyAnimator::RenderPropertyAnimator(RenderProperty property,
+        DeltaValueType deltaType, float deltaValue) {
+    PropertyAccessors pa = PROPERTY_ACCESSOR_LUT[property];
+    mImpl = new RenderPropertyAnimatorImpl(pa.getter, pa.setter, deltaType, deltaValue);
+}
+
+RenderPropertyAnimator::~RenderPropertyAnimator() {
+    delete mImpl;
+    mImpl = NULL;
+}
+
+void RenderPropertyAnimator::setInterpolator(Interpolator* interpolator) {
+    mImpl->setInterpolator(interpolator);
+}
+
+void RenderPropertyAnimator::setDuration(nsecs_t durationInMs) {
+    mImpl->setDuration(durationInMs);
+}
+
+bool RenderPropertyAnimator::isFinished() {
+    return mImpl->isFinished();
+}
+
+bool RenderPropertyAnimator::animate(RenderProperties* target, TreeInfo& info) {
+    return mImpl->animate(target, info);
+}
+
+
+/************************************************************
+ *  Base animator
+ ************************************************************/
+
+BaseAnimator::BaseAnimator()
+        : mInterpolator(0)
+        , mPlayState(PENDING)
+        , mStartTime(0)
+        , mDuration(300) {
+
+}
+
+BaseAnimator::~BaseAnimator() {
+    setInterpolator(NULL);
+}
+
+void BaseAnimator::setInterpolator(Interpolator* interpolator) {
+    delete mInterpolator;
+    mInterpolator = interpolator;
+}
+
+void BaseAnimator::setDuration(nsecs_t duration) {
+    mDuration = duration;
+}
+
+bool BaseAnimator::animateFrame(nsecs_t frameTime) {
+    if (mPlayState == PENDING) {
+        mPlayState = RUNNING;
+        mStartTime = frameTime;
+        // No interpolator was set, use the default
+        if (!mInterpolator) {
+            setInterpolator(Interpolator::createDefaultInterpolator());
+        }
+        onAnimationStarted();
+    }
+
+    float fraction = 1.0f;
+    if (mPlayState == RUNNING) {
+        fraction = mDuration > 0 ? (float)(frameTime - mStartTime) / mDuration : 1.0f;
+        if (fraction >= 1.0f) {
+            fraction = 1.0f;
+            mPlayState = FINISHED;
+        }
+    }
+    fraction = mInterpolator->interpolate(fraction);
+    onAnimationUpdated(fraction);
+
+    if (mPlayState == FINISHED) {
+        onAnimationFinished();
+        return true;
+    }
+    return false;
+}
+
+/************************************************************
+ *  RenderPropertyAnimator
+ ************************************************************/
+
+RenderPropertyAnimatorImpl::RenderPropertyAnimatorImpl(
+                GetFloatProperty getter, SetFloatProperty setter,
+                RenderPropertyAnimator::DeltaValueType deltaType, float delta)
+        : mTarget(0)
+        , mGetter(getter)
+        , mSetter(setter)
+        , mDeltaValueType(deltaType)
+        , mDeltaValue(delta)
+        , mFromValue(-1) {
+}
+
+RenderPropertyAnimatorImpl::~RenderPropertyAnimatorImpl() {
+}
+
+bool RenderPropertyAnimatorImpl::animate(RenderProperties* target, TreeInfo& info) {
+    mTarget = target;
+    bool finished = animateFrame(info.frameTimeMs);
+    mTarget = NULL;
+    return finished;
+}
+
+void RenderPropertyAnimatorImpl::onAnimationStarted() {
+    mFromValue = (mTarget->*mGetter)();
+
+    if (mDeltaValueType == RenderPropertyAnimator::ABSOLUTE) {
+        mDeltaValue = (mDeltaValue - mFromValue);
+        mDeltaValueType = RenderPropertyAnimator::DELTA;
+    }
+}
+
+void RenderPropertyAnimatorImpl::onAnimationUpdated(float fraction) {
+    float value = mFromValue + (mDeltaValue * fraction);
+    (mTarget->*mSetter)(value);
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/Animator.h b/libs/hwui/Animator.h
new file mode 100644
index 0000000..1c8361b
--- /dev/null
+++ b/libs/hwui/Animator.h
@@ -0,0 +1,79 @@
+/*
+ * 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.
+ */
+#ifndef ANIMATOR_H
+#define ANIMATOR_H
+
+#include <cutils/compiler.h>
+
+#include "Interpolator.h"
+#include "TreeInfo.h"
+#include "utils/VirtualLightRefBase.h"
+
+namespace android {
+namespace uirenderer {
+
+class RenderProperties;
+class RenderPropertyAnimatorImpl;
+
+class RenderPropertyAnimator : public VirtualLightRefBase {
+public:
+    // Since the UI thread doesn't necessarily know what the current values
+    // actually are and thus can't do the calculations, this is used to inform
+    // the animator how to lazy-resolve the input value
+    enum DeltaValueType {
+        // The delta value represents an absolute value endpoint
+        // mDeltaValue needs to be recalculated to be mDelta = (mDelta - fromValue)
+        // in onAnimationStarted()
+        ABSOLUTE = 0,
+        // The final value represents an offset from the current value
+        // No recalculation is needed
+        DELTA,
+    };
+
+    enum RenderProperty {
+        TRANSLATION_X = 0,
+        TRANSLATION_Y,
+        TRANSLATION_Z,
+        SCALE_X,
+        SCALE_Y,
+        ROTATION,
+        ROTATION_X,
+        ROTATION_Y,
+        X,
+        Y,
+        Z,
+        ALPHA,
+    };
+
+    ANDROID_API void setInterpolator(Interpolator* interpolator);
+    ANDROID_API void setDuration(nsecs_t durationInMs);
+    ANDROID_API bool isFinished();
+
+    bool animate(RenderProperties* target, TreeInfo& info);
+
+protected:
+    ANDROID_API RenderPropertyAnimator(RenderProperty property, DeltaValueType deltaType,
+            float deltaValue);
+    ANDROID_API virtual ~RenderPropertyAnimator();
+
+private:
+    RenderPropertyAnimatorImpl* mImpl;
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* ANIMATOR_H */
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index df2123b..43223ec 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -691,9 +691,10 @@
     propertyAmbientShadowStrength = 25;
     propertySpotShadowStrength = 25;
 
-    propertyLightPosXScale = 0.5f;
-    propertyLightPosYScale = 0.0f;
-    propertyLightPosZScale = 1.0f;
+    propertyLightDiameter = -1.0f;
+    propertyLightPosY = -1.0f;
+    propertyLightPosZ = -1.0f;
+    propertyAmbientRatio = -1.0f;
 }
 
 void Caches::setTempProperty(const char* name, const char* value) {
@@ -706,17 +707,21 @@
         propertySpotShadowStrength = atoi(value);
         ALOGD("spot shadow strength = 0x%x out of 0xff", propertySpotShadowStrength);
         return;
-    } else if (!strcmp(name, "lightPosXScale")) {
-        propertyLightPosXScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos X Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "ambientRatio")) {
+        propertyAmbientRatio = fmin(fmax(atof(value), 0.0), 10.0);
+        ALOGD("ambientRatio = %.2f", propertyAmbientRatio);
         return;
-    }  else if (!strcmp(name, "lightPosYScale")) {
-        propertyLightPosYScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Y Scale = %.2f", propertyLightPosXScale);
+    } else if (!strcmp(name, "lightDiameter")) {
+        propertyLightDiameter = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightDiameter = %.2f", propertyLightDiameter);
         return;
-    }  else if (!strcmp(name, "lightPosZScale")) {
-        propertyLightPosZScale = fmin(fmax(atof(value), 0.0), 1.0);
-        ALOGD("lightPos Z Scale = %.2f", propertyLightPosXScale);
+    }  else if (!strcmp(name, "lightPosY")) {
+        propertyLightPosY = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Y = %.2f", propertyLightPosY);
+        return;
+    }  else if (!strcmp(name, "lightPosZ")) {
+        propertyLightPosZ = fmin(fmax(atof(value), 0.0), 3000.0);
+        ALOGD("lightPos Z = %.2f", propertyLightPosZ);
         return;
     }
     ALOGD("    failed");
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index ba3ccaf..2e2ee15 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -352,13 +352,10 @@
     void initTempProperties();
     void setTempProperty(const char* name, const char* value);
 
-    // These scaling factors range from 0 to 1, to scale the light position
-    // within the bound of (screenwidth, screenheight, max(screenwidth, screenheight));
-    // The default scale is (0.5, 0, 1) which put the light at
-    // (screenwidth / 2, 0, max(screenwidth, screenheight)).
-    float propertyLightPosXScale;
-    float propertyLightPosYScale;
-    float propertyLightPosZScale;
+    float propertyLightDiameter;
+    float propertyLightPosY;
+    float propertyLightPosZ;
+    float propertyAmbientRatio;
     int propertyAmbientShadowStrength;
     int propertySpotShadowStrength;
 
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index ce711b6..285c8c3 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -41,6 +41,7 @@
 
 DeferredLayerUpdater::~DeferredLayerUpdater() {
     SkSafeUnref(mColorFilter);
+    setTransform(0);
     if (mLayer) {
         mCaches.resourceCache.decrementRefcount(mLayer);
     }
@@ -62,7 +63,7 @@
     }
 }
 
-bool DeferredLayerUpdater::apply() {
+bool DeferredLayerUpdater::apply(TreeInfo& info) {
     bool success = true;
     // These properties are applied the same to both layer types
     mLayer->setColorFilter(mColorFilter);
@@ -73,7 +74,7 @@
             success = LayerRenderer::resizeLayer(mLayer, mWidth, mHeight);
         }
         mLayer->setBlend(mBlend);
-        mDisplayList->updateProperties();
+        mDisplayList->prepareTree(info);
         mLayer->updateDeferred(mDisplayList.get(),
                 mDirtyRect.left, mDirtyRect.top, mDirtyRect.right, mDirtyRect.bottom);
         mDirtyRect.setEmpty();
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index ce08c2d..cc62caa 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -77,7 +77,7 @@
 
     ANDROID_API void setPaint(const SkPaint* paint);
 
-    ANDROID_API bool apply();
+    ANDROID_API bool apply(TreeInfo& info);
 
     ANDROID_API Layer* backingLayer() {
         return mLayer;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index a5d8dcb..dac86cb 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -29,7 +29,10 @@
 namespace android {
 namespace uirenderer {
 
-DisplayListData::DisplayListData() : projectionReceiveIndex(-1), functorCount(0), hasDrawOps(false) {
+DisplayListData::DisplayListData()
+        : projectionReceiveIndex(-1)
+        , functorCount(0)
+        , hasDrawOps(false) {
 }
 
 DisplayListData::~DisplayListData() {
diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h
index 06f675e..6dfb918 100644
--- a/libs/hwui/DisplayListOp.h
+++ b/libs/hwui/DisplayListOp.h
@@ -286,12 +286,6 @@
 
     int getFlags() const { return mFlags; }
 private:
-    SaveOp() {}
-    DisplayListOp* reinit(int flags) {
-        mFlags = flags;
-        return this;
-    }
-
     int mFlags;
 };
 
@@ -318,24 +312,25 @@
     virtual const char* name() { return "RestoreToCount"; }
 
 private:
-    RestoreToCountOp() {}
-    DisplayListOp* reinit(int count) {
-        mCount = count;
-        return this;
-    }
-
     int mCount;
 };
 
 class SaveLayerOp : public StateOp {
 public:
     SaveLayerOp(float left, float top, float right, float bottom, int alpha, int flags)
-            : mArea(left, top, right, bottom), mPaint(&mCachedPaint), mFlags(flags) {
+            : mArea(left, top, right, bottom)
+            , mPaint(&mCachedPaint)
+            , mFlags(flags)
+            , mConvexMask(NULL) {
         mCachedPaint.setAlpha(alpha);
     }
 
     SaveLayerOp(float left, float top, float right, float bottom, const SkPaint* paint, int flags)
-            : mArea(left, top, right, bottom), mPaint(paint), mFlags(flags) {}
+            : mArea(left, top, right, bottom)
+            , mPaint(paint)
+            , mFlags(flags)
+            , mConvexMask(NULL)
+    {}
 
     virtual void defer(DeferStateStruct& deferStruct, int saveCount, int level,
             bool useQuickReject) {
@@ -350,7 +345,8 @@
     }
 
     virtual void applyState(OpenGLRenderer& renderer, int saveCount) const {
-        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom, mPaint, mFlags);
+        renderer.saveLayer(mArea.left, mArea.top, mArea.right, mArea.bottom,
+                mPaint, mFlags, mConvexMask);
     }
 
     virtual void output(int level, uint32_t logFlags) const {
@@ -362,6 +358,11 @@
 
     int getFlags() { return mFlags; }
 
+    // Called to make SaveLayerOp clip to the provided mask when drawing back/restored
+    void setMask(const SkPath* convexMask) {
+        mConvexMask = convexMask;
+    }
+
 private:
     bool isSaveLayerAlpha() const {
         SkXfermode::Mode mode = OpenGLRenderer::getXfermodeDirect(mPaint);
@@ -373,6 +374,10 @@
     const SkPaint* mPaint;
     SkPaint mCachedPaint;
     int mFlags;
+
+    // Convex path, points at data in RenderNode, valid for the duration of the frame only
+    // Only used for masking the SaveLayer which wraps projected RenderNodes
+    const SkPath* mConvexMask;
 };
 
 class TranslateOp : public StateOp {
@@ -514,7 +519,6 @@
     }
 
 protected:
-    ClipOp() {}
     virtual bool isRect() { return false; }
 
     SkRegion::Op mOp;
@@ -539,13 +543,6 @@
     virtual bool isRect() { return true; }
 
 private:
-    ClipRectOp() {}
-    DisplayListOp* reinit(float left, float top, float right, float bottom, SkRegion::Op op) {
-        mOp = op;
-        mArea.set(left, top, right, bottom);
-        return this;
-    }
-
     Rect mArea;
 };
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 140a07a..e36d975 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -184,20 +184,15 @@
     // dirty is an out parameter and should not be recorded,
     // it matters only when replaying the display list
 
-    // TODO: To be safe, the display list should be ref-counted in the
-    //       resources cache, but we rely on the caller (UI toolkit) to
-    //       do the right thing for now
+    if (displayList->stagingProperties().isProjectionReceiver()) {
+        // use staging property, since recording on UI thread
+        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
+    }
 
     DrawDisplayListOp* op = new (alloc()) DrawDisplayListOp(displayList,
             flags, *currentTransform());
     addDrawOp(op);
     mDisplayListData->addChild(op);
-
-    if (displayList->stagingProperties().isProjectionReceiver()) {
-        // use staging property, since recording on UI thread
-        mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size() - 1;
-    }
-
     return DrawGlInfo::kStatusDone;
 }
 
@@ -258,11 +253,11 @@
 
 status_t DisplayListRenderer::drawBitmapMesh(const SkBitmap* bitmap, int meshWidth, int meshHeight,
         const float* vertices, const int* colors, const SkPaint* paint) {
-    int count = (meshWidth + 1) * (meshHeight + 1) * 2;
+    int vertexCount = (meshWidth + 1) * (meshHeight + 1);
     bitmap = refBitmap(bitmap);
-    vertices = refBuffer<float>(vertices, count);
+    vertices = refBuffer<float>(vertices, vertexCount * 2); // 2 floats per vertex
     paint = refPaint(paint);
-    colors = refBuffer<int>(colors, count);
+    colors = refBuffer<int>(colors, vertexCount); // 1 color per vertex
 
     addDrawOp(new (alloc()) DrawBitmapMeshOp(bitmap, meshWidth, meshHeight,
                     vertices, colors, paint));
diff --git a/libs/hwui/Interpolator.cpp b/libs/hwui/Interpolator.cpp
new file mode 100644
index 0000000..004ddf5
--- /dev/null
+++ b/libs/hwui/Interpolator.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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 "Interpolator.h"
+
+#include <math.h>
+
+namespace android {
+namespace uirenderer {
+
+Interpolator* Interpolator::createDefaultInterpolator() {
+    return new AccelerateDecelerateInterpolator();
+}
+
+float AccelerateDecelerateInterpolator::interpolate(float input) {
+    return (float)(cosf((input + 1) * M_PI) / 2.0f) + 0.5f;
+}
+
+} /* namespace uirenderer */
+} /* namespace android */
diff --git a/libs/hwui/Interpolator.h b/libs/hwui/Interpolator.h
new file mode 100644
index 0000000..2cfb60c
--- /dev/null
+++ b/libs/hwui/Interpolator.h
@@ -0,0 +1,45 @@
+/*
+ * 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.
+ */
+#ifndef INTERPOLATOR_H
+#define INTERPOLATOR_H
+
+namespace android {
+namespace uirenderer {
+
+class Interpolator {
+public:
+    virtual ~Interpolator() {}
+
+    virtual float interpolate(float input) = 0;
+
+    static Interpolator* createDefaultInterpolator();
+
+protected:
+    Interpolator() {}
+};
+
+class AccelerateDecelerateInterpolator : public Interpolator {
+public:
+    AccelerateDecelerateInterpolator() {}
+    virtual ~AccelerateDecelerateInterpolator() {}
+
+    virtual float interpolate(float input);
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* INTERPOLATOR_H */
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index bfe4eda..9606e58 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -48,6 +48,7 @@
     hasDrawnSinceUpdate = false;
     forceFilter = false;
     deferredList = NULL;
+    convexMask = NULL;
     caches.resourceCache.incrementRefcount(this);
 }
 
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 5375b45..49610d5 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -227,6 +227,14 @@
 
     ANDROID_API void setColorFilter(SkColorFilter* filter);
 
+    inline void setConvexMask(const SkPath* convexMask) {
+        this->convexMask = convexMask;
+    }
+
+    inline const SkPath* getConvexMask() {
+        return convexMask;
+    }
+
     void bindStencilRenderBuffer() const;
 
     void bindTexture() const;
@@ -378,6 +386,13 @@
      */
     DeferredDisplayList* deferredList;
 
+    /**
+     * This convex path should be used to mask the layer's draw to the screen.
+     *
+     * Data not owned/managed by layer object.
+     */
+    const SkPath* convexMask;
+
 }; // struct Layer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 9dbcd36..95fdb04 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -704,11 +704,11 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 int OpenGLRenderer::saveLayer(float left, float top, float right, float bottom,
-        const SkPaint* paint, int flags) {
+        const SkPaint* paint, int flags, const SkPath* convexMask) {
     const int count = saveSnapshot(flags);
 
     if (!currentSnapshot()->isIgnored()) {
-        createLayer(left, top, right, bottom, paint, flags);
+        createLayer(left, top, right, bottom, paint, flags, convexMask);
     }
 
     return count;
@@ -782,7 +782,6 @@
     return count;
 }
 
-
 /**
  * Layers are viewed by Skia are slightly different than layers in image editing
  * programs (for instance.) When a layer is created, previously created layers
@@ -835,7 +834,7 @@
  *     something actually gets drawn are the layers regions cleared.
  */
 bool OpenGLRenderer::createLayer(float left, float top, float right, float bottom,
-        const SkPaint* paint, int flags) {
+        const SkPaint* paint, int flags, const SkPath* convexMask) {
     LAYER_LOGD("Requesting layer %.2fx%.2f", right - left, bottom - top);
     LAYER_LOGD("Layer cache size = %d", mCaches.layerCache.getSize());
 
@@ -865,6 +864,7 @@
 
     layer->setBlend(true);
     layer->setDirty(false);
+    layer->setConvexMask(convexMask); // note: the mask must be cleared before returning to the cache
 
     // Save the layer in the snapshot
     mSnapshot->flags |= Snapshot::kFlagIsLayer;
@@ -1013,6 +1013,7 @@
     dirtyClip();
 
     // Failing to add the layer to the cache should happen only if the layer is too large
+    layer->setConvexMask(NULL);
     if (!mCaches.layerCache.put(layer)) {
         LAYER_LOGD("Deleting layer");
         Caches::getInstance().resourceCache.decrementRefcount(layer);
@@ -1122,6 +1123,38 @@
 #define DRAW_DOUBLE_STENCIL(DRAW_COMMAND) DRAW_DOUBLE_STENCIL_IF(true, DRAW_COMMAND)
 
 void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
+    if (CC_UNLIKELY(layer->region.isEmpty())) return; // nothing to draw
+
+    if (layer->getConvexMask()) {
+        save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
+
+        // clip to the area of the layer the mask can be larger
+        clipRect(rect.left, rect.top, rect.right, rect.bottom, SkRegion::kIntersect_Op);
+
+        SkPaint paint;
+        paint.setAntiAlias(true);
+        paint.setColor(SkColorSetARGB(int(getLayerAlpha(layer) * 255), 0, 0, 0));
+
+        SkiaShader* oldShader = mDrawModifiers.mShader;
+
+        // create LayerShader to map SaveLayer content into subsequent draw
+        SkMatrix shaderMatrix;
+        shaderMatrix.setTranslate(rect.left, rect.bottom);
+        shaderMatrix.preScale(1, -1);
+        SkiaLayerShader layerShader(layer, &shaderMatrix);
+        mDrawModifiers.mShader = &layerShader;
+
+        // Since the drawing primitive is defined in local drawing space,
+        // we don't need to modify the draw matrix
+        const SkPath* maskPath = layer->getConvexMask();
+        DRAW_DOUBLE_STENCIL(drawConvexPath(*maskPath, &paint));
+
+        mDrawModifiers.mShader = oldShader;
+        restore();
+
+        return;
+    }
+
     if (layer->region.isRect()) {
         layer->setRegionAsRect();
 
@@ -1131,88 +1164,87 @@
         return;
     }
 
-    if (CC_LIKELY(!layer->region.isEmpty())) {
-        size_t count;
-        const android::Rect* rects;
-        Region safeRegion;
-        if (CC_LIKELY(hasRectToRectTransform())) {
-            rects = layer->region.getArray(&count);
-        } else {
-            safeRegion = Region::createTJunctionFreeRegion(layer->region);
-            rects = safeRegion.getArray(&count);
-        }
+    // standard Region based draw
+    size_t count;
+    const android::Rect* rects;
+    Region safeRegion;
+    if (CC_LIKELY(hasRectToRectTransform())) {
+        rects = layer->region.getArray(&count);
+    } else {
+        safeRegion = Region::createTJunctionFreeRegion(layer->region);
+        rects = safeRegion.getArray(&count);
+    }
 
-        const float alpha = getLayerAlpha(layer);
-        const float texX = 1.0f / float(layer->getWidth());
-        const float texY = 1.0f / float(layer->getHeight());
-        const float height = rect.getHeight();
+    const float alpha = getLayerAlpha(layer);
+    const float texX = 1.0f / float(layer->getWidth());
+    const float texY = 1.0f / float(layer->getHeight());
+    const float height = rect.getHeight();
 
-        setupDraw();
+    setupDraw();
 
-        // We must get (and therefore bind) the region mesh buffer
-        // after we setup drawing in case we need to mess with the
-        // stencil buffer in setupDraw()
-        TextureVertex* mesh = mCaches.getRegionMesh();
-        uint32_t numQuads = 0;
+    // We must get (and therefore bind) the region mesh buffer
+    // after we setup drawing in case we need to mess with the
+    // stencil buffer in setupDraw()
+    TextureVertex* mesh = mCaches.getRegionMesh();
+    uint32_t numQuads = 0;
 
-        setupDrawWithTexture();
-        setupDrawColor(alpha, alpha, alpha, alpha);
-        setupDrawColorFilter(layer->getColorFilter());
-        setupDrawBlending(layer);
-        setupDrawProgram();
-        setupDrawDirtyRegionsDisabled();
-        setupDrawPureColorUniforms();
-        setupDrawColorFilterUniforms(layer->getColorFilter());
-        setupDrawTexture(layer->getTexture());
-        if (currentTransform()->isPureTranslate()) {
-            const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
-            const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
+    setupDrawWithTexture();
+    setupDrawColor(alpha, alpha, alpha, alpha);
+    setupDrawColorFilter(layer->getColorFilter());
+    setupDrawBlending(layer);
+    setupDrawProgram();
+    setupDrawDirtyRegionsDisabled();
+    setupDrawPureColorUniforms();
+    setupDrawColorFilterUniforms(layer->getColorFilter());
+    setupDrawTexture(layer->getTexture());
+    if (currentTransform()->isPureTranslate()) {
+        const float x = (int) floorf(rect.left + currentTransform()->getTranslateX() + 0.5f);
+        const float y = (int) floorf(rect.top + currentTransform()->getTranslateY() + 0.5f);
 
-            layer->setFilter(GL_NEAREST);
-            setupDrawModelView(kModelViewMode_Translate, false,
-                    x, y, x + rect.getWidth(), y + rect.getHeight(), true);
-        } else {
-            layer->setFilter(GL_LINEAR);
-            setupDrawModelView(kModelViewMode_Translate, false,
-                    rect.left, rect.top, rect.right, rect.bottom);
-        }
-        setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
+        layer->setFilter(GL_NEAREST);
+        setupDrawModelView(kModelViewMode_Translate, false,
+                x, y, x + rect.getWidth(), y + rect.getHeight(), true);
+    } else {
+        layer->setFilter(GL_LINEAR);
+        setupDrawModelView(kModelViewMode_Translate, false,
+                rect.left, rect.top, rect.right, rect.bottom);
+    }
+    setupDrawMeshIndices(&mesh[0].x, &mesh[0].u);
 
-        for (size_t i = 0; i < count; i++) {
-            const android::Rect* r = &rects[i];
+    for (size_t i = 0; i < count; i++) {
+        const android::Rect* r = &rects[i];
 
-            const float u1 = r->left * texX;
-            const float v1 = (height - r->top) * texY;
-            const float u2 = r->right * texX;
-            const float v2 = (height - r->bottom) * texY;
+        const float u1 = r->left * texX;
+        const float v1 = (height - r->top) * texY;
+        const float u2 = r->right * texX;
+        const float v2 = (height - r->bottom) * texY;
 
-            // TODO: Reject quads outside of the clip
-            TextureVertex::set(mesh++, r->left, r->top, u1, v1);
-            TextureVertex::set(mesh++, r->right, r->top, u2, v1);
-            TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
-            TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
+        // TODO: Reject quads outside of the clip
+        TextureVertex::set(mesh++, r->left, r->top, u1, v1);
+        TextureVertex::set(mesh++, r->right, r->top, u2, v1);
+        TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
+        TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
 
-            numQuads++;
+        numQuads++;
 
-            if (numQuads >= gMaxNumberOfQuads) {
-                DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
-                                GL_UNSIGNED_SHORT, NULL));
-                numQuads = 0;
-                mesh = mCaches.getRegionMesh();
-            }
-        }
-
-        if (numQuads > 0) {
+        if (numQuads >= gMaxNumberOfQuads) {
             DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
                             GL_UNSIGNED_SHORT, NULL));
+            numQuads = 0;
+            mesh = mCaches.getRegionMesh();
         }
+    }
+
+    if (numQuads > 0) {
+        DRAW_DOUBLE_STENCIL(glDrawElements(GL_TRIANGLES, numQuads * 6,
+                        GL_UNSIGNED_SHORT, NULL));
+    }
 
 #if DEBUG_LAYERS_AS_REGIONS
-        drawRegionRectsDebug(layer->region);
+    drawRegionRectsDebug(layer->region);
 #endif
 
-        layer->region.clear();
-    }
+    layer->region.clear();
 }
 
 #if DEBUG_LAYERS_AS_REGIONS
@@ -1901,7 +1933,6 @@
     // will be performed by the display list itself
     if (displayList && displayList->isRenderable()) {
         // compute 3d ordering
-        displayList->updateProperties();
         displayList->computeOrdering();
         if (CC_UNLIKELY(mCaches.drawDeferDisabled)) {
             status = startFrame();
@@ -2927,7 +2958,7 @@
     if (layer->isTextureLayer()) {
         transform = &layer->getTransform();
         if (!transform->isIdentity()) {
-            save(0);
+            save(SkCanvas::kMatrix_SaveFlag);
             concatMatrix(*transform);
         }
     }
@@ -3199,6 +3230,10 @@
     const float casterRefinementThresholdSquared = 20.0f; // TODO: experiment with this value
     PathTessellator::approximatePathOutlineVertices(*casterPerimeter,
             casterRefinementThresholdSquared, casterVertices2d);
+    if (!ShadowTessellator::isClockwisePath(*casterPerimeter)) {
+        ShadowTessellator::reverseVertexArray(casterVertices2d.editArray(),
+                casterVertices2d.size());
+    }
 
     if (casterVertices2d.size() == 0) {
         // empty caster polygon computed from path
@@ -3256,10 +3291,8 @@
     if (mCaches.propertySpotShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertySpotShadowStrength, 0, 0, 0);
         VertexBuffer spotShadowVertexBuffer;
-        Vector3 lightPosScale(mCaches.propertyLightPosXScale,
-                mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
         VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateSpotShadow(
-                isCasterOpaque, casterPolygon, casterVertexCount, lightPosScale,
+                isCasterOpaque, casterPolygon, casterVertexCount,
                 *currentTransform(), getWidth(), getHeight(), casterBounds, localClip,
                 spotShadowVertexBuffer);
         drawVertexBuffer(vertexBufferMode, spotShadowVertexBuffer, &paint);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 2debd2e..b49d1e1 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -161,7 +161,14 @@
     ANDROID_API void flushLayerUpdates();
 
     ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom,
-            const SkPaint* paint, int flags);
+            const SkPaint* paint, int flags) {
+        return saveLayer(left, top, right, bottom, paint, flags, NULL);
+    }
+
+    // Specialized saveLayer implementation, which will pass the convexMask to an FBO layer, if
+    // created, which will in turn clip to that mask when drawn back/restored.
+    int saveLayer(float left, float top, float right, float bottom,
+            const SkPaint* paint, int flags, const SkPath* convexMask);
 
     int saveLayerDeferred(float left, float top, float right, float bottom,
             const SkPaint* paint, int flags);
@@ -523,11 +530,12 @@
      * @param alpha The translucency of the layer
      * @param mode The blending mode of the layer
      * @param flags The layer save flags
+     * @param mask A mask to use when drawing the layer back, may be empty
      *
      * @return True if the layer was successfully created, false otherwise
      */
     bool createLayer(float left, float top, float right, float bottom,
-            const SkPaint* paint, int flags);
+            const SkPaint* paint, int flags, const SkPath* convexMask);
 
     /**
      * Creates a new layer stored in the specified snapshot as an FBO.
diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h
index 0083b77..92964a8 100644
--- a/libs/hwui/Rect.h
+++ b/libs/hwui/Rect.h
@@ -30,6 +30,8 @@
 #define RECT_STRING "%7.2f %7.2f %7.2f %7.2f"
 #define RECT_ARGS(r) \
     (r).left, (r).top, (r).right, (r).bottom
+#define SK_RECT_ARGS(r) \
+    (r).left(), (r).top(), (r).right(), (r).bottom()
 
 ///////////////////////////////////////////////////////////////////////////////
 // Structs
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 5010076..7a9c181 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -18,6 +18,8 @@
 
 #include "RenderNode.h"
 
+#include <algorithm>
+
 #include <SkCanvas.h>
 #include <algorithm>
 
@@ -26,6 +28,7 @@
 #include "Debug.h"
 #include "DisplayListOp.h"
 #include "DisplayListLogBuffer.h"
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -49,21 +52,25 @@
     fflush(file);
 }
 
-RenderNode::RenderNode() : mDestroyed(false), mNeedsPropertiesSync(false), mDisplayListData(0) {
+RenderNode::RenderNode()
+        : mNeedsPropertiesSync(false)
+        , mNeedsDisplayListDataSync(false)
+        , mDisplayListData(0)
+        , mStagingDisplayListData(0)
+        , mNeedsAnimatorsSync(false) {
 }
 
 RenderNode::~RenderNode() {
-    LOG_ALWAYS_FATAL_IF(mDestroyed, "Double destroyed DisplayList %p", this);
-
-    mDestroyed = true;
     delete mDisplayListData;
+    delete mStagingDisplayListData;
 }
 
-void RenderNode::setData(DisplayListData* data) {
-    delete mDisplayListData;
-    mDisplayListData = data;
-    if (mDisplayListData) {
-        Caches::getInstance().registerFunctors(mDisplayListData->functorCount);
+void RenderNode::setStagingDisplayList(DisplayListData* data) {
+    mNeedsDisplayListDataSync = true;
+    delete mStagingDisplayListData;
+    mStagingDisplayListData = data;
+    if (mStagingDisplayListData) {
+        Caches::getInstance().registerFunctors(mStagingDisplayListData->functorCount);
     }
 }
 
@@ -73,7 +80,7 @@
  */
 void RenderNode::output(uint32_t level) {
     ALOGD("%*sStart display list (%p, %s, render=%d)", (level - 1) * 2, "", this,
-            mName.string(), isRenderable());
+            getName(), isRenderable());
     ALOGD("%*s%s %d", level * 2, "", "Save",
             SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
 
@@ -83,38 +90,100 @@
         mDisplayListData->displayListOps[i]->output(level, flags);
     }
 
-    ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, mName.string());
+    ALOGD("%*sDone (%p, %s)", (level - 1) * 2, "", this, getName());
 }
 
-void RenderNode::updateProperties() {
+void RenderNode::prepareTree(TreeInfo& info) {
+    ATRACE_CALL();
+
+    prepareTreeImpl(info);
+}
+
+void RenderNode::prepareTreeImpl(TreeInfo& info) {
+    if (info.performStagingPush) {
+        pushStagingChanges(info);
+    }
+    if (info.evaluateAnimations) {
+        evaluateAnimations(info);
+    }
+    prepareSubTree(info, mDisplayListData);
+}
+
+static bool is_finished(const sp<RenderPropertyAnimator>& animator) {
+    return animator->isFinished();
+}
+
+void RenderNode::pushStagingChanges(TreeInfo& info) {
     if (mNeedsPropertiesSync) {
         mNeedsPropertiesSync = false;
         mProperties = mStagingProperties;
     }
-
-    if (mDisplayListData) {
-        for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
-            RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
-            childNode->updateProperties();
-        }
+    if (mNeedsAnimatorsSync) {
+        mAnimators.resize(mStagingAnimators.size());
+        std::vector< sp<RenderPropertyAnimator> >::iterator it;
+        // hint: this means copy_if_not()
+        it = std::remove_copy_if(mStagingAnimators.begin(), mStagingAnimators.end(),
+                mAnimators.begin(), is_finished);
+        mAnimators.resize(std::distance(mAnimators.begin(), it));
+    }
+    if (mNeedsDisplayListDataSync) {
+        mNeedsDisplayListDataSync = false;
+        // Do a push pass on the old tree to handle freeing DisplayListData
+        // that are no longer used
+        TreeInfo oldTreeInfo;
+        prepareSubTree(oldTreeInfo, mDisplayListData);
+        // TODO: The damage for the old tree should be accounted for
+        delete mDisplayListData;
+        mDisplayListData = mStagingDisplayListData;
+        mStagingDisplayListData = 0;
     }
 }
 
-bool RenderNode::hasFunctors() {
-    if (!mDisplayListData) return false;
+class AnimateFunctor {
+public:
+    AnimateFunctor(RenderProperties* target, TreeInfo& info)
+            : mTarget(target), mInfo(info) {}
 
-    if (mDisplayListData->functorCount) {
-        return true;
+    bool operator() (sp<RenderPropertyAnimator>& animator) {
+        bool finished = animator->animate(mTarget, mInfo);
+        if (finished && mInfo.animationListener) {
+            mInfo.animationListener->onAnimationFinished(animator);
+        }
+        return finished;
     }
+private:
+    RenderProperties* mTarget;
+    TreeInfo& mInfo;
+};
 
-    for (size_t i = 0; i < mDisplayListData->children().size(); i++) {
-        RenderNode* childNode = mDisplayListData->children()[i]->mDisplayList;
-        if (childNode->hasFunctors()) {
-            return true;
+void RenderNode::evaluateAnimations(TreeInfo& info) {
+    if (!mAnimators.size()) return;
+
+    AnimateFunctor functor(&mProperties, info);
+    std::vector< sp<RenderPropertyAnimator> >::iterator newEnd;
+    newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
+    mAnimators.erase(newEnd, mAnimators.end());
+    mProperties.updateMatrix();
+    info.hasAnimations |= mAnimators.size();
+}
+
+void RenderNode::prepareSubTree(TreeInfo& info, DisplayListData* subtree) {
+    if (subtree) {
+        TextureCache& cache = Caches::getInstance().textureCache;
+        info.hasFunctors |= subtree->functorCount;
+        // TODO: Fix ownedBitmapResources to not require disabling prepareTextures
+        // and thus falling out of async drawing path.
+        if (subtree->ownedBitmapResources.size()) {
+            info.prepareTextures = false;
+        }
+        for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
+            info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
+        }
+        for (size_t i = 0; i < subtree->children().size(); i++) {
+            RenderNode* childNode = subtree->children()[i]->mDisplayList;
+            childNode->prepareTreeImpl(info);
         }
     }
-
-    return false;
 }
 
 /*
@@ -137,8 +206,8 @@
     } else if (properties().getAnimationMatrix()) {
         renderer.concatMatrix(properties().getAnimationMatrix());
     }
-    if (properties().getMatrixFlags() != 0) {
-        if (properties().getMatrixFlags() == TRANSLATION) {
+    if (properties().hasTransformMatrix()) {
+        if (properties().isTransformTranslateOnly()) {
             renderer.translate(properties().getTranslationX(), properties().getTranslationY());
         } else {
             renderer.concatMatrix(*properties().getTransformMatrix());
@@ -197,10 +266,12 @@
         mat4 anim(*properties().getAnimationMatrix());
         matrix.multiply(anim);
     }
-    if (properties().getMatrixFlags() != 0) {
-        if (properties().getMatrixFlags() == TRANSLATION) {
+
+    bool applyTranslationZ = true3dTransform && !MathUtils::isZero(properties().getZ());
+    if (properties().hasTransformMatrix() || applyTranslationZ) {
+        if (properties().isTransformTranslateOnly()) {
             matrix.translate(properties().getTranslationX(), properties().getTranslationY(),
-                    true3dTransform ? properties().getTranslationZ() : 0.0f);
+                    true3dTransform ? properties().getZ() : 0.0f);
         } else {
             if (!true3dTransform) {
                 matrix.multiply(*properties().getTransformMatrix());
@@ -209,7 +280,7 @@
                 true3dMat.loadTranslate(
                         properties().getPivotX() + properties().getTranslationX(),
                         properties().getPivotY() + properties().getTranslationY(),
-                        properties().getTranslationZ());
+                        properties().getZ());
                 true3dMat.rotate(properties().getRotationX(), 1, 0, 0);
                 true3dMat.rotate(properties().getRotationY(), 0, 1, 0);
                 true3dMat.rotate(properties().getRotation(), 0, 0, 1);
@@ -240,12 +311,13 @@
     for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
         DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         childOp->mDisplayList->computeOrderingImpl(childOp,
-                &mProjectedNodes, &mat4::identity());
+                properties().getOutline().getPath(), &mProjectedNodes, &mat4::identity());
     }
 }
 
 void RenderNode::computeOrderingImpl(
         DrawDisplayListOp* opState,
+        const SkPath* outlineOfProjectionSurface,
         Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
         const mat4* transformFromProjectionSurface) {
     mProjectedNodes.clear();
@@ -273,6 +345,7 @@
             DrawDisplayListOp* childOp = mDisplayListData->children()[i];
             RenderNode* child = childOp->mDisplayList;
 
+            const SkPath* projectionOutline = NULL;
             Vector<DrawDisplayListOp*>* projectionChildren = NULL;
             const mat4* projectionTransform = NULL;
             if (isProjectionReceiver && !child->properties().getProjectBackwards()) {
@@ -281,6 +354,7 @@
                 // Note that if a direct descendent is projecting backwards, we pass it's
                 // grandparent projection collection, since it shouldn't project onto it's
                 // parent, where it will already be drawing.
+                projectionOutline = properties().getOutline().getPath();
                 projectionChildren = &mProjectedNodes;
                 projectionTransform = &mat4::identity();
             } else {
@@ -288,10 +362,12 @@
                     applyViewPropertyTransforms(localTransformFromProjectionSurface);
                     haveAppliedPropertiesToProjection = true;
                 }
+                projectionOutline = outlineOfProjectionSurface;
                 projectionChildren = compositedChildrenOfProjectionSurface;
                 projectionTransform = &localTransformFromProjectionSurface;
             }
-            child->computeOrderingImpl(childOp, projectionChildren, projectionTransform);
+            child->computeOrderingImpl(childOp,
+                    projectionOutline, projectionChildren, projectionTransform);
         }
     }
 }
@@ -316,7 +392,9 @@
 
 void RenderNode::deferNodeTree(DeferStateStruct& deferStruct) {
     DeferOperationHandler handler(deferStruct, 0);
-    if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+    if (MathUtils::isPositive(properties().getZ())) {
+        issueDrawShadowOperation(Matrix4::identity(), handler);
+    }
     issueOperations<DeferOperationHandler>(deferStruct.mRenderer, handler);
 }
 
@@ -331,7 +409,7 @@
         : mReplayStruct(replayStruct), mLevel(level) {}
     inline void operator()(DisplayListOp* operation, int saveCount, bool clipToBounds) {
 #if DEBUG_DISPLAY_LIST_OPS_AS_EVENTS
-        properties().getReplayStruct().mRenderer.eventMark(operation->name());
+        mReplayStruct.mRenderer.eventMark(operation->name());
 #endif
         operation->replay(mReplayStruct, saveCount, mLevel, clipToBounds);
     }
@@ -341,8 +419,6 @@
     }
     inline void endMark() {
         mReplayStruct.mRenderer.endMark();
-        DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", level * 2, "", this, mName.string(),
-                mReplayStruct.mDrawGlStatus);
     }
     inline int level() { return mLevel; }
     inline int replayFlags() { return mReplayStruct.mReplayFlags; }
@@ -354,7 +430,9 @@
 
 void RenderNode::replayNodeTree(ReplayStateStruct& replayStruct) {
     ReplayOperationHandler handler(replayStruct, 0);
-    if (properties().getTranslationZ() > 0.0f) issueDrawShadowOperation(Matrix4::identity(), handler);
+    if (MathUtils::isPositive(properties().getZ())) {
+        issueDrawShadowOperation(Matrix4::identity(), handler);
+    }
     issueOperations<ReplayOperationHandler>(replayStruct.mRenderer, handler);
 }
 
@@ -369,9 +447,9 @@
     for (unsigned int i = 0; i < mDisplayListData->children().size(); i++) {
         DrawDisplayListOp* childOp = mDisplayListData->children()[i];
         RenderNode* child = childOp->mDisplayList;
-        float childZ = child->properties().getTranslationZ();
+        float childZ = child->properties().getZ();
 
-        if (childZ != 0.0f) {
+        if (!MathUtils::isZero(childZ)) {
             zTranslatedNodes.add(ZDrawDisplayListOpPair(childZ, childOp));
             childOp->mSkipInOrderDraw = true;
         } else if (!child->properties().getProjectBackwards()) {
@@ -447,6 +525,10 @@
         endIndex = size;
         shadowIndex = drawIndex; // potentially draw shadow for each pos Z child
     }
+
+    DISPLAY_LIST_LOGD("%*s%d %s 3d children:", (handler.level() + 1) * 2, "",
+            endIndex - drawIndex, mode == kNegativeZChildren ? "negative" : "positive");
+
     float lastCasterZ = 0.0f;
     while (shadowIndex < endIndex || drawIndex < endIndex) {
         if (shadowIndex < endIndex) {
@@ -483,6 +565,42 @@
 
 template <class T>
 void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T& handler) {
+    DISPLAY_LIST_LOGD("%*s%d projected children:", (handler.level() + 1) * 2, "", mProjectedNodes.size());
+    const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
+    bool maskProjecteesWithPath = projectionReceiverOutline != NULL
+            && !projectionReceiverOutline->isRect(NULL);
+    int restoreTo = renderer.getSaveCount();
+
+    // If the projection reciever has an outline, we mask each of the projected rendernodes to it
+    // Either with clipRect, or special saveLayer masking
+    LinearAllocator& alloc = handler.allocator();
+    if (projectionReceiverOutline != NULL) {
+        const SkRect& outlineBounds = projectionReceiverOutline->getBounds();
+        if (projectionReceiverOutline->isRect(NULL)) {
+            // mask to the rect outline simply with clipRect
+            handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
+                    PROPERTY_SAVECOUNT, properties().getClipToBounds());
+            ClipRectOp* clipOp = new (alloc) ClipRectOp(
+                    outlineBounds.left(), outlineBounds.top(),
+                    outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op);
+            handler(clipOp, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+        } else {
+            // wrap the projected RenderNodes with a SaveLayer that will mask to the outline
+            SaveLayerOp* op = new (alloc) SaveLayerOp(
+                    outlineBounds.left(), outlineBounds.top(),
+                    outlineBounds.right(), outlineBounds.bottom(),
+                    255, SkCanvas::kARGB_ClipLayer_SaveFlag);
+            op->setMask(projectionReceiverOutline);
+            handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+
+            /* TODO: add optimizations here to take advantage of placement/size of projected
+             * children (which may shrink saveLayer area significantly). This is dependent on
+             * passing actual drawing/dirtying bounds of projected content down to native.
+             */
+        }
+    }
+
+    // draw projected nodes
     for (size_t i = 0; i < mProjectedNodes.size(); i++) {
         DrawDisplayListOp* childOp = mProjectedNodes[i];
 
@@ -494,6 +612,11 @@
         childOp->mSkipInOrderDraw = true;
         renderer.restoreToCount(restoreTo);
     }
+
+    if (projectionReceiverOutline != NULL) {
+        handler(new (alloc) RestoreToCountOp(restoreTo),
+                PROPERTY_SAVECOUNT, properties().getClipToBounds());
+    }
 }
 
 /**
@@ -508,22 +631,18 @@
 template <class T>
 void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) {
     const int level = handler.level();
-    if (CC_UNLIKELY(mDestroyed)) { // temporary debug logging
-        ALOGW("Error: %s is drawing after destruction", mName.string());
-        CRASH();
-    }
     if (mDisplayListData->isEmpty() || properties().getAlpha() <= 0) {
-        DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, mName.string());
+        DISPLAY_LIST_LOGD("%*sEmpty display list (%p, %s)", level * 2, "", this, getName());
         return;
     }
 
-    handler.startMark(mName.string());
+    handler.startMark(getName());
 
 #if DEBUG_DISPLAY_LIST
-    Rect* clipRect = renderer.getClipRect();
-    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), clipRect: %.0f, %.0f, %.0f, %.0f",
-            level * 2, "", this, mName.string(), clipRect->left, clipRect->top,
-            clipRect->right, clipRect->bottom);
+    const Rect& clipRect = renderer.getLocalClipBounds();
+    DISPLAY_LIST_LOGD("%*sStart display list (%p, %s), localClipBounds: %.0f, %.0f, %.0f, %.0f",
+            level * 2, "", this, getName(),
+            clipRect.left, clipRect.top, clipRect.right, clipRect.bottom);
 #endif
 
     LinearAllocator& alloc = handler.allocator();
@@ -571,6 +690,7 @@
             PROPERTY_SAVECOUNT, properties().getClipToBounds());
     renderer.setOverrideLayerAlpha(1.0f);
 
+    DISPLAY_LIST_LOGD("%*sDone (%p, %s)", level * 2, "", this, getName());
     handler.endMark();
 }
 
diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h
index fa0fb8a..294f436 100644
--- a/libs/hwui/RenderNode.h
+++ b/libs/hwui/RenderNode.h
@@ -20,6 +20,9 @@
     #define LOG_TAG "OpenGLRenderer"
 #endif
 
+#include <set>
+#include <vector>
+
 #include <SkCamera.h>
 #include <SkMatrix.h>
 
@@ -41,6 +44,7 @@
 #include "DeferredDisplayList.h"
 #include "DisplayList.h"
 #include "RenderProperties.h"
+#include "TreeInfo.h"
 #include "utils/VirtualLightRefBase.h"
 
 class SkBitmap;
@@ -80,7 +84,7 @@
 class RenderNode : public VirtualLightRefBase {
 public:
     ANDROID_API RenderNode();
-    ANDROID_API ~RenderNode();
+    ANDROID_API virtual ~RenderNode();
 
     // See flags defined in DisplayList.java
     enum ReplayFlag {
@@ -89,7 +93,7 @@
 
     ANDROID_API static void outputLogBuffer(int fd);
 
-    ANDROID_API void setData(DisplayListData* newData);
+    ANDROID_API void setStagingDisplayList(DisplayListData* newData);
 
     void computeOrdering();
 
@@ -141,10 +145,19 @@
         return properties().getHeight();
     }
 
-    ANDROID_API void updateProperties();
+    ANDROID_API virtual void prepareTree(TreeInfo& info);
 
-    // Returns true if this RenderNode or any of its children have functors
-    bool hasFunctors();
+    // UI thread only!
+    ANDROID_API void addAnimator(const sp<RenderPropertyAnimator>& animator) {
+        mStagingAnimators.insert(animator);
+        mNeedsAnimatorsSync = true;
+    }
+
+    // UI thread only!
+    ANDROID_API void removeAnimator(const sp<RenderPropertyAnimator>& animator) {
+        mStagingAnimators.erase(animator);
+        mNeedsAnimatorsSync = true;
+    }
 
 private:
     typedef key_value_pair_t<float, DrawDisplayListOp*> ZDrawDisplayListOpPair;
@@ -164,6 +177,7 @@
     void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false);
 
     void computeOrderingImpl(DrawDisplayListOp* opState,
+            const SkPath* outlineOfProjectionSurface,
             Vector<DrawDisplayListOp*>* compositedChildrenOfProjectionSurface,
             const mat4* transformFromProjectionSurface);
 
@@ -203,14 +217,24 @@
         const char* mText;
     };
 
+    void prepareTreeImpl(TreeInfo& info);
+    void pushStagingChanges(TreeInfo& info);
+    void evaluateAnimations(TreeInfo& info);
+    void prepareSubTree(TreeInfo& info, DisplayListData* subtree);
+
     String8 mName;
-    bool mDestroyed; // used for debugging crash, TODO: remove once invalid state crash fixed
 
     bool mNeedsPropertiesSync;
     RenderProperties mProperties;
     RenderProperties mStagingProperties;
 
+    bool mNeedsDisplayListDataSync;
     DisplayListData* mDisplayListData;
+    DisplayListData* mStagingDisplayListData;
+
+    bool mNeedsAnimatorsSync;
+    std::set< sp<RenderPropertyAnimator> > mStagingAnimators;
+    std::vector< sp<RenderPropertyAnimator> > mAnimators;
 
     /**
      * Draw time state - these properties are only set and used during rendering
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index e7e7768..99de1fc 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -26,6 +26,7 @@
 #include <SkPathOps.h>
 
 #include "Matrix.h"
+#include "utils/MathUtils.h"
 
 namespace android {
 namespace uirenderer {
@@ -36,28 +37,26 @@
         , mProjectionReceiver(false)
         , mAlpha(1)
         , mHasOverlappingRendering(true)
+        , mElevation(0)
         , mTranslationX(0), mTranslationY(0), mTranslationZ(0)
         , mRotation(0), mRotationX(0), mRotationY(0)
         , mScaleX(1), mScaleY(1)
         , mPivotX(0), mPivotY(0)
         , mLeft(0), mTop(0), mRight(0), mBottom(0)
         , mWidth(0), mHeight(0)
-        , mPrevWidth(-1), mPrevHeight(-1)
         , mPivotExplicitlySet(false)
-        , mMatrixDirty(false)
-        , mMatrixFlags(0)
+        , mMatrixOrPivotDirty(false)
         , mCaching(false) {
 }
 
 RenderProperties::ComputedFields::ComputedFields()
         : mTransformMatrix(NULL)
-        , mTransformMatrix3D(NULL)
-        , mClipPath(NULL) {
+        , mClipPath(NULL)
+        , mClipPathOp(SkRegion::kIntersect_Op) {
 }
 
 RenderProperties::ComputedFields::~ComputedFields() {
     delete mTransformMatrix;
-    delete mTransformMatrix3D;
     delete mClipPath;
 }
 
@@ -82,7 +81,7 @@
         updateClipPath();
 
         // Force recalculation of the matrix, since other's dirty bit may be clear
-        mPrimitiveFields.mMatrixDirty = true;
+        mPrimitiveFields.mMatrixOrPivotDirty = true;
         updateMatrix();
     }
     return *this;
@@ -100,10 +99,10 @@
         ALOGD("%*sConcatMatrix (animation) %p: " SK_MATRIX_STRING,
                 level * 2, "", mAnimationMatrix, SK_MATRIX_ARGS(mAnimationMatrix));
     }
-    if (mPrimitiveFields.mMatrixFlags != 0) {
-        if (mPrimitiveFields.mMatrixFlags == TRANSLATION) {
+    if (hasTransformMatrix()) {
+        if (isTransformTranslateOnly()) {
             ALOGD("%*sTranslate %.2f, %.2f, %.2f",
-                    level * 2, "", mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY, mPrimitiveFields.mTranslationZ);
+                    level * 2, "", getTranslationX(), getTranslationY(), getZ());
         } else {
             ALOGD("%*sConcatMatrix %p: " SK_MATRIX_STRING,
                     level * 2, "", mComputedFields.mTransformMatrix, SK_MATRIX_ARGS(mComputedFields.mTransformMatrix));
@@ -134,52 +133,36 @@
 }
 
 void RenderProperties::updateMatrix() {
-    if (mPrimitiveFields.mMatrixDirty) {
-        // NOTE: mComputedFields.mTransformMatrix won't be up to date if a DisplayList goes from a complex transform
-        // to a pure translate. This is safe because the mPrimitiveFields.matrix isn't read in pure translate cases.
-        if (mPrimitiveFields.mMatrixFlags && mPrimitiveFields.mMatrixFlags != TRANSLATION) {
-            if (!mComputedFields.mTransformMatrix) {
-                // only allocate a mPrimitiveFields.matrix if we have a complex transform
-                mComputedFields.mTransformMatrix = new SkMatrix();
-            }
-            if (!mPrimitiveFields.mPivotExplicitlySet) {
-                if (mPrimitiveFields.mWidth != mPrimitiveFields.mPrevWidth || mPrimitiveFields.mHeight != mPrimitiveFields.mPrevHeight) {
-                    mPrimitiveFields.mPrevWidth = mPrimitiveFields.mWidth;
-                    mPrimitiveFields.mPrevHeight = mPrimitiveFields.mHeight;
-                    mPrimitiveFields.mPivotX = mPrimitiveFields.mPrevWidth / 2.0f;
-                    mPrimitiveFields.mPivotY = mPrimitiveFields.mPrevHeight / 2.0f;
-                }
-            }
-
-            if ((mPrimitiveFields.mMatrixFlags & ROTATION_3D) == 0) {
-                mComputedFields.mTransformMatrix->setTranslate(
-                        mPrimitiveFields.mTranslationX, mPrimitiveFields.mTranslationY);
-                mComputedFields.mTransformMatrix->preRotate(mPrimitiveFields.mRotation,
-                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
-                mComputedFields.mTransformMatrix->preScale(
-                        mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
-                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
-            } else {
-                if (!mComputedFields.mTransformMatrix3D) {
-                    mComputedFields.mTransformMatrix3D = new SkMatrix();
-                }
-                mComputedFields.mTransformMatrix->reset();
-                mComputedFields.mTransformCamera.save();
-                mComputedFields.mTransformMatrix->preScale(
-                        mPrimitiveFields.mScaleX, mPrimitiveFields.mScaleY,
-                        mPrimitiveFields.mPivotX, mPrimitiveFields.mPivotY);
-                mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX);
-                mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY);
-                mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation);
-                mComputedFields.mTransformCamera.getMatrix(mComputedFields.mTransformMatrix3D);
-                mComputedFields.mTransformMatrix3D->preTranslate(-mPrimitiveFields.mPivotX, -mPrimitiveFields.mPivotY);
-                mComputedFields.mTransformMatrix3D->postTranslate(mPrimitiveFields.mPivotX + mPrimitiveFields.mTranslationX,
-                        mPrimitiveFields.mPivotY + mPrimitiveFields.mTranslationY);
-                mComputedFields.mTransformMatrix->postConcat(*mComputedFields.mTransformMatrix3D);
-                mComputedFields.mTransformCamera.restore();
-            }
+    if (mPrimitiveFields.mMatrixOrPivotDirty) {
+        if (!mComputedFields.mTransformMatrix) {
+            // only allocate a mPrimitiveFields.matrix if we have a complex transform
+            mComputedFields.mTransformMatrix = new SkMatrix();
         }
-        mPrimitiveFields.mMatrixDirty = false;
+        if (!mPrimitiveFields.mPivotExplicitlySet) {
+            mPrimitiveFields.mPivotX = mPrimitiveFields.mWidth / 2.0f;
+            mPrimitiveFields.mPivotY = mPrimitiveFields.mHeight / 2.0f;
+        }
+        SkMatrix* transform = mComputedFields.mTransformMatrix;
+        transform->reset();
+        if (MathUtils::isZero(getRotationX()) && MathUtils::isZero(getRotationY())) {
+            transform->setTranslate(getTranslationX(), getTranslationY());
+            transform->preRotate(getRotation(), getPivotX(), getPivotY());
+            transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
+        } else {
+            SkMatrix transform3D;
+            mComputedFields.mTransformCamera.save();
+            transform->preScale(getScaleX(), getScaleY(), getPivotX(), getPivotY());
+            mComputedFields.mTransformCamera.rotateX(mPrimitiveFields.mRotationX);
+            mComputedFields.mTransformCamera.rotateY(mPrimitiveFields.mRotationY);
+            mComputedFields.mTransformCamera.rotateZ(-mPrimitiveFields.mRotation);
+            mComputedFields.mTransformCamera.getMatrix(&transform3D);
+            transform3D.preTranslate(-getPivotX(), -getPivotY());
+            transform3D.postTranslate(getPivotX() + getTranslationX(),
+                    getPivotY() + getTranslationY());
+            transform->postConcat(transform3D);
+            mComputedFields.mTransformCamera.restore();
+        }
+        mPrimitiveFields.mMatrixOrPivotDirty = false;
     }
 }
 
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index dd68210..6fc8bce 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -16,7 +16,9 @@
 #ifndef RENDERNODEPROPERTIES_H
 #define RENDERNODEPROPERTIES_H
 
+#include <algorithm>
 #include <stddef.h>
+#include <vector>
 #include <cutils/compiler.h>
 #include <androidfw/ResourceTypes.h>
 
@@ -24,16 +26,11 @@
 #include <SkMatrix.h>
 #include <SkRegion.h>
 
+#include "Animator.h"
 #include "Rect.h"
 #include "RevealClip.h"
 #include "Outline.h"
 
-#define TRANSLATION 0x0001
-#define ROTATION    0x0002
-#define ROTATION_3D 0x0004
-#define SCALE       0x0008
-#define PIVOT       0x0010
-
 class SkBitmap;
 class SkPaint;
 
@@ -111,10 +108,21 @@
         return mPrimitiveFields.mHasOverlappingRendering;
     }
 
+    void setElevation(float elevation) {
+        if (elevation != mPrimitiveFields.mElevation) {
+            mPrimitiveFields.mElevation = elevation;
+            // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
+        }
+    }
+
+    float getElevation() const {
+        return mPrimitiveFields.mElevation;
+    }
+
     void setTranslationX(float translationX) {
         if (translationX != mPrimitiveFields.mTranslationX) {
             mPrimitiveFields.mTranslationX = translationX;
-            onTranslationUpdate();
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -125,7 +133,7 @@
     void setTranslationY(float translationY) {
         if (translationY != mPrimitiveFields.mTranslationY) {
             mPrimitiveFields.mTranslationY = translationY;
-            onTranslationUpdate();
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -136,7 +144,7 @@
     void setTranslationZ(float translationZ) {
         if (translationZ != mPrimitiveFields.mTranslationZ) {
             mPrimitiveFields.mTranslationZ = translationZ;
-            onTranslationUpdate();
+            // mMatrixOrPivotDirty not set, since matrix doesn't respect Z
         }
     }
 
@@ -144,15 +152,39 @@
         return mPrimitiveFields.mTranslationZ;
     }
 
+    // Animation helper
+    void setX(float value) {
+        setTranslationX(value - getLeft());
+    }
+
+    // Animation helper
+    float getX() const {
+        return getLeft() + getTranslationX();
+    }
+
+    // Animation helper
+    void setY(float value) {
+        setTranslationY(value - getTop());
+    }
+
+    // Animation helper
+    float getY() const {
+        return getTop() + getTranslationY();
+    }
+
+    // Animation helper
+    void setZ(float value) {
+        setTranslationZ(value - getElevation());
+    }
+
+    float getZ() const {
+        return getElevation() + getTranslationZ();
+    }
+
     void setRotation(float rotation) {
         if (rotation != mPrimitiveFields.mRotation) {
             mPrimitiveFields.mRotation = rotation;
-            mPrimitiveFields.mMatrixDirty = true;
-            if (mPrimitiveFields.mRotation == 0.0f) {
-                mPrimitiveFields.mMatrixFlags &= ~ROTATION;
-            } else {
-                mPrimitiveFields.mMatrixFlags |= ROTATION;
-            }
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -163,12 +195,7 @@
     void setRotationX(float rotationX) {
         if (rotationX != mPrimitiveFields.mRotationX) {
             mPrimitiveFields.mRotationX = rotationX;
-            mPrimitiveFields.mMatrixDirty = true;
-            if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) {
-                mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D;
-            } else {
-                mPrimitiveFields.mMatrixFlags |= ROTATION_3D;
-            }
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -179,12 +206,7 @@
     void setRotationY(float rotationY) {
         if (rotationY != mPrimitiveFields.mRotationY) {
             mPrimitiveFields.mRotationY = rotationY;
-            mPrimitiveFields.mMatrixDirty = true;
-            if (mPrimitiveFields.mRotationX == 0.0f && mPrimitiveFields.mRotationY == 0.0f) {
-                mPrimitiveFields.mMatrixFlags &= ~ROTATION_3D;
-            } else {
-                mPrimitiveFields.mMatrixFlags |= ROTATION_3D;
-            }
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -195,12 +217,7 @@
     void setScaleX(float scaleX) {
         if (scaleX != mPrimitiveFields.mScaleX) {
             mPrimitiveFields.mScaleX = scaleX;
-            mPrimitiveFields.mMatrixDirty = true;
-            if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) {
-                mPrimitiveFields.mMatrixFlags &= ~SCALE;
-            } else {
-                mPrimitiveFields.mMatrixFlags |= SCALE;
-            }
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -211,12 +228,7 @@
     void setScaleY(float scaleY) {
         if (scaleY != mPrimitiveFields.mScaleY) {
             mPrimitiveFields.mScaleY = scaleY;
-            mPrimitiveFields.mMatrixDirty = true;
-            if (mPrimitiveFields.mScaleX == 1.0f && mPrimitiveFields.mScaleY == 1.0f) {
-                mPrimitiveFields.mMatrixFlags &= ~SCALE;
-            } else {
-                mPrimitiveFields.mMatrixFlags |= SCALE;
-            }
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
         }
     }
 
@@ -226,12 +238,7 @@
 
     void setPivotX(float pivotX) {
         mPrimitiveFields.mPivotX = pivotX;
-        mPrimitiveFields.mMatrixDirty = true;
-        if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) {
-            mPrimitiveFields.mMatrixFlags &= ~PIVOT;
-        } else {
-            mPrimitiveFields.mMatrixFlags |= PIVOT;
-        }
+        mPrimitiveFields.mMatrixOrPivotDirty = true;
         mPrimitiveFields.mPivotExplicitlySet = true;
     }
 
@@ -245,12 +252,7 @@
 
     void setPivotY(float pivotY) {
         mPrimitiveFields.mPivotY = pivotY;
-        mPrimitiveFields.mMatrixDirty = true;
-        if (mPrimitiveFields.mPivotX == 0.0f && mPrimitiveFields.mPivotY == 0.0f) {
-            mPrimitiveFields.mMatrixFlags &= ~PIVOT;
-        } else {
-            mPrimitiveFields.mMatrixFlags |= PIVOT;
-        }
+        mPrimitiveFields.mMatrixOrPivotDirty = true;
         mPrimitiveFields.mPivotExplicitlySet = true;
     }
 
@@ -264,7 +266,7 @@
 
     void setCameraDistance(float distance) {
         if (distance != getCameraDistance()) {
-            mPrimitiveFields.mMatrixDirty = true;
+            mPrimitiveFields.mMatrixOrPivotDirty = true;
             mComputedFields.mTransformCamera.setCameraLocation(0, 0, distance);
         }
     }
@@ -278,8 +280,8 @@
         if (left != mPrimitiveFields.mLeft) {
             mPrimitiveFields.mLeft = left;
             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -292,8 +294,8 @@
         if (top != mPrimitiveFields.mTop) {
             mPrimitiveFields.mTop = top;
             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -306,8 +308,8 @@
         if (right != mPrimitiveFields.mRight) {
             mPrimitiveFields.mRight = right;
             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -320,8 +322,8 @@
         if (bottom != mPrimitiveFields.mBottom) {
             mPrimitiveFields.mBottom = bottom;
             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -336,22 +338,23 @@
             mPrimitiveFields.mTop = top;
             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
 
     void setLeftTopRightBottom(int left, int top, int right, int bottom) {
-        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
+        if (left != mPrimitiveFields.mLeft || top != mPrimitiveFields.mTop
+                || right != mPrimitiveFields.mRight || bottom != mPrimitiveFields.mBottom) {
             mPrimitiveFields.mLeft = left;
             mPrimitiveFields.mTop = top;
             mPrimitiveFields.mRight = right;
             mPrimitiveFields.mBottom = bottom;
             mPrimitiveFields.mWidth = mPrimitiveFields.mRight - mPrimitiveFields.mLeft;
             mPrimitiveFields.mHeight = mPrimitiveFields.mBottom - mPrimitiveFields.mTop;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -360,8 +363,8 @@
         if (offset != 0) {
             mPrimitiveFields.mLeft += offset;
             mPrimitiveFields.mRight += offset;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -370,8 +373,8 @@
         if (offset != 0) {
             mPrimitiveFields.mTop += offset;
             mPrimitiveFields.mBottom += offset;
-            if (mPrimitiveFields.mMatrixFlags > TRANSLATION && !mPrimitiveFields.mPivotExplicitlySet) {
-                mPrimitiveFields.mMatrixDirty = true;
+            if (!mPrimitiveFields.mPivotExplicitlySet) {
+                mPrimitiveFields.mMatrixOrPivotDirty = true;
             }
         }
     }
@@ -392,11 +395,17 @@
         return mAnimationMatrix;
     }
 
-    uint32_t getMatrixFlags() const {
-        return mPrimitiveFields.mMatrixFlags;
+    bool hasTransformMatrix() const {
+        return getTransformMatrix() && !getTransformMatrix()->isIdentity();
+    }
+
+    // May only call this if hasTransformMatrix() is true
+    bool isTransformTranslateOnly() const {
+        return getTransformMatrix()->getType() == SkMatrix::kTranslate_Mask;
     }
 
     const SkMatrix* getTransformMatrix() const {
+        LOG_ALWAYS_FATAL_IF(mPrimitiveFields.mMatrixOrPivotDirty, "Cannot get a dirty matrix!");
         return mComputedFields.mTransformMatrix;
     }
 
@@ -452,14 +461,6 @@
     }
 
 private:
-    void onTranslationUpdate() {
-        mPrimitiveFields.mMatrixDirty = true;
-        if (mPrimitiveFields.mTranslationX == 0.0f && mPrimitiveFields.mTranslationY == 0.0f && mPrimitiveFields.mTranslationZ == 0.0f) {
-            mPrimitiveFields.mMatrixFlags &= ~TRANSLATION;
-        } else {
-            mPrimitiveFields.mMatrixFlags |= TRANSLATION;
-        }
-    }
 
     // Rendering properties
     struct PrimitiveFields {
@@ -472,20 +473,18 @@
         bool mProjectionReceiver;
         float mAlpha;
         bool mHasOverlappingRendering;
+        float mElevation;
         float mTranslationX, mTranslationY, mTranslationZ;
         float mRotation, mRotationX, mRotationY;
         float mScaleX, mScaleY;
         float mPivotX, mPivotY;
         int mLeft, mTop, mRight, mBottom;
         int mWidth, mHeight;
-        int mPrevWidth, mPrevHeight;
         bool mPivotExplicitlySet;
-        bool mMatrixDirty;
-        uint32_t mMatrixFlags;
+        bool mMatrixOrPivotDirty;
         bool mCaching;
     } mPrimitiveFields;
 
-    // mCameraDistance isn't in mPrimitiveFields as it has a complex setter
     SkMatrix* mStaticMatrix;
     SkMatrix* mAnimationMatrix;
 
@@ -506,7 +505,6 @@
         SkMatrix* mTransformMatrix;
 
         Sk3DView mTransformCamera;
-        SkMatrix* mTransformMatrix3D;
         SkPath* mClipPath; // TODO: remove this, create new ops for efficient/special case clipping
         SkRegion::Op mClipPathOp;
     } mComputedFields;
diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h
index efcea5f..3209a53 100644
--- a/libs/hwui/Renderer.h
+++ b/libs/hwui/Renderer.h
@@ -167,7 +167,7 @@
     virtual void concatMatrix(const SkMatrix* matrix) = 0;
 
     // clip
-    virtual const Rect& getClipBounds() const = 0;
+    virtual const Rect& getLocalClipBounds() const = 0;
     virtual bool quickRejectConservative(float left, float top,
             float right, float bottom) const = 0;
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op) = 0;
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index 4d0edfb..be49aed 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -22,6 +22,7 @@
 #include <utils/Trace.h>
 
 #include "AmbientShadow.h"
+#include "Caches.h"
 #include "ShadowTessellator.h"
 #include "SpotShadow.h"
 
@@ -41,9 +42,14 @@
 
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
-    const float heightFactor = 1.0f / 128;
+    float heightFactor = 1.0f / 128;
     const float geomFactor = 64;
 
+    Caches& caches = Caches::getInstance();
+    if (CC_UNLIKELY(caches.propertyAmbientRatio > 0.0f)) {
+        heightFactor *= caches.propertyAmbientRatio;
+    }
+
     Rect ambientShadowBounds(casterBounds);
     ambientShadowBounds.outset(maxZ * geomFactor * heightFactor);
 
@@ -62,16 +68,26 @@
 
 VertexBufferMode ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
         const Vector3* casterPolygon, int casterVertexCount,
-        const Vector3& lightPosScale, const mat4& receiverTransform,
+        const mat4& receiverTransform,
         int screenWidth, int screenHeight, const Rect& casterBounds,
         const Rect& localClip, VertexBuffer& shadowVertexBuffer) {
     ATRACE_CALL();
 
+    Caches& caches = Caches::getInstance();
+
     // A bunch of parameters to tweak the shadow.
     // TODO: Allow some of these changable by debug settings or APIs.
     int maximal = max(screenWidth, screenHeight);
-    Vector3 lightCenter(screenWidth * lightPosScale.x, screenHeight * lightPosScale.y,
-            maximal * lightPosScale.z);
+    Vector3 lightCenter(screenWidth * 0.5f, 0, maximal);
+
+    if (CC_UNLIKELY(caches.propertyLightPosY > 0)) {
+        lightCenter.y = - caches.propertyLightPosY; // negated since this shifts up
+    }
+    if (CC_UNLIKELY(caches.propertyLightPosZ > 0)) {
+        lightCenter.z = caches.propertyLightPosZ;
+    }
+
+
 #if DEBUG_SHADOW
     ALOGD("light center %f %f %f", lightCenter.x, lightCenter.y, lightCenter.z);
 #endif
@@ -82,9 +98,13 @@
     reverseReceiverTransform.loadInverse(receiverTransform);
     reverseReceiverTransform.mapPoint3d(lightCenter);
 
-    const float lightSize = maximal / 4;
+    float lightSize = maximal / 4;
     const int lightVertexCount = 8;
 
+    if (CC_UNLIKELY(caches.propertyLightDiameter > 0)) {
+        lightSize = caches.propertyLightDiameter;
+    }
+
     // Now light and caster are both in local space, we will check whether
     // the shadow is within the clip area.
     Rect lightRect = Rect(lightCenter.x - lightSize, lightCenter.y - lightSize,
@@ -169,5 +189,67 @@
     return centroid;
 }
 
+/**
+ * Test whether the polygon is order in clockwise.
+ *
+ * @param polygon the polygon as a Vector2 array
+ * @param len the number of points of the polygon
+ */
+bool ShadowTessellator::isClockwise(const Vector2* polygon, int len) {
+    double sum = 0;
+    double p1x = polygon[len - 1].x;
+    double p1y = polygon[len - 1].y;
+    for (int i = 0; i < len; i++) {
+
+        double p2x = polygon[i].x;
+        double p2y = polygon[i].y;
+        sum += p1x * p2y - p2x * p1y;
+        p1x = p2x;
+        p1y = p2y;
+    }
+    return sum < 0;
+}
+
+bool ShadowTessellator::isClockwisePath(const SkPath& path) {
+    SkPath::Iter iter(path, false);
+    SkPoint pts[4];
+    SkPath::Verb v;
+
+    Vector<Vector2> arrayForDirection;
+    while (SkPath::kDone_Verb != (v = iter.next(pts))) {
+            switch (v) {
+            case SkPath::kMove_Verb:
+                arrayForDirection.add(Vector2(pts[0].x(), pts[0].y()));
+                break;
+            case SkPath::kLine_Verb:
+                arrayForDirection.add(Vector2(pts[1].x(), pts[1].y()));
+                break;
+            case SkPath::kQuad_Verb:
+                arrayForDirection.add(Vector2(pts[1].x(), pts[1].y()));
+                arrayForDirection.add(Vector2(pts[2].x(), pts[2].y()));
+                break;
+            case SkPath::kCubic_Verb:
+                arrayForDirection.add(Vector2(pts[1].x(), pts[1].y()));
+                arrayForDirection.add(Vector2(pts[2].x(), pts[2].y()));
+                arrayForDirection.add(Vector2(pts[3].x(), pts[3].y()));
+                break;
+            default:
+                break;
+            }
+    }
+
+    return isClockwise(arrayForDirection.array(), arrayForDirection.size());
+}
+
+void ShadowTessellator::reverseVertexArray(Vertex* polygon, int len) {
+    int n = len / 2;
+    for (int i = 0; i < n; i++) {
+        Vertex tmp = polygon[i];
+        int k = len - 1 - i;
+        polygon[i] = polygon[k];
+        polygon[k] = tmp;
+    }
+}
+
 }; // namespace uirenderer
 }; // namespace android
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index ff3de74..e5a3da1 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -62,6 +62,8 @@
 
 #define SHADOW_MIN_CASTER_Z 0.001f
 
+#define MINIMAL_DELTA_THETA (M_PI / 180 / 1000)
+
 class ShadowTessellator {
 public:
     static VertexBufferMode tessellateAmbientShadow(bool isCasterOpaque,
@@ -71,13 +73,34 @@
 
     static VertexBufferMode tessellateSpotShadow(bool isCasterOpaque,
             const Vector3* casterPolygon, int casterVertexCount,
-            const Vector3& lightPosScale, const mat4& receiverTransform,
+            const mat4& receiverTransform,
             int screenWidth, int screenHeight, const Rect& casterBounds,
             const Rect& localClip, VertexBuffer& shadowVertexBuffer);
 
     static void generateShadowIndices(uint16_t*  shadowIndices);
 
     static Vector2 centroid2d(const Vector2* poly, int polyLength);
+
+    static bool isClockwise(const Vector2* polygon, int len);
+
+    /**
+     * Determine whether the path is clockwise, using the control points.
+     *
+     * TODO: Given the skia is using inverted Y coordinate, shadow system needs
+     * to convert to the same coordinate to avoid the extra reverse.
+     *
+     * @param path The path to be examined.
+     */
+    static bool isClockwisePath(const SkPath &path);
+
+    /**
+     * Reverse the vertex array.
+     *
+     * @param polygon The vertex array to be reversed.
+     * @param len The length of the vertex array.
+     */
+    static void reverseVertexArray(Vertex* polygon, int len);
+
 }; // ShadowTessellator
 
 }; // namespace uirenderer
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index 4f2a432..6a4a0c8 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -73,7 +73,7 @@
 }
 
 SkiaShader::SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
-        SkShader::TileMode tileY, SkMatrix* matrix, bool blend):
+        SkShader::TileMode tileY, const SkMatrix* matrix, bool blend):
         mType(type), mKey(key), mTileX(tileX), mTileY(tileY), mBlend(blend),
         mCaches(NULL) {
     setMatrix(matrix);
@@ -101,6 +101,49 @@
 }
 
 ///////////////////////////////////////////////////////////////////////////////
+// Layer shader
+///////////////////////////////////////////////////////////////////////////////
+
+SkiaLayerShader::SkiaLayerShader(Layer* layer, const SkMatrix* matrix):
+        SkiaShader(kBitmap, NULL, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode,
+                matrix, layer->isBlend()), mLayer(layer) {
+    updateLocalMatrix(matrix);
+}
+
+SkiaShader* SkiaLayerShader::copy() {
+    SkiaLayerShader* copy = new SkiaLayerShader();
+    copy->copyFrom(*this);
+    copy->mLayer = mLayer;
+    return copy;
+}
+
+void SkiaLayerShader::describe(ProgramDescription& description, const Extensions& extensions) {
+    description.hasBitmap = true;
+}
+
+void SkiaLayerShader::setupProgram(Program* program, const mat4& modelView,
+        const Snapshot& snapshot, GLuint* textureUnit) {
+    GLuint textureSlot = (*textureUnit)++;
+    Caches::getInstance().activeTexture(textureSlot);
+
+    const float width = mLayer->getWidth();
+    const float height = mLayer->getHeight();
+
+    mat4 textureTransform;
+    computeScreenSpaceMatrix(textureTransform, modelView);
+
+    // Uniforms
+    mLayer->bindTexture();
+    mLayer->setWrap(GL_CLAMP_TO_EDGE);
+    mLayer->setFilter(GL_LINEAR);
+
+    glUniform1i(program->getUniform("bitmapSampler"), textureSlot);
+    glUniformMatrix4fv(program->getUniform("textureTransform"), 1,
+            GL_FALSE, &textureTransform.data[0]);
+    glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height);
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Bitmap shader
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h
index 6015761..9f30257 100644
--- a/libs/hwui/SkiaShader.h
+++ b/libs/hwui/SkiaShader.h
@@ -58,7 +58,7 @@
     };
 
     ANDROID_API SkiaShader(Type type, SkShader* key, SkShader::TileMode tileX,
-            SkShader::TileMode tileY, SkMatrix* matrix, bool blend);
+            SkShader::TileMode tileY, const SkMatrix* matrix, bool blend);
     virtual ~SkiaShader();
 
     virtual SkiaShader* copy() = 0;
@@ -88,7 +88,7 @@
         return mGenerationId;
     }
 
-    void setMatrix(SkMatrix* matrix) {
+    void setMatrix(const SkMatrix* matrix) {
         updateLocalMatrix(matrix);
         mGenerationId++;
     }
@@ -134,6 +134,24 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 /**
+ * A shader that draws a layer.
+ */
+struct SkiaLayerShader: public SkiaShader {
+    SkiaLayerShader(Layer* layer, const SkMatrix* matrix);
+    SkiaShader* copy();
+
+    void describe(ProgramDescription& description, const Extensions& extensions);
+    void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot,
+            GLuint* textureUnit);
+
+private:
+    SkiaLayerShader() {
+    }
+
+    Layer* mLayer;
+}; // struct SkiaLayerShader
+
+/**
  * A shader that draws a bitmap.
  */
 struct SkiaBitmapShader: public SkiaShader {
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index 5bdb18a..038aea8 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -108,7 +108,12 @@
      * Returns the current clip in local coordinates. The clip rect is
      * transformed by the inverse transform matrix.
      */
-    ANDROID_API const Rect& getLocalClip();
+    const Rect& getLocalClip();
+
+    /**
+     * Returns the current clip in render target coordinates.
+     */
+    const Rect& getRenderTargetClip() { return *clipRect; }
 
     /**
      * Resets the clip to the specified rect.
@@ -238,7 +243,7 @@
 
     mat4 mTransformRoot;
     Rect mClipRectRoot;
-    Rect mLocalClip;
+    Rect mLocalClip; // don't use directly, call getLocalClip() which initializes this
 
     SkRegion mClipRegionRoot;
 
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 5fa0ba5..3ebe7b4 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -174,10 +174,10 @@
 int SpotShadow::intersection(const Vector2* poly1, int poly1Length,
         Vector2* poly2, int poly2Length) {
 #if DEBUG_SHADOW
-    if (!isClockwise(poly1, poly1Length)) {
+    if (!ShadowTessellator::isClockwise(poly1, poly1Length)) {
         ALOGW("Poly1 is not clockwise! Intersection is wrong!");
     }
-    if (!isClockwise(poly2, poly2Length)) {
+    if (!ShadowTessellator::isClockwise(poly2, poly2Length)) {
         ALOGW("Poly2 is not clockwise! Intersection is wrong!");
     }
 #endif
@@ -407,33 +407,12 @@
     if (polygon == 0  || len == 0) {
         return;
     }
-    if (!isClockwise(polygon, len)) {
+    if (!ShadowTessellator::isClockwise(polygon, len)) {
         reverse(polygon, len);
     }
 }
 
 /**
- * Test whether the polygon is order in clockwise.
- *
- * @param polygon the polygon as a Vector2 array
- * @param len the number of points of the polygon
- */
-bool SpotShadow::isClockwise(const Vector2* polygon, int len) {
-    double sum = 0;
-    double p1x = polygon[len - 1].x;
-    double p1y = polygon[len - 1].y;
-    for (int i = 0; i < len; i++) {
-
-        double p2x = polygon[i].x;
-        double p2y = polygon[i].y;
-        sum += p1x * p2y - p2x * p1y;
-        p1x = p2x;
-        p1y = p2y;
-    }
-    return sum < 0;
-}
-
-/**
  * Reverse the polygon
  *
  * @param polygon the polygon as a Vector2 array
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index 599d37e..fb3e6d5 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -56,7 +56,6 @@
 
     static bool testPointInsidePolygon(const Vector2 testPoint, const Vector2* poly, int len);
     static void makeClockwise(Vector2* polygon, int len);
-    static bool isClockwise(const Vector2* polygon, int len);
     static void reverse(Vector2* polygon, int len);
     static inline bool lineIntersection(double x1, double y1, double x2, double y2,
             double x3, double y3, double x4, double y4, Vector2& ret);
diff --git a/libs/hwui/StatefulBaseRenderer.h b/libs/hwui/StatefulBaseRenderer.h
index bf34bec..64354ac 100644
--- a/libs/hwui/StatefulBaseRenderer.h
+++ b/libs/hwui/StatefulBaseRenderer.h
@@ -75,7 +75,8 @@
     void concatMatrix(const Matrix4& matrix); // internal only convenience method
 
     // Clip
-    const Rect& getClipBounds() const { return mSnapshot->getLocalClip(); }
+    virtual const Rect& getLocalClipBounds() const { return mSnapshot->getLocalClip(); }
+
     virtual bool quickRejectConservative(float left, float top, float right, float bottom) const;
 
     virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
@@ -83,6 +84,8 @@
     virtual bool clipRegion(const SkRegion* region, SkRegion::Op op);
 
 protected:
+    const Rect& getRenderTargetClipBounds() const { return mSnapshot->getRenderTargetClip(); }
+
     int getWidth() { return mWidth; }
     int getHeight() { return mHeight; }
 
diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp
index 7923ce7..e783905 100644
--- a/libs/hwui/Texture.cpp
+++ b/libs/hwui/Texture.cpp
@@ -25,14 +25,14 @@
 namespace uirenderer {
 
 Texture::Texture(): id(0), generation(0), blend(false), width(0), height(0),
-        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
         mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
         mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
         mFirstFilter(true), mFirstWrap(true), mCaches(Caches::getInstance()) {
 }
 
 Texture::Texture(Caches& caches): id(0), generation(0), blend(false), width(0), height(0),
-        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL),
+        cleanup(false), bitmapSize(0), mipMap(false), uvMapper(NULL), isInUse(false),
         mWrapS(GL_CLAMP_TO_EDGE), mWrapT(GL_CLAMP_TO_EDGE),
         mMinFilter(GL_NEAREST), mMagFilter(GL_NEAREST),
         mFirstFilter(true), mFirstWrap(true), mCaches(caches) {
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index d48ec59..d5601f8 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -94,6 +94,12 @@
      */
     const UvMapper* uvMapper;
 
+    /**
+     * Whether or not the Texture is marked in use and thus not evictable for
+     * the current frame. This is reset at the start of a new frame.
+     */
+    bool isInUse;
+
 private:
     /**
      * Last wrap modes set on this texture. Defaults to GL_CLAMP_TO_EDGE.
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index 01d72d1..34e2265 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -121,29 +121,49 @@
 // Caching
 ///////////////////////////////////////////////////////////////////////////////
 
-Texture* TextureCache::get(const SkBitmap* bitmap) {
+void TextureCache::resetMarkInUse() {
+    LruCache<const SkBitmap*, Texture*>::Iterator iter(mCache);
+    while (iter.next()) {
+        iter.value()->isInUse = false;
+    }
+}
+
+bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
+    if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
+        ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
+                bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+        return false;
+    }
+    return true;
+}
+
+// Returns a prepared Texture* that either is already in the cache or can fit
+// in the cache (and is thus added to the cache)
+Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
     Texture* texture = mCache.get(bitmap);
 
     if (!texture) {
-        if (bitmap->width() > mMaxTextureSize || bitmap->height() > mMaxTextureSize) {
-            ALOGW("Bitmap too large to be uploaded into a texture (%dx%d, max=%dx%d)",
-                    bitmap->width(), bitmap->height(), mMaxTextureSize, mMaxTextureSize);
+        if (!canMakeTextureFromBitmap(bitmap)) {
             return NULL;
         }
 
         const uint32_t size = bitmap->rowBytes() * bitmap->height();
+        bool canCache = size < mMaxSize;
         // Don't even try to cache a bitmap that's bigger than the cache
-        if (size < mMaxSize) {
-            while (mSize + size > mMaxSize) {
+        while (canCache && mSize + size > mMaxSize) {
+            Texture* oldest = mCache.peekOldestValue();
+            if (oldest && !oldest->isInUse) {
                 mCache.removeOldest();
+            } else {
+                canCache = false;
             }
         }
 
-        texture = new Texture();
-        texture->bitmapSize = size;
-        generateTexture(bitmap, texture, false);
+        if (canCache) {
+            texture = new Texture();
+            texture->bitmapSize = size;
+            generateTexture(bitmap, texture, false);
 
-        if (size < mMaxSize) {
             mSize += size;
             TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d",
                      bitmap, texture->id, size, mSize);
@@ -151,16 +171,42 @@
                 ALOGD("Texture created, size = %d", size);
             }
             mCache.put(bitmap, texture);
-        } else {
-            texture->cleanup = true;
         }
-    } else if (bitmap->getGenerationID() != texture->generation) {
+    } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) {
+        // Texture was in the cache but is dirty, re-upload
+        // TODO: Re-adjust the cache size if the bitmap's dimensions have changed
         generateTexture(bitmap, texture, true);
     }
 
     return texture;
 }
 
+bool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) {
+    Texture* texture = getCachedTexture(bitmap);
+    if (texture) {
+        texture->isInUse = true;
+    }
+    return texture;
+}
+
+Texture* TextureCache::get(const SkBitmap* bitmap) {
+    Texture* texture = getCachedTexture(bitmap);
+
+    if (!texture) {
+        if (!canMakeTextureFromBitmap(bitmap)) {
+            return NULL;
+        }
+
+        const uint32_t size = bitmap->rowBytes() * bitmap->height();
+        texture = new Texture();
+        texture->bitmapSize = size;
+        generateTexture(bitmap, texture, false);
+        texture->cleanup = true;
+    }
+
+    return texture;
+}
+
 Texture* TextureCache::getTransient(const SkBitmap* bitmap) {
     Texture* texture = new Texture();
     texture->bitmapSize = bitmap->rowBytes() * bitmap->height();
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index e33c60d..48a10c2 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -62,6 +62,18 @@
     void operator()(const SkBitmap*& bitmap, Texture*& texture);
 
     /**
+     * Resets all Textures to not be marked as in use
+     */
+    void resetMarkInUse();
+
+    /**
+     * Attempts to precache the SkBitmap. Returns true if a Texture was successfully
+     * acquired for the bitmap, false otherwise. If a Texture was acquired it is
+     * marked as in use.
+     */
+    bool prefetchAndMarkInUse(const SkBitmap* bitmap);
+
+    /**
      * Returns the texture associated with the specified bitmap. If the texture
      * cannot be found in the cache, a new texture is generated.
      */
@@ -116,6 +128,11 @@
     void setFlushRate(float flushRate);
 
 private:
+
+    bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
+
+    Texture* getCachedTexture(const SkBitmap* bitmap);
+
     /**
      * Generates the texture from a bitmap into the specified texture structure.
      *
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
new file mode 100644
index 0000000..8957607
--- /dev/null
+++ b/libs/hwui/TreeInfo.h
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+#ifndef TREEINFO_H
+#define TREEINFO_H
+
+#include <cutils/compiler.h>
+#include <utils/Timers.h>
+#include <utils/StrongPointer.h>
+
+namespace android {
+namespace uirenderer {
+
+class RenderPropertyAnimator;
+
+class AnimationListener {
+public:
+    ANDROID_API virtual void onAnimationFinished(const sp<RenderPropertyAnimator>&) = 0;
+protected:
+    ANDROID_API virtual ~AnimationListener() {}
+};
+
+struct TreeInfo {
+    // The defaults here should be safe for everyone but DrawFrameTask to use as-is.
+    TreeInfo()
+            : hasFunctors(false)
+            , prepareTextures(false)
+            , performStagingPush(true)
+            , frameTimeMs(0)
+            , evaluateAnimations(false)
+            , hasAnimations(false)
+            , animationListener(0)
+    {}
+
+    bool hasFunctors;
+    bool prepareTextures;
+    bool performStagingPush;
+
+    // Animations
+    nsecs_t frameTimeMs;
+    bool evaluateAnimations;
+    // This is only updated if evaluateAnimations is true
+    bool hasAnimations;
+    AnimationListener* animationListener;
+
+    // TODO: Damage calculations
+};
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* TREEINFO_H */
diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp
index 5187f8f..d22cb8a 100644
--- a/libs/hwui/font/Font.cpp
+++ b/libs/hwui/font/Font.cpp
@@ -42,6 +42,7 @@
 
 Font::Font(FontRenderer* state, const Font::FontDescription& desc) :
         mState(state), mDescription(desc) {
+    mDeviceProperties = SkDeviceProperties::Make(SkDeviceProperties::Geometry::MakeDefault(), 1.0f);
 }
 
 Font::FontDescription::FontDescription(const SkPaint* paint, const mat4& matrix) {
@@ -272,7 +273,7 @@
     if (cachedGlyph) {
         // Is the glyph still in texture cache?
         if (!cachedGlyph->mIsValid) {
-            SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+            SkAutoGlyphCache autoCache(*paint, &mDeviceProperties, &mDescription.mLookupTransform);
             const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), textUnit);
             updateGlyphCache(paint, skiaGlyph, autoCache.getCache(), cachedGlyph, precaching);
         }
@@ -464,7 +465,7 @@
     CachedGlyphInfo* newGlyph = new CachedGlyphInfo();
     mCachedGlyphs.add(glyph, newGlyph);
 
-    SkAutoGlyphCache autoCache(*paint, NULL, &mDescription.mLookupTransform);
+    SkAutoGlyphCache autoCache(*paint, &mDeviceProperties, &mDescription.mLookupTransform);
     const SkGlyph& skiaGlyph = GET_METRICS(autoCache.getCache(), glyph);
     newGlyph->mIsValid = false;
     newGlyph->mGlyphIndex = skiaGlyph.fID;
diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h
index 02197bc..6ddd4f2 100644
--- a/libs/hwui/font/Font.h
+++ b/libs/hwui/font/Font.h
@@ -19,6 +19,8 @@
 
 #include <utils/KeyedVector.h>
 
+#include <SkScalar.h>
+#include <SkDeviceProperties.h>
 #include <SkGlyphCache.h>
 #include <SkScalerContext.h>
 #include <SkPaint.h>
@@ -146,6 +148,7 @@
     DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
 
     bool mIdentityTransform;
+    SkDeviceProperties mDeviceProperties;
 };
 
 inline int strictly_order_type(const Font::FontDescription& lhs,
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index af35344..63f4b95 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -91,7 +91,8 @@
     void destroy();
 
     bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
-    void makeCurrent(EGLSurface surface);
+    // Returns true if the current surface changed, false if it was already current
+    bool makeCurrent(EGLSurface surface);
     void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
     void swapBuffers(EGLSurface surface);
 
@@ -250,8 +251,8 @@
     mCurrentSurface = EGL_NO_SURFACE;
 }
 
-void GlobalContext::makeCurrent(EGLSurface surface) {
-    if (isCurrent(surface)) return;
+bool GlobalContext::makeCurrent(EGLSurface surface) {
+    if (isCurrent(surface)) return false;
 
     if (surface == EGL_NO_SURFACE) {
         // If we are setting EGL_NO_SURFACE we don't care about any of the potential
@@ -263,6 +264,7 @@
                 (void*)surface, egl_error_str());
     }
     mCurrentSurface = surface;
+    return true;
 }
 
 void GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) {
@@ -281,7 +283,6 @@
 void GlobalContext::swapBuffers(EGLSurface surface) {
     eglSwapBuffers(mEglDisplay, surface);
     EGLint err = eglGetError();
-    // TODO: Check whether we need to special case EGL_CONTEXT_LOST
     LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS,
             "Encountered EGL error %d %s during rendering", err, egl_error_str(err));
 }
@@ -307,24 +308,23 @@
     return value == EGL_BUFFER_PRESERVED;
 }
 
-CanvasContext::CanvasContext(bool translucent)
+CanvasContext::CanvasContext(bool translucent, RenderNode* rootRenderNode)
         : mRenderThread(RenderThread::getInstance())
         , mEglSurface(EGL_NO_SURFACE)
         , mDirtyRegionsEnabled(false)
         , mOpaque(!translucent)
         , mCanvas(0)
         , mHaveNewSurface(false)
-        , mInvokeFunctorsPending(false)
-        , mInvokeFunctorsTask(this) {
+        , mRootRenderNode(rootRenderNode) {
     mGlobalContext = GlobalContext::get();
 }
 
 CanvasContext::~CanvasContext() {
-    removeFunctorsTask();
-    destroyCanvas();
+    destroyCanvasAndSurface();
+    mRenderThread.removeFrameCallback(this);
 }
 
-void CanvasContext::destroyCanvas() {
+void CanvasContext::destroyCanvasAndSurface() {
     if (mCanvas) {
         delete mCanvas;
         mCanvas = 0;
@@ -347,8 +347,8 @@
 
     if (mEglSurface != EGL_NO_SURFACE) {
         mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface);
-        mGlobalContext->makeCurrent(mEglSurface);
         mHaveNewSurface = true;
+        makeCurrent();
     }
 }
 
@@ -360,7 +360,7 @@
 void CanvasContext::requireSurface() {
     LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
             "requireSurface() called but no surface set!");
-    mGlobalContext->makeCurrent(mEglSurface);
+    makeCurrent();
 }
 
 bool CanvasContext::initialize(EGLNativeWindowType window) {
@@ -385,22 +385,36 @@
     mCanvas->setViewport(width, height);
 }
 
-void CanvasContext::setDisplayListData(RenderNode* displayList, DisplayListData* newData) {
-    displayList->setData(newData);
+void CanvasContext::makeCurrent() {
+    // TODO: Figure out why this workaround is needed, see b/13913604
+    // In the meantime this matches the behavior of GLRenderer, so it is not a regression
+    mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface);
 }
 
-void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) {
-    mGlobalContext->makeCurrent(mEglSurface);
+void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters,
+        TreeInfo& info) {
+    LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!");
+    makeCurrent();
     for (size_t i = 0; i < layerUpdaters->size(); i++) {
         DeferredLayerUpdater* update = layerUpdaters->itemAt(i);
-        LOG_ALWAYS_FATAL_IF(!update->apply(), "Failed to update layer!");
+        bool success = update->apply(info);
+        LOG_ALWAYS_FATAL_IF(!success, "Failed to update layer!");
         if (update->backingLayer()->deferredUpdateScheduled) {
             mCanvas->pushLayerUpdate(update->backingLayer());
         }
     }
 }
 
-void CanvasContext::drawDisplayList(RenderNode* displayList, Rect* dirty) {
+void CanvasContext::prepareTree(TreeInfo& info) {
+    mRootRenderNode->prepareTree(info);
+
+    if (info.hasAnimations && !info.hasFunctors) {
+        // TODO: Functors
+        mRenderThread.postFrameCallback(this);
+    }
+}
+
+void CanvasContext::draw(Rect* dirty) {
     LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE,
             "drawDisplayList called on a context with no canvas or surface!");
 
@@ -414,7 +428,7 @@
     }
 
     status_t status;
-    if (dirty) {
+    if (dirty && !dirty->isEmpty()) {
         status = mCanvas->prepareDirty(dirty->left, dirty->top,
                 dirty->right, dirty->bottom, mOpaque);
     } else {
@@ -422,7 +436,7 @@
     }
 
     Rect outBounds;
-    status |= mCanvas->drawDisplayList(displayList, outBounds);
+    status |= mCanvas->drawDisplayList(mRootRenderNode.get(), outBounds);
 
     // TODO: Draw debug info
     // TODO: Performance tracking
@@ -434,60 +448,41 @@
     }
 }
 
-void InvokeFunctorsTask::run() {
-    mContext->invokeFunctors();
-}
+// Called by choreographer to do an RT-driven animation
+void CanvasContext::doFrame(nsecs_t frameTimeNanos) {
+    ATRACE_CALL();
 
-void CanvasContext::attachFunctor(Functor* functor) {
-    if (!mCanvas) return;
+    TreeInfo info;
+    info.evaluateAnimations = true;
+    info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNanos);
+    info.performStagingPush = false;
+    info.prepareTextures = false;
 
-    mCanvas->attachFunctor(functor);
-    removeFunctorsTask();
-    queueFunctorsTask(0);
-}
-
-void CanvasContext::detachFunctor(Functor* functor) {
-    if (!mCanvas) return;
-
-    mCanvas->detachFunctor(functor);
+    prepareTree(info);
+    draw(NULL);
 }
 
 void CanvasContext::invokeFunctor(Functor* functor) {
+    ATRACE_CALL();
     DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
     if (mGlobalContext->hasContext()) {
         requireGlContext();
         mode = DrawGlInfo::kModeProcess;
     }
-    (*functor)(mode, NULL);
-}
+    // TODO: Remove the dummy info in the future
+    DrawGlInfo dummyInfo;
+    memset(&dummyInfo, 0, sizeof(DrawGlInfo));
+    (*functor)(mode, &dummyInfo);
 
-void CanvasContext::invokeFunctors() {
-    mInvokeFunctorsPending = false;
-
-    if (!mCanvas) return;
-
-    requireSurface();
-    Rect dirty;
-    mCanvas->invokeFunctors(dirty);
-}
-
-void CanvasContext::removeFunctorsTask() {
-    if (!mInvokeFunctorsPending) return;
-
-    mInvokeFunctorsPending = false;
-    mRenderThread.remove(&mInvokeFunctorsTask);
-}
-
-void CanvasContext::queueFunctorsTask(int delayMs) {
-    if (mInvokeFunctorsPending) return;
-
-    mInvokeFunctorsPending = true;
-    mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs);
+    if (mCanvas) {
+        mCanvas->resume();
+    }
 }
 
 bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) {
     requireGlContext();
-    layer->apply();
+    TreeInfo info;
+    layer->apply(info);
     return LayerRenderer::copyLayer(layer->backingLayer(), bitmap);
 }
 
@@ -508,7 +503,7 @@
 
 void CanvasContext::requireGlContext() {
     if (mEglSurface != EGL_NO_SURFACE) {
-        mGlobalContext->makeCurrent(mEglSurface);
+        makeCurrent();
     } else {
         mGlobalContext->usePBufferSurface();
     }
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 9f64944..0873ad4 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -23,7 +23,9 @@
 #include <utils/Functor.h>
 #include <utils/Vector.h>
 
+#include "../RenderNode.h"
 #include "RenderTask.h"
+#include "RenderThread.h"
 
 #define FUNCTOR_PROCESS_DELAY 4
 
@@ -31,8 +33,6 @@
 namespace uirenderer {
 
 class DeferredLayerUpdater;
-class RenderNode;
-class DisplayListData;
 class OpenGLRenderer;
 class Rect;
 class Layer;
@@ -40,40 +40,29 @@
 namespace renderthread {
 
 class GlobalContext;
-class CanvasContext;
-class RenderThread;
-
-class InvokeFunctorsTask : public RenderTask {
-public:
-    InvokeFunctorsTask(CanvasContext* context)
-        : mContext(context) {}
-
-    virtual void run();
-
-private:
-    CanvasContext* mContext;
-};
 
 // This per-renderer class manages the bridge between the global EGL context
 // and the render surface.
-class CanvasContext {
+class CanvasContext : public IFrameCallback {
 public:
-    CanvasContext(bool translucent);
-    ~CanvasContext();
+    CanvasContext(bool translucent, RenderNode* rootRenderNode);
+    virtual ~CanvasContext();
 
     bool initialize(EGLNativeWindowType window);
     void updateSurface(EGLNativeWindowType window);
     void pauseSurface(EGLNativeWindowType window);
     void setup(int width, int height);
-    void setDisplayListData(RenderNode* displayList, DisplayListData* newData);
-    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters);
-    void drawDisplayList(RenderNode* displayList, Rect* dirty);
-    void destroyCanvas();
+    void makeCurrent();
+    void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, TreeInfo& info);
+    void prepareTree(TreeInfo& info);
+    void draw(Rect* dirty);
+    void destroyCanvasAndSurface();
+
+    // IFrameCallback, Chroreographer-driven frame callback entry point
+    virtual void doFrame(nsecs_t frameTimeNanos);
 
     bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap);
 
-    void attachFunctor(Functor* functor);
-    void detachFunctor(Functor* functor);
     void invokeFunctor(Functor* functor);
 
     void runWithGlContext(RenderTask* task);
@@ -86,11 +75,6 @@
     void swapBuffers();
     void requireSurface();
 
-    friend class InvokeFunctorsTask;
-    void invokeFunctors();
-    void removeFunctorsTask();
-    void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY);
-
     void requireGlContext();
 
     GlobalContext* mGlobalContext;
@@ -102,9 +86,7 @@
     OpenGLRenderer* mCanvas;
     bool mHaveNewSurface;
 
-    bool mInvokeFunctorsPending;
-    InvokeFunctorsTask mInvokeFunctorsTask;
-
+    const sp<RenderNode> mRootRenderNode;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 7b509a2..ff4be71 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -30,19 +30,7 @@
 namespace uirenderer {
 namespace renderthread {
 
-SetDisplayListData::SetDisplayListData() : mNewData(0) {}
-
-SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData)
-        : mTargetNode(node), mNewData(newData) {
-}
-
-SetDisplayListData::~SetDisplayListData() {}
-
-void SetDisplayListData::apply() const {
-    mTargetNode->setData(mNewData);
-}
-
-DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) {
+DrawFrameTask::DrawFrameTask() : mContext(0) {
 }
 
 DrawFrameTask::~DrawFrameTask() {
@@ -52,13 +40,6 @@
     mContext = context;
 }
 
-void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
-    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!");
-
-    SetDisplayListData setter(renderNode, newData);
-    mDisplayListDataUpdates.push(setter);
-}
-
 void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) {
     LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!");
 
@@ -74,37 +55,20 @@
     }
 }
 
-void DrawFrameTask::setRenderNode(RenderNode* renderNode) {
-    LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setRenderNode with!");
-
-    mRenderNode = renderNode;
-}
-
 void DrawFrameTask::setDirty(int left, int top, int right, int bottom) {
     mDirty.set(left, top, right, bottom);
 }
 
 void DrawFrameTask::drawFrame(RenderThread* renderThread) {
-    LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!");
     LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
 
-    postAndWait(renderThread, MODE_FULL);
+    postAndWait(renderThread);
 
     // Reset the single-frame data
     mDirty.setEmpty();
-    mRenderNode = 0;
 }
 
-void DrawFrameTask::flushStateChanges(RenderThread* renderThread) {
-    LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!");
-
-    postAndWait(renderThread, MODE_STATE_ONLY);
-}
-
-void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) {
-    LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!");
-
-    mTaskMode = mode;
+void DrawFrameTask::postAndWait(RenderThread* renderThread) {
     AutoMutex _lock(mLock);
     renderThread->queue(this);
     mSignal.wait(mLock);
@@ -113,48 +77,43 @@
 void DrawFrameTask::run() {
     ATRACE_NAME("DrawFrame");
 
-    syncFrameState();
-
-    if (mTaskMode == MODE_STATE_ONLY) {
-        unblockUiThread();
-        return;
-    }
+    bool canUnblockUiThread = syncFrameState();
 
     // Grab a copy of everything we need
-    Rect dirtyCopy(mDirty);
-    sp<RenderNode> renderNode = mRenderNode;
+    Rect dirty(mDirty);
     CanvasContext* context = mContext;
 
-    // This is temporary until WebView has a solution for syncing frame state
-    bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get());
-
     // From this point on anything in "this" is *UNSAFE TO ACCESS*
     if (canUnblockUiThread) {
         unblockUiThread();
     }
 
-    drawRenderNode(context, renderNode.get(), &dirtyCopy);
+    context->draw(&dirty);
 
     if (!canUnblockUiThread) {
         unblockUiThread();
     }
 }
 
-void DrawFrameTask::syncFrameState() {
+static void initTreeInfo(TreeInfo& info) {
+    info.prepareTextures = true;
+    info.performStagingPush = true;
+    info.evaluateAnimations = true;
+    // TODO: Get this from Choreographer
+    nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
+    info.frameTimeMs = nanoseconds_to_milliseconds(frameTimeNs);
+}
+
+bool DrawFrameTask::syncFrameState() {
     ATRACE_CALL();
-
-    for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) {
-        const SetDisplayListData& setter = mDisplayListDataUpdates[i];
-        setter.apply();
-    }
-    mDisplayListDataUpdates.clear();
-
-    mContext->processLayerUpdates(&mLayers);
-
-    // If we don't have an mRenderNode this is a state flush only
-    if (mRenderNode.get()) {
-        mRenderNode->updateProperties();
-    }
+    mContext->makeCurrent();
+    Caches::getInstance().textureCache.resetMarkInUse();
+    TreeInfo info;
+    initTreeInfo(info);
+    mContext->processLayerUpdates(&mLayers, info);
+    mContext->prepareTree(info);
+    // If prepareTextures is false, we ran out of texture cache space
+    return !info.hasFunctors && info.prepareTextures;
 }
 
 void DrawFrameTask::unblockUiThread() {
@@ -162,20 +121,6 @@
     mSignal.signal();
 }
 
-void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty) {
-    ATRACE_CALL();
-
-    if (dirty->bottom == -1 && dirty->left == -1
-            && dirty->top == -1 && dirty->right == -1) {
-        dirty = 0;
-    }
-    context->drawDisplayList(renderNode, dirty);
-}
-
-bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) {
-    return renderNode->hasFunctors();
-}
-
 } /* namespace renderthread */
 } /* namespace uirenderer */
 } /* namespace android */
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index 4e9b244..c280868 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -37,18 +37,6 @@
 class CanvasContext;
 class RenderThread;
 
-class SetDisplayListData {
-public:
-    // This ctor exists for Vector's usage
-    SetDisplayListData();
-    SetDisplayListData(RenderNode* node, DisplayListData* newData);
-    ~SetDisplayListData();
-    void apply() const;
-private:
-    sp<RenderNode> mTargetNode;
-    DisplayListData* mNewData;
-};
-
 /*
  * This is a special Super Task. It is re-used multiple times by RenderProxy,
  * and contains state (such as layer updaters & new DisplayListDatas) that is
@@ -62,32 +50,18 @@
 
     void setContext(CanvasContext* context);
 
-    void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
     void addLayer(DeferredLayerUpdater* layer);
     void removeLayer(DeferredLayerUpdater* layer);
 
-    void setRenderNode(RenderNode* renderNode);
     void setDirty(int left, int top, int right, int bottom);
     void drawFrame(RenderThread* renderThread);
-    void flushStateChanges(RenderThread* renderThread);
 
     virtual void run();
 
 private:
-    enum TaskMode {
-        MODE_INVALID,
-        MODE_FULL,
-        MODE_STATE_ONLY,
-    };
-
-    void postAndWait(RenderThread* renderThread, TaskMode mode);
-    void syncFrameState();
+    void postAndWait(RenderThread* renderThread);
+    bool syncFrameState();
     void unblockUiThread();
-    static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty);
-
-    // This checks to see if there are any drawGlFunctors which would require
-    // a synchronous drawRenderNode()
-    static bool requiresSynchronousDraw(RenderNode* renderNode);
 
     Mutex mLock;
     Condition mSignal;
@@ -97,10 +71,7 @@
     /*********************************************
      *  Single frame data
      *********************************************/
-    TaskMode mTaskMode;
-    sp<RenderNode> mRenderNode;
     Rect mDirty;
-    Vector<SetDisplayListData> mDisplayListDataUpdates;
 
     /*********************************************
      *  Multi frame data
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index a7c955e..87886e6 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -51,15 +51,16 @@
     MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \
     ARGS(method) *args = (ARGS(method) *) task->payload()
 
-CREATE_BRIDGE1(createContext, bool translucent) {
-    return new CanvasContext(args->translucent);
+CREATE_BRIDGE2(createContext, bool translucent, RenderNode* rootRenderNode) {
+    return new CanvasContext(args->translucent, args->rootRenderNode);
 }
 
-RenderProxy::RenderProxy(bool translucent)
+RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode)
         : mRenderThread(RenderThread::getInstance())
         , mContext(0) {
     SETUP_TASK(createContext);
     args->translucent = translucent;
+    args->rootRenderNode = rootRenderNode;
     mContext = (CanvasContext*) postAndWait(task);
     mDrawFrameTask.setContext(mContext);
 }
@@ -75,9 +76,6 @@
 
 void RenderProxy::destroyContext() {
     if (mContext) {
-        // Flush any pending changes to ensure all garbage is destroyed
-        mDrawFrameTask.flushStateChanges(&mRenderThread);
-
         SETUP_TASK(destroyContext);
         args->context = mContext;
         mContext = 0;
@@ -136,54 +134,24 @@
     post(task);
 }
 
-void RenderProxy::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) {
-    mDrawFrameTask.setDisplayListData(renderNode, newData);
-}
-
-void RenderProxy::drawDisplayList(RenderNode* displayList,
+void RenderProxy::syncAndDrawFrame(
         int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) {
-    mDrawFrameTask.setRenderNode(displayList);
     mDrawFrameTask.setDirty(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom);
     mDrawFrameTask.drawFrame(&mRenderThread);
 }
 
-CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) {
-    args->context->destroyCanvas();
+CREATE_BRIDGE1(destroyCanvasAndSurface, CanvasContext* context) {
+    args->context->destroyCanvasAndSurface();
     return NULL;
 }
 
-void RenderProxy::destroyCanvas() {
-    // If the canvas is being destroyed we won't be drawing again anytime soon
-    // So flush any pending state changes to allow for resource cleanup.
-    mDrawFrameTask.flushStateChanges(&mRenderThread);
-
-    SETUP_TASK(destroyCanvas);
+void RenderProxy::destroyCanvasAndSurface() {
+    SETUP_TASK(destroyCanvasAndSurface);
     args->context = mContext;
-    post(task);
-}
-
-CREATE_BRIDGE2(attachFunctor, CanvasContext* context, Functor* functor) {
-    args->context->attachFunctor(args->functor);
-    return NULL;
-}
-
-void RenderProxy::attachFunctor(Functor* functor) {
-    SETUP_TASK(attachFunctor);
-    args->context = mContext;
-    args->functor = functor;
-    post(task);
-}
-
-CREATE_BRIDGE2(detachFunctor, CanvasContext* context, Functor* functor) {
-    args->context->detachFunctor(args->functor);
-    return NULL;
-}
-
-void RenderProxy::detachFunctor(Functor* functor) {
-    SETUP_TASK(detachFunctor);
-    args->context = mContext;
-    args->functor = functor;
-    post(task);
+    // destroyCanvasAndSurface() needs a fence as when it returns the
+    // underlying BufferQueue is going to be released from under
+    // the render thread.
+    postAndWait(task);
 }
 
 CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) {
@@ -192,6 +160,7 @@
 }
 
 void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) {
+    ATRACE_CALL();
     SETUP_TASK(invokeFunctor);
     args->context = mContext;
     args->functor = functor;
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 489bf20c1..eab1395 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -56,20 +56,17 @@
  */
 class ANDROID_API RenderProxy {
 public:
-    ANDROID_API RenderProxy(bool translucent);
+    ANDROID_API RenderProxy(bool translucent, RenderNode* rootNode);
     ANDROID_API virtual ~RenderProxy();
 
     ANDROID_API bool initialize(const sp<ANativeWindow>& window);
     ANDROID_API void updateSurface(const sp<ANativeWindow>& window);
     ANDROID_API void pauseSurface(const sp<ANativeWindow>& window);
     ANDROID_API void setup(int width, int height);
-    ANDROID_API void setDisplayListData(RenderNode* renderNode, DisplayListData* newData);
-    ANDROID_API void drawDisplayList(RenderNode* displayList,
+    ANDROID_API void syncAndDrawFrame(
             int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom);
-    ANDROID_API void destroyCanvas();
+    ANDROID_API void destroyCanvasAndSurface();
 
-    ANDROID_API void attachFunctor(Functor* functor);
-    ANDROID_API void detachFunctor(Functor* functor);
     ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion);
 
     ANDROID_API void runWithGlContext(RenderTask* task);
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index 212f475..e95707a 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -18,9 +18,11 @@
 
 #include "RenderThread.h"
 
+#include <gui/DisplayEventReceiver.h>
+#include <utils/Log.h>
+
 #include "CanvasContext.h"
 #include "RenderProxy.h"
-#include <utils/Log.h>
 
 namespace android {
 using namespace uirenderer::renderthread;
@@ -29,6 +31,14 @@
 namespace uirenderer {
 namespace renderthread {
 
+// Number of events to read at a time from the DisplayEventReceiver pipe.
+// The value should be large enough that we can quickly drain the pipe
+// using just a few large reads.
+static const size_t EVENT_BUFFER_SIZE = 100;
+
+// Slight delay to give the UI time to push us a new frame before we replay
+static const int DISPATCH_FRAME_CALLBACKS_DELAY = 0;
+
 TaskQueue::TaskQueue() : mHead(0), mTail(0) {}
 
 RenderTask* TaskQueue::next() {
@@ -103,8 +113,25 @@
     }
 }
 
+class DispatchFrameCallbacks : public RenderTask {
+private:
+    RenderThread* mRenderThread;
+public:
+    DispatchFrameCallbacks(RenderThread* rt) : mRenderThread(rt) {}
+
+    virtual void run() {
+        mRenderThread->dispatchFrameCallbacks();
+    }
+};
+
 RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>()
-        , mNextWakeup(LLONG_MAX) {
+        , mNextWakeup(LLONG_MAX)
+        , mDisplayEventReceiver(0)
+        , mVsyncRequested(false)
+        , mFrameCallbackTaskPending(false)
+        , mFrameCallbackTask(0)
+        , mFrameTime(0) {
+    mFrameCallbackTask = new DispatchFrameCallbacks(this);
     mLooper = new Looper(false);
     run("RenderThread");
 }
@@ -112,10 +139,86 @@
 RenderThread::~RenderThread() {
 }
 
+void RenderThread::initializeDisplayEventReceiver() {
+    LOG_ALWAYS_FATAL_IF(mDisplayEventReceiver, "Initializing a second DisplayEventReceiver?");
+    mDisplayEventReceiver = new DisplayEventReceiver();
+    status_t status = mDisplayEventReceiver->initCheck();
+    LOG_ALWAYS_FATAL_IF(status != NO_ERROR, "Initialization of DisplayEventReceiver "
+            "failed with status: %d", status);
+
+    // Register the FD
+    mLooper->addFd(mDisplayEventReceiver->getFd(), 0,
+            Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this);
+}
+
+int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) {
+    if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) {
+        ALOGE("Display event receiver pipe was closed or an error occurred.  "
+                "events=0x%x", events);
+        return 0; // remove the callback
+    }
+
+    if (!(events & Looper::EVENT_INPUT)) {
+        ALOGW("Received spurious callback for unhandled poll event.  "
+                "events=0x%x", events);
+        return 1; // keep the callback
+    }
+
+    reinterpret_cast<RenderThread*>(data)->drainDisplayEventQueue();
+
+    return 1; // keep the callback
+}
+
+static nsecs_t latestVsyncEvent(DisplayEventReceiver* receiver) {
+    DisplayEventReceiver::Event buf[EVENT_BUFFER_SIZE];
+    nsecs_t latest = 0;
+    ssize_t n;
+    while ((n = receiver->getEvents(buf, EVENT_BUFFER_SIZE)) > 0) {
+        for (ssize_t i = 0; i < n; i++) {
+            const DisplayEventReceiver::Event& ev = buf[i];
+            switch (ev.header.type) {
+            case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
+                latest = ev.header.timestamp;
+                break;
+            }
+        }
+    }
+    if (n < 0) {
+        ALOGW("Failed to get events from display event receiver, status=%d", status_t(n));
+    }
+    return latest;
+}
+
+void RenderThread::drainDisplayEventQueue() {
+    nsecs_t vsyncEvent = latestVsyncEvent(mDisplayEventReceiver);
+    if (vsyncEvent > 0) {
+        mVsyncRequested = false;
+        mFrameTime = vsyncEvent;
+        if (!mFrameCallbackTaskPending) {
+            mFrameCallbackTaskPending = true;
+            //queueDelayed(mFrameCallbackTask, DISPATCH_FRAME_CALLBACKS_DELAY);
+            queue(mFrameCallbackTask);
+        }
+    }
+}
+
+void RenderThread::dispatchFrameCallbacks() {
+    mFrameCallbackTaskPending = false;
+
+    std::set<IFrameCallback*> callbacks;
+    mFrameCallbacks.swap(callbacks);
+
+    for (std::set<IFrameCallback*>::iterator it = callbacks.begin(); it != callbacks.end(); it++) {
+        (*it)->doFrame(mFrameTime);
+    }
+}
+
 bool RenderThread::threadLoop() {
+    initializeDisplayEventReceiver();
+
     int timeoutMillis = -1;
     for (;;) {
-        int result = mLooper->pollAll(timeoutMillis);
+        int result = mLooper->pollOnce(timeoutMillis);
         LOG_ALWAYS_FATAL_IF(result == Looper::POLL_ERROR,
                 "RenderThread Looper POLL_ERROR!");
 
@@ -159,6 +262,20 @@
     mQueue.remove(task);
 }
 
+void RenderThread::postFrameCallback(IFrameCallback* callback) {
+    mFrameCallbacks.insert(callback);
+    if (!mVsyncRequested) {
+        mVsyncRequested = true;
+        status_t status = mDisplayEventReceiver->requestNextVsync();
+        LOG_ALWAYS_FATAL_IF(status != NO_ERROR,
+                "requestNextVsync failed with status: %d", status);
+    }
+}
+
+void RenderThread::removeFrameCallback(IFrameCallback* callback) {
+    mFrameCallbacks.erase(callback);
+}
+
 RenderTask* RenderThread::nextTask(nsecs_t* nextWakeup) {
     AutoMutex _lock(mLock);
     RenderTask* next = mQueue.peek();
diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h
index e444aa0..b93dfd6 100644
--- a/libs/hwui/renderthread/RenderThread.h
+++ b/libs/hwui/renderthread/RenderThread.h
@@ -18,6 +18,10 @@
 #define RENDERTHREAD_H_
 
 #include "RenderTask.h"
+
+#include <memory>
+#include <set>
+
 #include <cutils/compiler.h>
 #include <utils/Looper.h>
 #include <utils/Mutex.h>
@@ -25,9 +29,13 @@
 #include <utils/Thread.h>
 
 namespace android {
+class DisplayEventReceiver;
+
 namespace uirenderer {
 namespace renderthread {
 
+class DispatchFrameCallbacks;
+
 class TaskQueue {
 public:
     TaskQueue();
@@ -42,6 +50,15 @@
     RenderTask* mTail;
 };
 
+// Mimics android.view.Choreographer.FrameCallback
+class IFrameCallback {
+public:
+    virtual void doFrame(nsecs_t frameTimeNanos) = 0;
+
+protected:
+    ~IFrameCallback() {}
+};
+
 class ANDROID_API RenderThread : public Thread, public Singleton<RenderThread> {
 public:
     // RenderThread takes complete ownership of tasks that are queued
@@ -50,15 +67,25 @@
     void queueDelayed(RenderTask* task, int delayMs);
     void remove(RenderTask* task);
 
+    // Mimics android.view.Choreographer
+    void postFrameCallback(IFrameCallback* callback);
+    void removeFrameCallback(IFrameCallback* callback);
+
 protected:
     virtual bool threadLoop();
 
 private:
     friend class Singleton<RenderThread>;
+    friend class DispatchFrameCallbacks;
 
     RenderThread();
     virtual ~RenderThread();
 
+    void initializeDisplayEventReceiver();
+    static int displayEventReceiverCallback(int fd, int events, void* data);
+    void drainDisplayEventQueue();
+    void dispatchFrameCallbacks();
+
     // Returns the next task to be run. If this returns NULL nextWakeup is set
     // to the time to requery for the nextTask to run. mNextWakeup is also
     // set to this time
@@ -69,6 +96,13 @@
 
     nsecs_t mNextWakeup;
     TaskQueue mQueue;
+
+    DisplayEventReceiver* mDisplayEventReceiver;
+    bool mVsyncRequested;
+    std::set<IFrameCallback*> mFrameCallbacks;
+    bool mFrameCallbackTaskPending;
+    DispatchFrameCallbacks* mFrameCallbackTask;
+    nsecs_t mFrameTime;
 };
 
 } /* namespace renderthread */
diff --git a/libs/hwui/utils/MathUtils.h b/libs/hwui/utils/MathUtils.h
new file mode 100644
index 0000000..7deabe9
--- /dev/null
+++ b/libs/hwui/utils/MathUtils.h
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ */
+#ifndef MATHUTILS_H
+#define MATHUTILS_H
+
+namespace android {
+namespace uirenderer {
+
+class MathUtils {
+private:
+    static const float gNonZeroEpsilon = 0.001f;
+public:
+    /**
+     * Check for floats that are close enough to zero.
+     */
+    inline static bool isZero(float value) {
+        return (value >= -gNonZeroEpsilon) && (value <= gNonZeroEpsilon);
+    }
+
+    inline static bool isPositive(float value) {
+        return value >= gNonZeroEpsilon;
+    }
+}; // class MathUtils
+
+} /* namespace uirenderer */
+} /* namespace android */
+
+#endif /* RENDERNODE_H */
diff --git a/location/java/android/location/FusedBatchOptions.java b/location/java/android/location/FusedBatchOptions.java
index 623d707..5600aeb 100644
--- a/location/java/android/location/FusedBatchOptions.java
+++ b/location/java/android/location/FusedBatchOptions.java
@@ -95,8 +95,9 @@
     }
 
     public static final class BatchFlags {
-        public static int WAKEUP_ON_FIFO_FULL = 1<<0;
-        public static int CALLBACK_ON_LOCATION_FIX = 1<<1;
+        // follow the definitions to the letter in fused_location.h
+        public static int WAKEUP_ON_FIFO_FULL = 0x0000001;
+        public static int CALLBACK_ON_LOCATION_FIX =0x0000002;
     }
 
     /*
diff --git a/media/java/android/media/AudioFormat.java b/media/java/android/media/AudioFormat.java
index 04c6e97..ad0d459 100644
--- a/media/java/android/media/AudioFormat.java
+++ b/media/java/android/media/AudioFormat.java
@@ -88,12 +88,22 @@
 
     public static final int CHANNEL_OUT_MONO = CHANNEL_OUT_FRONT_LEFT;
     public static final int CHANNEL_OUT_STEREO = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT);
+    // aka QUAD_BACK
     public static final int CHANNEL_OUT_QUAD = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+    /** @hide */
+    public static final int CHANNEL_OUT_QUAD_SIDE = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT);
     public static final int CHANNEL_OUT_SURROUND = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_BACK_CENTER);
+    // aka 5POINT1_BACK
     public static final int CHANNEL_OUT_5POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT);
+    /** @hide */
+    public static final int CHANNEL_OUT_5POINT1_SIDE = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
+            CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY |
+            CHANNEL_OUT_SIDE_LEFT | CHANNEL_OUT_SIDE_RIGHT);
+    // TODO does this need an @deprecated ?
     // different from AUDIO_CHANNEL_OUT_7POINT1
     public static final int CHANNEL_OUT_7POINT1 = (CHANNEL_OUT_FRONT_LEFT | CHANNEL_OUT_FRONT_RIGHT |
             CHANNEL_OUT_FRONT_CENTER | CHANNEL_OUT_LOW_FREQUENCY | CHANNEL_OUT_BACK_LEFT | CHANNEL_OUT_BACK_RIGHT |
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 8ae06e0..1dcfcb8 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -25,6 +25,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.media.RemoteController.OnClientUpdateListener;
+import android.media.session.MediaSessionLegacyHelper;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -48,6 +49,12 @@
  */
 public class AudioManager {
 
+    // If we should use the new sessions APIs.
+    private final static boolean USE_SESSIONS = true;
+    // If we should use the legacy APIs. If both are true information will be
+    // duplicated through both paths. Currently this flag isn't used.
+    private final static boolean USE_LEGACY = true;
+
     private final Context mContext;
     private long mVolumeKeyUpTime;
     private final boolean mUseMasterVolume;
@@ -421,6 +428,7 @@
     public static final int USE_DEFAULT_STREAM_TYPE = Integer.MIN_VALUE;
 
     private static IAudioService sService;
+    private MediaSessionLegacyHelper mSessionHelper;
 
     /**
      * @hide
@@ -431,6 +439,9 @@
                 com.android.internal.R.bool.config_useMasterVolume);
         mUseVolumeKeySounds = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_useVolumeKeySounds);
+        if (USE_SESSIONS) {
+            mSessionHelper = MediaSessionLegacyHelper.getHelper(context);
+        }
     }
 
     private static IAudioService getService()
@@ -2166,6 +2177,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerMediaButtonIntent"+e);
         }
+        if (USE_SESSIONS) {
+            mSessionHelper.addMediaButtonListener(pi, mContext);
+        }
     }
 
     /**
@@ -2239,6 +2253,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in unregisterMediaButtonIntent"+e);
         }
+        if (USE_SESSIONS) {
+            mSessionHelper.removeMediaButtonListener(pi);
+        }
     }
 
     /**
@@ -2263,6 +2280,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in registerRemoteControlClient"+e);
         }
+        if (USE_SESSIONS) {
+            rcClient.registerWithSession(mSessionHelper);
+        }
     }
 
     /**
@@ -2282,6 +2302,9 @@
         } catch (RemoteException e) {
             Log.e(TAG, "Dead object in unregisterRemoteControlClient"+e);
         }
+        if (USE_SESSIONS) {
+            rcClient.unregisterWithSession(mSessionHelper);
+        }
     }
 
     /**
diff --git a/media/java/android/media/AudioService.java b/media/java/android/media/AudioService.java
index 7f1c5c7..4513ead 100644
--- a/media/java/android/media/AudioService.java
+++ b/media/java/android/media/AudioService.java
@@ -43,6 +43,7 @@
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.database.ContentObserver;
+import android.hardware.usb.UsbManager;
 import android.media.MediaPlayer.OnCompletionListener;
 import android.media.MediaPlayer.OnErrorListener;
 import android.os.Binder;
@@ -528,6 +529,7 @@
         intentFilter.addAction(Intent.ACTION_SCREEN_ON);
         intentFilter.addAction(Intent.ACTION_SCREEN_OFF);
         intentFilter.addAction(Intent.ACTION_USER_SWITCHED);
+        intentFilter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
 
         intentFilter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
         // TODO merge orientation and rotation
@@ -3975,7 +3977,8 @@
                     (device == AudioSystem.DEVICE_OUT_WIRED_HEADPHONE))) {
                 setBluetoothA2dpOnInt(true);
             }
-            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0);
+            boolean isUsb = ((device & AudioSystem.DEVICE_OUT_ALL_USB) != 0) ||
+                            ((device & AudioSystem.DEVICE_IN_ALL_USB) != 0);
             handleDeviceConnection((state == 1), device, (isUsb ? name : ""));
             if (state != 0) {
                 if ((device == AudioSystem.DEVICE_OUT_WIRED_HEADSET) ||
@@ -4080,20 +4083,41 @@
                         }
                     }
                 }
-            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ||
-                           action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
+            } else if (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG)) {
                 state = intent.getIntExtra("state", 0);
+
                 int alsaCard = intent.getIntExtra("card", -1);
                 int alsaDevice = intent.getIntExtra("device", -1);
+
                 String params = (alsaCard == -1 && alsaDevice == -1 ? ""
                                     : "card=" + alsaCard + ";device=" + alsaDevice);
-                device = action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
-                        AudioSystem.DEVICE_OUT_USB_ACCESSORY : AudioSystem.DEVICE_OUT_USB_DEVICE;
-                Log.v(TAG, "Broadcast Receiver: Got "
-                        + (action.equals(Intent.ACTION_USB_AUDIO_ACCESSORY_PLUG) ?
-                              "ACTION_USB_AUDIO_ACCESSORY_PLUG" : "ACTION_USB_AUDIO_DEVICE_PLUG")
-                        + ", state = " + state + ", card: " + alsaCard + ", device: " + alsaDevice);
+
+                // Playback Device
+                device = AudioSystem.DEVICE_OUT_USB_ACCESSORY;
                 setWiredDeviceConnectionState(device, state, params);
+            } else if (action.equals(Intent.ACTION_USB_AUDIO_DEVICE_PLUG)) {
+                state = intent.getIntExtra("state", 0);
+
+                int alsaCard = intent.getIntExtra("card", -1);
+                int alsaDevice = intent.getIntExtra("device", -1);
+                boolean hasPlayback = intent.getBooleanExtra("hasPlayback", false);
+                boolean hasCapture = intent.getBooleanExtra("hasCapture", false);
+                boolean hasMIDI = intent.getBooleanExtra("hasMIDI", false);
+
+                String params = (alsaCard == -1 && alsaDevice == -1 ? ""
+                                    : "card=" + alsaCard + ";device=" + alsaDevice);
+
+                // Playback Device
+                if (hasPlayback) {
+                    device = AudioSystem.DEVICE_OUT_USB_DEVICE;
+                    setWiredDeviceConnectionState(device, state, params);
+                }
+
+                // Capture Device
+                if (hasCapture) {
+                    device = AudioSystem.DEVICE_IN_USB_DEVICE;
+                    setWiredDeviceConnectionState(device, state, params);
+                }
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
@@ -4199,7 +4223,7 @@
                         mStreamStates[AudioSystem.STREAM_MUSIC], 0);
             }
         }
-    }
+    } // end class AudioServiceBroadcastReceiver
 
     //==========================================================================================
     // RemoteControlDisplay / RemoteControlClient / Remote info
diff --git a/media/java/android/media/AudioSystem.java b/media/java/android/media/AudioSystem.java
index 9c67bae..327c10c 100644
--- a/media/java/android/media/AudioSystem.java
+++ b/media/java/android/media/AudioSystem.java
@@ -288,6 +288,8 @@
                                              DEVICE_IN_USB_DEVICE |
                                              DEVICE_IN_DEFAULT);
     public static final int DEVICE_IN_ALL_SCO = DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+    public static final int DEVICE_IN_ALL_USB = (DEVICE_IN_USB_ACCESSORY |
+                                                 DEVICE_IN_USB_DEVICE);
 
     // device states, must match AudioSystem::device_connection_state
     public static final int DEVICE_STATE_UNAVAILABLE = 0;
diff --git a/media/java/android/media/DngCreator.java b/media/java/android/media/DngCreator.java
new file mode 100644
index 0000000..b2a38ab
--- /dev/null
+++ b/media/java/android/media/DngCreator.java
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media;
+
+import android.graphics.Bitmap;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CaptureResult;
+import android.location.Location;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * The {@link DngCreator} class provides functions to write raw pixel data as a DNG file.
+ *
+ * <p>
+ * This class is designed to be used with the {@link android.graphics.ImageFormat#RAW_SENSOR}
+ * buffers available from {@link android.hardware.camera2.CameraDevice}, or with Bayer-type raw
+ * pixel data that is otherwise generated by an application.  The DNG metadata tags will be
+ * generated from a {@link android.hardware.camera2.CaptureResult} object or set directly.
+ * </p>
+ *
+ * <p>
+ * The DNG file format is a cross-platform file format that is used to store pixel data from
+ * camera sensors with minimal pre-processing applied.  DNG files allow for pixel data to be
+ * defined in a user-defined colorspace, and have associated metadata that allow for this
+ * pixel data to be converted to the standard CIE XYZ colorspace during post-processing.
+ * </p>
+ *
+ * <p>
+ * For more information on the DNG file format and associated metadata, please refer to the
+ * <a href=
+ * "https://wwwimages2.adobe.com/content/dam/Adobe/en/products/photoshop/pdfs/dng_spec_1.4.0.0.pdf">
+ * Adobe DNG 1.4.0.0 specification</a>.
+ * </p>
+ */
+public final class DngCreator {
+
+    /**
+     * Create a new DNG object.
+     *
+     * <p>
+     * It is not necessary to call any set methods to write a well-formatted DNG file.
+     * </p>
+     * <p>
+     * DNG metadata tags will be generated from the corresponding parameters in the
+     * {@link android.hardware.camera2.CaptureResult} object.  This removes or overrides
+     * all previous tags set.
+     * </p>
+     *
+     * @param characteristics an object containing the static
+     *          {@link android.hardware.camera2.CameraCharacteristics}.
+     * @param metadata a metadata object to generate tags from.
+     */
+    public DngCreator(CameraCharacteristics characteristics, CaptureResult metadata) {/*TODO*/}
+
+    /**
+     * Set the orientation value to write.
+     *
+     * <p>
+     * This will be written as the TIFF "Orientation" tag {@code (0x0112)}.
+     * Calling this will override any prior settings for this tag.
+     * </p>
+     *
+     * @param orientation the orientation value to set, one of:
+     *                    <ul>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_NORMAL}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_HORIZONTAL}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_180}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_FLIP_VERTICAL}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_TRANSPOSE}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_90}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_TRANSVERSE}</li>
+     *                      <li>{@link android.media.ExifInterface#ORIENTATION_ROTATE_270}</li>
+     *                    </ul>
+     * @return this {@link #DngCreator} object.
+     */
+    public DngCreator setOrientation(int orientation) {
+        return this;
+    }
+
+    /**
+     * Set the thumbnail image.
+     *
+     * <p>
+     * Pixel data will be converted to a Baseline TIFF RGB image, with 8 bits per color channel.
+     * The alpha channel will be discarded.
+     * </p>
+     *
+     * <p>
+     * The given bitmap should not be altered while this object is in use.
+     * </p>
+     *
+     * @param pixels a {@link android.graphics.Bitmap} of pixel data.
+     * @return this {@link #DngCreator} object.
+     */
+    public DngCreator setThumbnail(Bitmap pixels) {
+        return this;
+    }
+
+    /**
+     * Set the thumbnail image.
+     *
+     * <p>
+     * Pixel data is interpreted as a {@link android.graphics.ImageFormat#YUV_420_888} image.
+     * </p>
+     *
+     * <p>
+     * The given image should not be altered while this object is in use.
+     * </p>
+     *
+     * @param pixels an {@link android.media.Image} object with the format
+     *               {@link android.graphics.ImageFormat#YUV_420_888}.
+     * @return this {@link #DngCreator} object.
+     */
+    public DngCreator setThumbnail(Image pixels) {
+        return this;
+    }
+
+
+    /**
+     * Set image location metadata.
+     *
+     * <p>
+     * The given location object must contain at least a valid time, latitude, and longitude
+     * (equivalent to the values returned by {@link android.location.Location#getTime()},
+     * {@link android.location.Location#getLatitude()}, and
+     * {@link android.location.Location#getLongitude()} methods).
+     * </p>
+     *
+     * @param location an {@link android.location.Location} object to set.
+     * @return this {@link #DngCreator} object.
+     *
+     * @throws java.lang.IllegalArgumentException if the given location object doesn't
+     *          contain enough information to set location metadata.
+     */
+    public DngCreator setLocation(Location location) { return this; }
+
+    /**
+     * Set the user description string to write.
+     *
+     * <p>
+     * This is equivalent to setting the TIFF "ImageDescription" tag {@code (0x010E)}.
+     * </p>
+     *
+     * @param description the user description string.
+     * @return this {@link #DngCreator} object.
+     */
+    public DngCreator setDescription(String description) {
+        return this;
+    }
+
+    /**
+     * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
+     * the currently configured metadata.
+     *
+     * <p>
+     * Raw pixel data must have 16 bits per pixel, and the input must contain at least
+     * {@code offset + 2 * (stride * (height - 1) + width * height)} bytes.  The width and height of
+     * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
+     * and will typically be equal to the width and height of
+     * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+     * If insufficient metadata is set to write a well-formatted DNG file, and
+     * {@link java.lang.IllegalStateException} will be thrown.
+     * </p>
+     *
+     * <p>
+     * When reading from the pixel input, {@code stride} pixels will be skipped
+     * after each row (excluding the last).
+     * </p>
+     *
+     * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+     * @param pixels an {@link java.io.InputStream} of pixel data to write.
+     * @param stride the stride of the raw image in pixels.
+     * @param offset the offset of the raw image in bytes.  This indicates how many bytes will
+     *               be skipped in the input before any pixel data is read.
+     *
+     * @throws IOException if an error was encountered in the input or output stream.
+     * @throws java.lang.IllegalStateException if not enough metadata information has been
+     *          set to write a well-formatted DNG file.
+     */
+    public void writeInputStream(OutputStream dngOutput, InputStream pixels, int stride,
+                                 long offset) throws IOException {
+        /*TODO*/
+    }
+
+    /**
+     * Write the {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data to a DNG file with
+     * the currently configured metadata.
+     *
+     * <p>
+     * Raw pixel data must have 16 bits per pixel, and the input must contain at least
+     * {@code offset + 2 * (stride * (height - 1) + width * height)} bytes.  The width and height of
+     * the input are taken from the width and height set in the {@link DngCreator} metadata tags,
+     * and will typically be equal to the width and height of
+     * {@link android.hardware.camera2.CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}.
+     * If insufficient metadata is set to write a well-formatted DNG file, and
+     * {@link java.lang.IllegalStateException} will be thrown.
+     * </p>
+     *
+     * <p>
+     * When reading from the pixel input, {@code stride} pixels will be skipped
+     * after each row (excluding the last).
+     * </p>
+     *
+     * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+     * @param pixels an {@link java.nio.ByteBuffer} of pixel data to write.
+     * @param stride the stride of the raw image in pixels.
+     * @param offset the offset of the raw image in bytes.  This indicates how many bytes will
+     *               be skipped in the input before any pixel data is read.
+     *
+     * @throws IOException if an error was encountered in the input or output stream.
+     * @throws java.lang.IllegalStateException if not enough metadata information has been
+     *          set to write a well-formatted DNG file.
+     */
+    public void writeByteBuffer(OutputStream dngOutput, ByteBuffer pixels, int stride,
+                                long offset) throws IOException {/*TODO*/}
+
+    /**
+     * Write the pixel data to a DNG file with the currently configured metadata.
+     *
+     * <p>
+     * For this method to succeed, the {@link android.media.Image} input must contain
+     * {@link android.graphics.ImageFormat#RAW_SENSOR} pixel data, otherwise an
+     * {@link java.lang.IllegalArgumentException} will be thrown.
+     * </p>
+     *
+     * @param dngOutput an {@link java.io.OutputStream} to write the DNG file to.
+     * @param pixels an {@link android.media.Image} to write.
+     *
+     * @throws java.io.IOException if an error was encountered in the output stream.
+     * @throws java.lang.IllegalArgumentException if an image with an unsupported format was used.
+     * @throws java.lang.IllegalStateException if not enough metadata information has been
+     *          set to write a well-formatted DNG file.
+     */
+    public void writeImage(OutputStream dngOutput, Image pixels) throws IOException {/*TODO*/}
+
+}
diff --git a/media/java/android/media/MediaFocusControl.java b/media/java/android/media/MediaFocusControl.java
index 664c707..1c73c05 100644
--- a/media/java/android/media/MediaFocusControl.java
+++ b/media/java/android/media/MediaFocusControl.java
@@ -327,13 +327,12 @@
     private static final int MSG_REEVALUATE_REMOTE = 3;
     private static final int MSG_RCC_NEW_PLAYBACK_INFO = 4;
     private static final int MSG_RCC_NEW_VOLUME_OBS = 5;
-    private static final int MSG_PROMOTE_RCC = 6;
-    private static final int MSG_RCC_NEW_PLAYBACK_STATE = 7;
-    private static final int MSG_RCC_SEEK_REQUEST = 8;
-    private static final int MSG_RCC_UPDATE_METADATA = 9;
-    private static final int MSG_RCDISPLAY_INIT_INFO = 10;
-    private static final int MSG_REEVALUATE_RCD = 11;
-    private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 12;
+    private static final int MSG_RCC_NEW_PLAYBACK_STATE = 6;
+    private static final int MSG_RCC_SEEK_REQUEST = 7;
+    private static final int MSG_RCC_UPDATE_METADATA = 8;
+    private static final int MSG_RCDISPLAY_INIT_INFO = 9;
+    private static final int MSG_REEVALUATE_RCD = 10;
+    private static final int MSG_UNREGISTER_MEDIABUTTONINTENT = 11;
 
     // sendMsg() flags
     /** If the msg is already queued, replace it with this one. */
@@ -406,10 +405,6 @@
                             (Rating) msg.obj /* value */);
                     break;
 
-                case MSG_PROMOTE_RCC:
-                    onPromoteRcc(msg.arg1);
-                    break;
-
                 case MSG_RCDISPLAY_INIT_INFO:
                     // msg.obj is guaranteed to be non null
                     onRcDisplayInitInfo((IRemoteControlDisplay)msg.obj /*newRcd*/,
@@ -1064,10 +1059,8 @@
     private boolean mHasRemotePlayback;
 
     /**
-     *  The stack of remote control event receivers.
-     *  Code sections and methods that modify the remote control event receiver stack are
-     *  synchronized on mPRStack, but also BEFORE on mFocusLock as any change in either
-     *  stack, audio focus or RC, can lead to a change in the remote control display
+     * The stack of remote control event receivers.
+     * All read and write operations on mPRStack are synchronized.
      */
     private final Stack<PlayerRecord> mPRStack = new Stack<PlayerRecord>();
 
@@ -1214,56 +1207,93 @@
             mediaButtonIntent.setComponent(eventReceiver);
             PendingIntent pi = PendingIntent.getBroadcast(mContext,
                     0/*requestCode, ignored*/, mediaButtonIntent, 0/*flags*/);
-            registerMediaButtonIntent(pi, eventReceiver, null);
+            registerMediaButtonIntent(pi, eventReceiver, null /*token*/);
         }
     }
 
     /**
      * Helper function:
-     * Set the new remote control receiver at the top of the RC focus stack.
+     * Push the new media button receiver "near" the top of the PlayerRecord stack.
+     * "Near the top" is defined as:
+     *   - at the top if the current PlayerRecord at the top is not playing
+     *   - below the entries at the top of the stack that correspond to the playing PlayerRecord
+     *     otherwise
      * Called synchronized on mPRStack
      * precondition: mediaIntent != null
-     * @return true if mPRStack was changed, false otherwise
+     * @return true if the top of mPRStack was changed, false otherwise
      */
     private boolean pushMediaButtonReceiver_syncPrs(PendingIntent mediaIntent,
             ComponentName target, IBinder token) {
-        // already at top of stack?
-        if (!mPRStack.empty() && mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
+        if (mPRStack.empty()) {
+            mPRStack.push(new PlayerRecord(mediaIntent, target, token));
+            return true;
+        } else if (mPRStack.peek().hasMatchingMediaButtonIntent(mediaIntent)) {
+            // already at top of stack
             return false;
         }
         if (mAppOps.noteOp(AppOpsManager.OP_TAKE_MEDIA_BUTTONS, Binder.getCallingUid(),
                 mediaIntent.getCreatorPackage()) != AppOpsManager.MODE_ALLOWED) {
             return false;
         }
+        PlayerRecord oldTopPrse = mPRStack.lastElement(); // top of the stack before any changes
+        boolean topChanged = false;
         PlayerRecord prse = null;
-        boolean wasInsideStack = false;
+        int lastPlayingIndex = mPRStack.size();
+        int inStackIndex = -1;
         try {
+            // go through the stack from the top to figure out who's playing, and the position
+            // of this media button receiver (note that it may not be in the stack)
             for (int index = mPRStack.size()-1; index >= 0; index--) {
                 prse = mPRStack.elementAt(index);
-                if(prse.hasMatchingMediaButtonIntent(mediaIntent)) {
-                    // ok to remove element while traversing the stack since we're leaving the loop
-                    mPRStack.removeElementAt(index);
-                    wasInsideStack = true;
-                    break;
+                if (prse.isPlaybackActive()) {
+                    lastPlayingIndex = index;
+                }
+                if (prse.hasMatchingMediaButtonIntent(mediaIntent)) {
+                    inStackIndex = index;
                 }
             }
+
+            if (inStackIndex == -1) {
+                // is not in stack
+                prse = new PlayerRecord(mediaIntent, target, token);
+                // it's new so it's not playing (no RemoteControlClient to give a playstate),
+                // therefore it goes after the ones with active playback
+                mPRStack.add(lastPlayingIndex, prse);
+            } else {
+                // is in the stack
+                if (mPRStack.size() > 1) { // no need to remove and add if stack contains only 1
+                    prse = mPRStack.elementAt(inStackIndex);
+                    // remove it from its old location in the stack
+                    mPRStack.removeElementAt(inStackIndex);
+                    if (prse.isPlaybackActive()) {
+                        // and put it at the top
+                        mPRStack.push(prse);
+                    } else {
+                        // and put it after the ones with active playback
+                        if (inStackIndex > lastPlayingIndex) {
+                            mPRStack.add(lastPlayingIndex, prse);
+                        } else {
+                            mPRStack.add(lastPlayingIndex - 1, prse);
+                        }
+                    }
+                }
+            }
+
+            topChanged = (oldTopPrse != mPRStack.lastElement());
+            // post message to persist the default media button receiver
+            if (topChanged && (target != null)) {
+                mEventHandler.sendMessage( mEventHandler.obtainMessage(
+                        MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+            }
+
         } catch (ArrayIndexOutOfBoundsException e) {
-            // not expected to happen, indicates improper concurrent modification
-            Log.e(TAG, "Wrong index accessing media button stack, lock error? ", e);
-        }
-        if (!wasInsideStack) {
-            prse = new PlayerRecord(mediaIntent, target, token);
-        }
-        mPRStack.push(prse); // prse is never null
-
-        // post message to persist the default media button receiver
-        if (target != null) {
-            mEventHandler.sendMessage( mEventHandler.obtainMessage(
-                    MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+            // not expected to happen, indicates improper concurrent modification or bad index
+            Log.e(TAG, "Wrong index (inStack=" + inStackIndex + " lastPlaying=" + lastPlayingIndex
+                    + " size=" + mPRStack.size()
+                    + " accessing media button stack", e);
         }
 
-        // RC stack was modified
-        return true;
+        return (topChanged);
     }
 
     /**
@@ -1517,48 +1547,6 @@
     }
 
     /**
-     * Helper function:
-     * Post a message to asynchronously move the media button event receiver associated with the
-     * given remote control client ID to the top of the remote control stack
-     * @param rccId
-     */
-    private void postPromoteRcc(int rccId) {
-        sendMsg(mEventHandler, MSG_PROMOTE_RCC, SENDMSG_REPLACE,
-                rccId /*arg1*/, 0, null, 0/*delay*/);
-    }
-
-    private void onPromoteRcc(int rccId) {
-        if (DEBUG_RC) { Log.d(TAG, "Promoting RCC " + rccId); }
-        synchronized(mPRStack) {
-            // ignore if given RCC ID is already at top of remote control stack
-            if (!mPRStack.isEmpty() && (mPRStack.peek().getRccId() == rccId)) {
-                return;
-            }
-            int indexToPromote = -1;
-            try {
-                for (int index = mPRStack.size()-1; index >= 0; index--) {
-                    final PlayerRecord prse = mPRStack.elementAt(index);
-                    if (prse.getRccId() == rccId) {
-                        indexToPromote = index;
-                        break;
-                    }
-                }
-                if (indexToPromote >= 0) {
-                    if (DEBUG_RC) { Log.d(TAG, "  moving RCC from index " + indexToPromote
-                            + " to " + (mPRStack.size()-1)); }
-                    final PlayerRecord prse = mPRStack.remove(indexToPromote);
-                    mPRStack.push(prse);
-                    // the RC stack changed, reevaluate the display
-                    checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
-                }
-            } catch (ArrayIndexOutOfBoundsException e) {
-                // not expected to happen, indicates improper concurrent modification
-                Log.e(TAG, "Wrong index accessing RC stack, lock error? ", e);
-            }
-        }//synchronized(mPRStack)
-    }
-
-    /**
      * see AudioManager.registerMediaButtonIntent(PendingIntent pi, ComponentName c)
      * precondition: mediaIntent != null
      */
@@ -2153,30 +2141,70 @@
         if(DEBUG_RC) Log.d(TAG, "onNewPlaybackStateForRcc(id=" + rccId + ", state=" + state
                 + ", time=" + newState.mPositionMs + ", speed=" + newState.mSpeed + ")");
         synchronized(mPRStack) {
-            // iterating from top of stack as playback information changes are more likely
-            //   on entries at the top of the remote control stack
+            if (mPRStack.empty()) {
+                return;
+            }
+            PlayerRecord oldTopPrse = mPRStack.lastElement(); // top of the stack before any changes
+            PlayerRecord prse = null;
+            int lastPlayingIndex = mPRStack.size();
+            int inStackIndex = -1;
             try {
+                // go through the stack from the top to figure out who's playing, and the position
+                // of this RemoteControlClient (note that it may not be in the stack)
                 for (int index = mPRStack.size()-1; index >= 0; index--) {
-                    final PlayerRecord prse = mPRStack.elementAt(index);
+                    prse = mPRStack.elementAt(index);
                     if (prse.getRccId() == rccId) {
+                        inStackIndex = index;
                         prse.mPlaybackState = newState;
-                        synchronized (mMainRemote) {
-                            if (rccId == mMainRemote.mRccId) {
-                                mMainRemoteIsActive = isPlaystateActive(state);
-                                postReevaluateRemote();
-                            }
-                        }
-                        // an RCC moving to a "playing" state should become the media button
-                        //   event receiver so it can be controlled, without requiring the
-                        //   app to re-register its receiver
-                        if (isPlaystateActive(state)) {
-                            postPromoteRcc(rccId);
+                    }
+                    if (prse.isPlaybackActive()) {
+                        lastPlayingIndex = index;
+                    }
+                }
+
+                if (inStackIndex != -1) {
+                    // is in the stack
+                    prse = mPRStack.elementAt(inStackIndex);
+                    synchronized (mMainRemote) {
+                        if (rccId == mMainRemote.mRccId) {
+                            mMainRemoteIsActive = isPlaystateActive(state);
+                            postReevaluateRemote();
                         }
                     }
-                }//for
+                    if (mPRStack.size() > 1) { // no need to remove and add if stack contains only 1
+                        // remove it from its old location in the stack
+                        mPRStack.removeElementAt(inStackIndex);
+                        if (prse.isPlaybackActive()) {
+                            // and put it at the top
+                            mPRStack.push(prse);
+                        } else {
+                            // and put it after the ones with active playback
+                            if (inStackIndex > lastPlayingIndex) {
+                                mPRStack.add(lastPlayingIndex, prse);
+                            } else {
+                                mPRStack.add(lastPlayingIndex - 1, prse);
+                            }
+                        }
+                    }
+
+                    if (oldTopPrse != mPRStack.lastElement()) {
+                        // the top of the stack changed:
+                        final ComponentName target =
+                                mPRStack.lastElement().getMediaButtonReceiver();
+                        if (target != null) {
+                            // post message to persist the default media button receiver
+                            mEventHandler.sendMessage( mEventHandler.obtainMessage(
+                                    MSG_PERSIST_MEDIABUTTONRECEIVER, 0, 0, target/*obj*/) );
+                        }
+                        // reevaluate the display
+                        checkUpdateRemoteControlDisplay_syncPrs(RC_INFO_ALL);
+                    }
+                }
             } catch (ArrayIndexOutOfBoundsException e) {
-                // not expected to happen, indicates improper concurrent modification
-                Log.e(TAG, "Wrong index on mPRStack in onNewPlaybackStateForRcc, lock error? ", e);
+                // not expected to happen, indicates improper concurrent modification or bad index
+                Log.e(TAG, "Wrong index (inStack=" + inStackIndex + " lastPlaying=" + lastPlayingIndex
+                        + " size=" + mPRStack.size()
+                        + "accessing PlayerRecord stack in onNewPlaybackStateForRcc", e);
             }
         }
     }
@@ -2251,7 +2279,7 @@
      * @param playState the playback state to evaluate
      * @return true if active, false otherwise (inactive or unknown)
      */
-    private static boolean isPlaystateActive(int playState) {
+    protected static boolean isPlaystateActive(int playState) {
         switch (playState) {
             case RemoteControlClient.PLAYSTATE_PLAYING:
             case RemoteControlClient.PLAYSTATE_BUFFERING:
diff --git a/media/java/android/media/MediaMetadataEditor.java b/media/java/android/media/MediaMetadataEditor.java
index 3bfdb5a..1a4e8da 100644
--- a/media/java/android/media/MediaMetadataEditor.java
+++ b/media/java/android/media/MediaMetadataEditor.java
@@ -17,6 +17,7 @@
 package android.media;
 
 import android.graphics.Bitmap;
+import android.media.session.MediaMetadata;
 import android.os.Bundle;
 import android.os.Parcelable;
 import android.util.Log;
@@ -106,6 +107,10 @@
      */
     protected Bundle mEditorMetadata;
 
+    /**
+     * @hide
+     */
+    protected MediaMetadata.Builder mMetadataBuilder;
 
     /**
      * Clears all the pending metadata changes set since the MediaMetadataEditor instance was
@@ -120,6 +125,7 @@
         }
         mEditorMetadata.clear();
         mEditorArtwork = null;
+        mMetadataBuilder = new MediaMetadata.Builder();
     }
 
     /**
diff --git a/media/java/android/media/MediaScanner.java b/media/java/android/media/MediaScanner.java
index 72f3e1a..9516bf8 100644
--- a/media/java/android/media/MediaScanner.java
+++ b/media/java/android/media/MediaScanner.java
@@ -44,6 +44,8 @@
 import android.sax.Element;
 import android.sax.ElementListener;
 import android.sax.RootElement;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.text.TextUtils;
 import android.util.Log;
 import android.util.Xml;
@@ -60,9 +62,6 @@
 import java.util.Iterator;
 import java.util.Locale;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-
 /**
  * Internal service helper that no-one should use directly.
  *
@@ -1130,7 +1129,7 @@
                         if (path != null && path.startsWith("/")) {
                             boolean exists = false;
                             try {
-                                exists = Libcore.os.access(path, libcore.io.OsConstants.F_OK);
+                                exists = Os.access(path, android.system.OsConstants.F_OK);
                             } catch (ErrnoException e1) {
                             }
                             if (!exists && !MtpConstants.isAbstractObject(format)) {
@@ -1281,6 +1280,14 @@
         mMediaProvider = null;
     }
 
+    private void releaseResources() {
+        // release the DrmManagerClient resources
+        if (mDrmManagerClient != null) {
+            mDrmManagerClient.release();
+            mDrmManagerClient = null;
+        }
+    }
+
     private void initialize(String volumeName) {
         mMediaProvider = mContext.getContentResolver().acquireProvider("media");
 
@@ -1341,6 +1348,8 @@
             Log.e(TAG, "UnsupportedOperationException in MediaScanner.scan()", e);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in MediaScanner.scan()", e);
+        } finally {
+            releaseResources();
         }
     }
 
@@ -1364,6 +1373,8 @@
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in MediaScanner.scanFile()", e);
             return null;
+        } finally {
+            releaseResources();
         }
     }
 
@@ -1511,6 +1522,7 @@
             if (fileList != null) {
                 fileList.close();
             }
+            releaseResources();
         }
     }
 
diff --git a/media/java/android/media/PlayerRecord.java b/media/java/android/media/PlayerRecord.java
index a79b0ed..f9708c3 100644
--- a/media/java/android/media/PlayerRecord.java
+++ b/media/java/android/media/PlayerRecord.java
@@ -58,6 +58,9 @@
 
     private int mRccId = RemoteControlClient.RCSE_ID_UNREGISTERED;
 
+    /**
+     * A non-null token implies this record tracks a "live" player whose death is being monitored.
+     */
     private IBinder mToken;
     private String mCallingPackageName;
     private int mCallingUid;
@@ -254,20 +257,20 @@
         return mMediaIntent;
     }
 
-    // FIXME this is only used when comparing with the audio focus owner calling package name,
-    //       accessor to be removed once audio focus and media button owner are dissociated
-    protected String getCallingPackageName() {
-        return mCallingPackageName;
-    }
-
-    // FIXME this is only used when comparing with the audio focus owner calling package name,
-    //       accessor to be removed once audio focus and media button owner are dissociated
-    protected int getCallingUid() {
-        return mCallingUid;
-    }
-
     protected boolean hasMatchingMediaButtonIntent(PendingIntent pi) {
-        return mMediaIntent.equals(pi);
+        if (mToken != null) {
+            return mMediaIntent.equals(pi);
+        } else {
+            if (mReceiverComponent != null) {
+                return mReceiverComponent.equals(pi.getIntent().getComponent());
+            } else {
+                return false;
+            }
+        }
+    }
+
+    protected boolean isPlaybackActive() {
+        return MediaFocusControl.isPlaystateActive(mPlaybackState.mState);
     }
 
     //---------------------------------------------
diff --git a/media/java/android/media/RemoteControlClient.java b/media/java/android/media/RemoteControlClient.java
index c2c61d3..8368df94 100644
--- a/media/java/android/media/RemoteControlClient.java
+++ b/media/java/android/media/RemoteControlClient.java
@@ -24,6 +24,11 @@
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.RectF;
+import android.media.session.MediaMetadata;
+import android.media.session.MediaSessionLegacyHelper;
+import android.media.session.PlaybackState;
+import android.media.session.Session;
+import android.media.session.TransportPerformer;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
@@ -336,6 +341,8 @@
      */
     public final static int FLAG_INFORMATION_REQUEST_ALBUM_ART = 1 << 3;
 
+    private Session mSession;
+
     /**
      * Class constructor.
      * @param mediaButtonIntent The intent that will be sent for the media button events sent
@@ -385,6 +392,22 @@
     }
 
     /**
+     * @hide
+     */
+    public void registerWithSession(MediaSessionLegacyHelper helper) {
+        helper.addRccListener(mRcMediaIntent, mTransportListener);
+        mSession = helper.getSession(mRcMediaIntent);
+    }
+
+    /**
+     * @hide
+     */
+    public void unregisterWithSession(MediaSessionLegacyHelper helper) {
+        helper.removeRccListener(mRcMediaIntent);
+        mSession = null;
+    }
+
+    /**
      * Class used to modify metadata in a {@link RemoteControlClient} object.
      * Use {@link RemoteControlClient#editMetadata(boolean)} to create an instance of an editor,
      * on which you set the metadata for the RemoteControlClient instance. Once all the information
@@ -438,6 +461,15 @@
         public synchronized MetadataEditor putString(int key, String value)
                 throws IllegalArgumentException {
             super.putString(key, value);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putString(metadataKey, value);
+                }
+            }
+
             return this;
         }
 
@@ -459,6 +491,14 @@
         public synchronized MetadataEditor putLong(int key, long value)
                 throws IllegalArgumentException {
             super.putLong(key, value);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putLong(metadataKey, value);
+                }
+            }
             return this;
         }
 
@@ -476,6 +516,14 @@
         public synchronized MetadataEditor putBitmap(int key, Bitmap bitmap)
                 throws IllegalArgumentException {
             super.putBitmap(key, bitmap);
+            if (mMetadataBuilder != null) {
+                // MediaMetadata supports all the same fields as MetadataEditor
+                String metadataKey = MediaMetadata.getKeyFromMetadataEditorKey(key);
+                // But just in case, don't add things we don't understand
+                if (metadataKey != null) {
+                    mMetadataBuilder.putBitmap(metadataKey, bitmap);
+                }
+            }
             return this;
         }
 
@@ -501,7 +549,7 @@
                 Log.e(TAG, "Can't apply a previously applied MetadataEditor");
                 return;
             }
-            synchronized(mCacheLock) {
+            synchronized (mCacheLock) {
                 // assign the edited data
                 mMetadata = new Bundle(mEditorMetadata);
                 // add the information about editable keys
@@ -521,6 +569,11 @@
                     // send to remote control display if conditions are met
                     sendArtwork_syncCacheLock(null, 0, 0);
                 }
+
+                // USE_SESSIONS
+                if (mSession != null && mMetadataBuilder != null) {
+                    mSession.getTransportPerformer().setMetadata(mMetadataBuilder.build());
+                }
                 mApplied = true;
             }
         }
@@ -546,6 +599,12 @@
             editor.mMetadataChanged = false;
             editor.mArtworkChanged = false;
         }
+        // USE_SESSIONS
+        if (startEmpty || mMediaMetadata == null) {
+            editor.mMetadataBuilder = new MediaMetadata.Builder();
+        } else {
+            editor.mMetadataBuilder = new MediaMetadata.Builder(mMediaMetadata);
+        }
         return editor;
     }
 
@@ -624,6 +683,15 @@
 
                 // handle automatic playback position refreshes
                 initiateCheckForDrift_syncCacheLock();
+
+                // USE_SESSIONS
+                if (mSession != null) {
+                    int pbState = PlaybackState.getStateFromRccState(state);
+                    mSessionPlaybackState.setState(pbState, hasPosition ?
+                            mPlaybackPositionMs : PlaybackState.PLAYBACK_POSITION_UNKNOWN,
+                            playbackSpeed);
+                    mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState);
+                }
             }
         }
     }
@@ -704,6 +772,13 @@
 
             // send to remote control display if conditions are met
             sendTransportControlInfo_syncCacheLock(null);
+
+            // USE_SESSIONS
+            if (mSession != null) {
+                mSessionPlaybackState.setActions(PlaybackState
+                        .getActionsFromRccControlFlags(transportControlFlags));
+                mSession.getTransportPerformer().setPlaybackState(mSessionPlaybackState);
+            }
         }
     }
 
@@ -1038,6 +1113,16 @@
     private boolean mNeedsPositionSync = false;
 
     /**
+     * Cache for the current playback state using Session APIs.
+     */
+    private final PlaybackState mSessionPlaybackState = new PlaybackState();
+
+    /**
+     * Cache for metadata using Session APIs. This is re-initialized in apply().
+     */
+    private MediaMetadata mMediaMetadata;
+
+    /**
      * A class to encapsulate all the information about a remote control display.
      * A RemoteControlClient's metadata and state may be displayed on multiple IRemoteControlDisplay
      */
@@ -1219,6 +1304,26 @@
         return mRcseId;
     }
 
+    // USE_SESSIONS
+    private TransportPerformer.Listener mTransportListener = new TransportPerformer.Listener() {
+
+        @Override
+        public void onSeekTo(long pos) {
+            RemoteControlClient.this.onSeekTo(mCurrentClientGenId, pos);
+        }
+
+        @Override
+        public void onRate(Rating rating) {
+            if ((mTransportControlFlags & FLAG_KEY_MEDIA_RATING) != 0) {
+                if (mEventHandler != null) {
+                    mEventHandler.sendMessage(mEventHandler.obtainMessage(
+                            MSG_UPDATE_METADATA, mCurrentClientGenId,
+                            MetadataEditor.RATING_KEY_BY_USER, rating));
+                }
+            }
+        }
+    };
+
     private EventHandler mEventHandler;
     private final static int MSG_REQUEST_PLAYBACK_STATE = 1;
     private final static int MSG_REQUEST_METADATA = 2;
@@ -1325,7 +1430,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setPlaybackState(mInternalClientGenId,
@@ -1353,7 +1458,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setMetadata(mInternalClientGenId, mMetadata);
@@ -1381,7 +1486,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     try {
                         di.mRcDisplay.setTransportControlInfo(mInternalClientGenId,
@@ -1407,7 +1512,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                if (!sendArtworkToDisplay((DisplayInfoForClient) displayIterator.next())) {
+                if (!sendArtworkToDisplay(displayIterator.next())) {
                     displayIterator.remove();
                 }
             }
@@ -1453,7 +1558,7 @@
             // target == null implies all displays must be updated
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 try {
                     if (di.mEnabled) {
                         if ((di.mArtworkExpectedWidth > 0) && (di.mArtworkExpectedHeight > 0)) {
@@ -1537,7 +1642,7 @@
             boolean displayKnown = false;
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext() && !displayKnown) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 displayKnown = di.mRcDisplay.asBinder().equals(rcd.asBinder());
                 if (displayKnown) {
                     // this display was known but the change in artwork size will cause the
@@ -1562,7 +1667,7 @@
         synchronized(mCacheLock) {
             Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                     displayIterator.remove();
                     break;
@@ -1573,7 +1678,7 @@
             boolean newNeedsPositionSync = false;
             displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mWantsPositionSync) {
                     newNeedsPositionSync = true;
                     break;
@@ -1592,7 +1697,7 @@
         synchronized(mCacheLock) {
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder()) &&
                         ((di.mArtworkExpectedWidth != w) || (di.mArtworkExpectedHeight != h))) {
                     di.mArtworkExpectedWidth = w;
@@ -1617,7 +1722,7 @@
             // go through the list of RCDs and for each entry, check both whether this is the RCD
             //  that gets upated, and whether the list has one entry that wants position sync
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mEnabled) {
                     if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                         di.mWantsPositionSync = wantsSync;
@@ -1640,7 +1745,7 @@
         synchronized(mCacheLock) {
             final Iterator<DisplayInfoForClient> displayIterator = mRcDisplays.iterator();
             while (displayIterator.hasNext()) {
-                final DisplayInfoForClient di = (DisplayInfoForClient) displayIterator.next();
+                final DisplayInfoForClient di = displayIterator.next();
                 if (di.mRcDisplay.asBinder().equals(rcd.asBinder())) {
                     di.mEnabled = enable;
                 }
diff --git a/media/java/android/media/Ringtone.java b/media/java/android/media/Ringtone.java
index 1283e9b..2616b6c 100644
--- a/media/java/android/media/Ringtone.java
+++ b/media/java/android/media/Ringtone.java
@@ -217,7 +217,7 @@
             if (mAudioManager.getStreamVolume(mStreamType) != 0) {
                 mLocalPlayer.start();
             }
-        } else if (mAllowRemote) {
+        } else if (mAllowRemote && (mRemotePlayer != null)) {
             final Uri canonicalUri = mUri.getCanonicalUri();
             try {
                 mRemotePlayer.play(mRemoteToken, canonicalUri, mStreamType);
@@ -239,7 +239,7 @@
     public void stop() {
         if (mLocalPlayer != null) {
             destroyLocalPlayer();
-        } else if (mAllowRemote) {
+        } else if (mAllowRemote && (mRemotePlayer != null)) {
             try {
                 mRemotePlayer.stop(mRemoteToken);
             } catch (RemoteException e) {
@@ -264,7 +264,7 @@
     public boolean isPlaying() {
         if (mLocalPlayer != null) {
             return mLocalPlayer.isPlaying();
-        } else if (mAllowRemote) {
+        } else if (mAllowRemote && (mRemotePlayer != null)) {
             try {
                 return mRemotePlayer.isPlaying(mRemoteToken);
             } catch (RemoteException e) {
diff --git a/media/java/android/media/WebVttRenderer.java b/media/java/android/media/WebVttRenderer.java
index 58d3520..1c9730f 100644
--- a/media/java/android/media/WebVttRenderer.java
+++ b/media/java/android/media/WebVttRenderer.java
@@ -558,7 +558,11 @@
     }
 }
 
-/** @hide */
+/**
+ *  Supporting July 10 2013 draft version
+ *
+ *  @hide
+ */
 class WebVttParser {
     private static final String TAG = "WebVttParser";
     private Phase mPhase;
@@ -726,15 +730,15 @@
                                 "has invalid value", e.getMessage(), value);
                     }
                 } else if (name.equals("lines")) {
-                    try {
-                        int lines = Integer.parseInt(value);
-                        if (lines >= 0) {
-                            region.mLines = lines;
-                        } else {
-                            log_warning("region setting", name, "is negative", value);
+                    if (value.matches(".*[^0-9].*")) {
+                        log_warning("lines", name, "contains an invalid character", value);
+                    } else {
+                        try {
+                            region.mLines = Integer.parseInt(value);
+                            assert(region.mLines >= 0); // lines contains only digits
+                        } catch (NumberFormatException e) {
+                            log_warning("region setting", name, "is not numeric", value);
                         }
-                    } catch (NumberFormatException e) {
-                        log_warning("region setting", name, "is not numeric", value);
                     }
                 } else if (name.equals("regionanchor") ||
                            name.equals("viewportanchor")) {
@@ -872,26 +876,23 @@
                     }
                 } else if (name.equals("line")) {
                     try {
-                        int linePosition;
                         /* TRICKY: we know that there are no spaces in value */
                         assert(value.indexOf(' ') < 0);
                         if (value.endsWith("%")) {
-                            linePosition = Integer.parseInt(
-                                    value.substring(0, value.length() - 1));
-                            if (linePosition < 0 || linePosition > 100) {
-                                log_warning("cue setting", name, "is out of range", value);
-                                continue;
-                            }
                             mCue.mSnapToLines = false;
-                            mCue.mLinePosition = linePosition;
+                            mCue.mLinePosition = parseIntPercentage(value);
+                        } else if (value.matches(".*[^0-9].*")) {
+                            log_warning("cue setting", name,
+                                    "contains an invalid character", value);
                         } else {
                             mCue.mSnapToLines = true;
                             mCue.mLinePosition = Integer.parseInt(value);
                         }
                     } catch (NumberFormatException e) {
                         log_warning("cue setting", name,
-                               "is not numeric or percentage", value);
+                                "is not numeric or percentage", value);
                     }
+                    // TODO: add support for optional alignment value [,start|middle|end]
                 } else if (name.equals("position")) {
                     try {
                         mCue.mTextPosition = parseIntPercentage(value);
diff --git a/media/java/android/media/session/IMediaSessionManager.aidl b/media/java/android/media/routeprovider/IRouteConnection.aidl
similarity index 65%
copy from media/java/android/media/session/IMediaSessionManager.aidl
copy to media/java/android/media/routeprovider/IRouteConnection.aidl
index 0b4328e..15c8039 100644
--- a/media/java/android/media/session/IMediaSessionManager.aidl
+++ b/media/java/android/media/routeprovider/IRouteConnection.aidl
@@ -13,16 +13,16 @@
  * limitations under the License.
  */
 
-package android.media.session;
+package android.media.routeprovider;
 
-import android.media.session.IMediaSession;
-import android.media.session.IMediaSessionCallback;
-import android.os.Bundle;
+import android.media.session.RouteCommand;
+import android.os.ResultReceiver;
 
 /**
- * Interface to the MediaSessionManagerService
+ * Interface for a specific connected route.
  * @hide
  */
-interface IMediaSessionManager {
-    IMediaSession createSession(String packageName, in IMediaSessionCallback cb, String tag);
+oneway interface IRouteConnection {
+    void onCommand(in RouteCommand command, in ResultReceiver cb);
+    void disconnect();
 }
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/IRouteProvider.aidl b/media/java/android/media/routeprovider/IRouteProvider.aidl
new file mode 100644
index 0000000..c36f6a7
--- /dev/null
+++ b/media/java/android/media/routeprovider/IRouteProvider.aidl
@@ -0,0 +1,36 @@
+/* Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.routeprovider;
+
+import android.media.routeprovider.IRouteConnection;
+import android.media.routeprovider.IRouteProviderCallback;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.RouteInfo;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+
+/**
+ * Interface to an app's RouteProviderService.
+ * @hide
+ */
+oneway interface IRouteProvider {
+    void registerCallback(in IRouteProviderCallback cb);
+    void unregisterCallback(in IRouteProviderCallback cb);
+    void updateDiscoveryRequests(in List<RouteRequest> requests);
+
+    void getAvailableRoutes(in List<RouteRequest> requests, in ResultReceiver cb);
+    void connect(in RouteInfo route, in RouteRequest request, in ResultReceiver cb);
+}
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/IRouteProviderCallback.aidl b/media/java/android/media/routeprovider/IRouteProviderCallback.aidl
new file mode 100644
index 0000000..9185347
--- /dev/null
+++ b/media/java/android/media/routeprovider/IRouteProviderCallback.aidl
@@ -0,0 +1,32 @@
+/* Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.routeprovider;
+
+import android.media.routeprovider.IRouteConnection;
+import android.media.session.RouteEvent;
+import android.os.Bundle;
+import android.os.ResultReceiver;
+
+/**
+ * System's provider callback interface.
+ * @hide
+ */
+oneway interface IRouteProviderCallback {
+    void onRoutesChanged();
+    void onConnectionStateChanged(in IRouteConnection connection, int state);
+    void onConnectionTerminated(in IRouteConnection connection);
+    void onRouteEvent(in RouteEvent event);
+}
\ No newline at end of file
diff --git a/media/java/android/media/routeprovider/RouteConnection.java b/media/java/android/media/routeprovider/RouteConnection.java
new file mode 100644
index 0000000..9214ff8
--- /dev/null
+++ b/media/java/android/media/routeprovider/RouteConnection.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.routeprovider;
+
+import android.media.routeprovider.IRouteConnection;
+import android.media.session.RouteCommand;
+import android.media.session.RouteEvent;
+import android.media.session.RouteInfo;
+import android.media.session.RouteInterface;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.text.TextUtils;
+import android.util.ArrayMap;
+import android.util.Log;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Represents an ongoing connection between an application and a media route
+ * offered by a media route provider.
+ * <p>
+ * The media route provider should add interfaces to the connection before
+ * returning it to the system in order to receive commands from clients on those
+ * interfaces. Use {@link #addRouteInterface(String)} to add an interface and
+ * {@link #getRouteInterface(String)} to retrieve the interface's handle anytime
+ * after it has been added.
+ */
+public final class RouteConnection {
+    private static final String TAG = "RouteConnection";
+    private final ConnectionStub mBinder;
+    private final ArrayList<String> mIfaceNames = new ArrayList<String>();
+    private final ArrayMap<String, RouteInterfaceHandler> mIfaces
+            = new ArrayMap<String, RouteInterfaceHandler>();
+    private final RouteProviderService mProvider;
+    private final RouteInfo mRoute;
+
+    private boolean mPublished;
+
+    /**
+     * Create a new connection for the given Provider and Route.
+     *
+     * @param provider The provider this route is associated with.
+     * @param route The route this is a connection to.
+     */
+    public RouteConnection(RouteProviderService provider, RouteInfo route) {
+        if (provider == null) {
+            throw new IllegalArgumentException("provider may not be null.");
+        }
+        if (route == null) {
+            throw new IllegalArgumentException("route may not be null.");
+        }
+        mBinder = new ConnectionStub(this);
+        mProvider = provider;
+        mRoute = route;
+    }
+
+    /**
+     * Add an interface to this route connection. All interfaces must be added
+     * to the connection before the connection is returned to the system.
+     *
+     * @param ifaceName The name of the interface to add
+     * @return The route interface that was registered
+     */
+    public RouteInterfaceHandler addRouteInterface(String ifaceName) {
+        if (TextUtils.isEmpty(ifaceName)) {
+            throw new IllegalArgumentException("The interface's name may not be empty");
+        }
+        if (mPublished) {
+            throw new IllegalStateException(
+                    "Connection has already been published to the system.");
+        }
+        RouteInterfaceHandler iface = mIfaces.get(ifaceName);
+        if (iface == null) {
+            iface = new RouteInterfaceHandler(this, ifaceName);
+            mIfaceNames.add(ifaceName);
+            mIfaces.put(ifaceName, iface);
+        } else {
+            Log.w(TAG, "Attempted to add an interface that already exists");
+        }
+        return iface;
+    }
+
+    /**
+     * Get the interface instance for the specified interface name. If the
+     * interface was not added to this connection null will be returned.
+     *
+     * @param ifaceName The name of the interface to get.
+     * @return The route interface with that name or null.
+     */
+    public RouteInterfaceHandler getRouteInterface(String ifaceName) {
+        return mIfaces.get(ifaceName);
+    }
+
+    /**
+     * Close the connection and inform the system that it may no longer be used.
+     */
+    public void shutDown() {
+        mProvider.disconnect(this);
+    }
+
+    /**
+     * @hide
+     */
+    public void sendEvent(String iface, String event, Bundle extras) {
+        RouteEvent e = new RouteEvent(mBinder, iface, event, extras);
+        mProvider.sendRouteEvent(e);
+    }
+
+    /**
+     * @hide
+     */
+    IRouteConnection.Stub getBinder() {
+        return mBinder;
+    }
+
+    /**
+     * @hide
+     */
+    void publish() {
+        mPublished = true;
+    }
+
+    private static class ConnectionStub extends IRouteConnection.Stub {
+        private final WeakReference<RouteConnection> mConnection;
+
+        public ConnectionStub(RouteConnection connection) {
+            mConnection = new WeakReference<RouteConnection>(connection);
+        }
+
+        @Override
+        public void onCommand(RouteCommand command, ResultReceiver cb) {
+            RouteConnection connection = mConnection.get();
+            if (connection != null) {
+                RouteInterfaceHandler iface = connection.mIfaces.get(command.getIface());
+                if (iface != null) {
+                    iface.onCommand(command.getEvent(), command.getExtras(), cb);
+                } else if (cb != null) {
+                    cb.send(RouteInterface.RESULT_INTERFACE_NOT_SUPPORTED, null);
+                }
+            }
+        }
+
+        @Override
+        public void disconnect() {
+            // TODO
+        }
+    }
+}
diff --git a/media/java/android/media/routeprovider/RouteInterfaceHandler.java b/media/java/android/media/routeprovider/RouteInterfaceHandler.java
new file mode 100644
index 0000000..9693dc6
--- /dev/null
+++ b/media/java/android/media/routeprovider/RouteInterfaceHandler.java
@@ -0,0 +1,245 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.routeprovider;
+
+import android.media.session.Route;
+import android.media.session.Session;
+import android.media.session.RouteInterface;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ResultReceiver;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+
+/**
+ * Represents an interface that an application may use to send requests to a
+ * connected media route.
+ * <p>
+ * A {@link RouteProviderService} may expose multiple interfaces on a
+ * {@link RouteConnection} for a {@link Session} to interact with. A
+ * provider creates an interface with
+ * {@link RouteConnection#addRouteInterface(String)} to allow messages to be
+ * routed appropriately. Events are then sent through a specific interface and
+ * all commands being sent on the interface will be sent to any registered
+ * {@link CommandListener}s.
+ * <p>
+ * An interface instance can only be registered on one {@link RouteConnection}.
+ * To use the same interface on multiple connections a new instance must be
+ * created for each connection.
+ * <p>
+ * It is recommended you wrap this interface with a standard implementation to
+ * avoid errors, but for simple interfaces this class may be used directly. TODO
+ * add link to sample code.
+ */
+public final class RouteInterfaceHandler {
+    private static final String TAG = "RouteInterfaceHandler";
+
+    private final Object mLock = new Object();
+    private final RouteConnection mConnection;
+    private final String mName;
+
+    private ArrayList<MessageHandler> mListeners = new ArrayList<MessageHandler>();
+
+    /**
+     * Create a new RouteInterface for a given connection. This can be used to
+     * send events on the given interface and register listeners for commands
+     * from the connected session.
+     *
+     * @param connection The connection this interface sends events on
+     * @param ifaceName The name of this interface
+     * @hide
+     */
+    public RouteInterfaceHandler(RouteConnection connection, String ifaceName) {
+        if (connection == null) {
+            throw new IllegalArgumentException("connection may not be null");
+        }
+        if (TextUtils.isEmpty(ifaceName)) {
+            throw new IllegalArgumentException("ifaceName can not be empty");
+        }
+        mConnection = connection;
+        mName = ifaceName;
+    }
+
+    /**
+     * Send an event on this interface to the connected session.
+     *
+     * @param event The event to send
+     * @param extras Any extras for the event
+     */
+    public void sendEvent(String event, Bundle extras) {
+        mConnection.sendEvent(mName, event, extras);
+    }
+
+    /**
+     * Send a result from a command to the specified callback. The result codes
+     * in {@link RouteInterface} must be used. More information
+     * about the result, whether successful or an error, should be included in
+     * the extras.
+     *
+     * @param cb The callback to send the result to
+     * @param resultCode The result code for the call
+     * @param extras Any extras to include
+     */
+    public static void sendResult(ResultReceiver cb, int resultCode, Bundle extras) {
+        if (cb != null) {
+            cb.send(resultCode, extras);
+        }
+    }
+
+    /**
+     * Add a listener for this interface. If a handler is specified callbacks
+     * will be performed on the handler's thread, otherwise the callers thread
+     * will be used.
+     *
+     * @param listener The listener to receive calls on.
+     * @param handler The handler whose thread to post calls on or null.
+     */
+    public void addListener(CommandListener listener, Handler handler) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener may not be null");
+        }
+        Looper looper = handler != null ? handler.getLooper() : Looper.myLooper();
+        synchronized (mLock) {
+            if (findIndexOfListenerLocked(listener) != -1) {
+                Log.d(TAG, "Listener is already added, ignoring");
+                return;
+            }
+            mListeners.add(new MessageHandler(looper, listener));
+        }
+    }
+
+    /**
+     * Remove a listener from this interface.
+     *
+     * @param listener The listener to stop receiving commands on.
+     */
+    public void removeListener(CommandListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("listener may not be null");
+        }
+        synchronized (mLock) {
+            int index = findIndexOfListenerLocked(listener);
+            if (index != -1) {
+                mListeners.remove(index);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public void onCommand(String command, Bundle args, ResultReceiver cb) {
+        synchronized (mLock) {
+            Command cmd = new Command(command, args, cb);
+            for (int i = mListeners.size() - 1; i >= 0; i--) {
+                mListeners.get(i).post(MessageHandler.MSG_COMMAND, cmd);
+            }
+        }
+    }
+
+    /**
+     * Get the interface name.
+     *
+     * @return The name of this interface
+     */
+    public String getName() {
+        return mName;
+    }
+
+    private int findIndexOfListenerLocked(CommandListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("Callback cannot be null");
+        }
+        for (int i = mListeners.size() - 1; i >= 0; i--) {
+            MessageHandler handler = mListeners.get(i);
+            if (listener == handler.mListener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Handles commands sent to the interface.
+     * <p>
+     * Register an InterfaceListener using {@link #addListener}.
+     */
+    public abstract static class CommandListener {
+        /**
+         * This is called when a command is received that matches this
+         * interface. Commands are sent by a {@link Session} that is
+         * connected to the route this interface is registered with.
+         *
+         * @param iface The interface the command was received on.
+         * @param command The command or method to invoke.
+         * @param args Any args that were included with the command. May be
+         *            null.
+         * @param cb The callback provided to send a response on. May be null.
+         * @return true if the command was handled, false otherwise. If the
+         *         command was not handled an error will be sent automatically.
+         *         true may be returned if the command will be handled
+         *         asynchronously.
+         * @see Route
+         * @see Session
+         */
+        public abstract boolean onCommand(RouteInterfaceHandler iface, String command, Bundle args,
+                ResultReceiver cb);
+    }
+
+    private class MessageHandler extends Handler {
+        private static final int MSG_COMMAND = 1;
+
+        private final CommandListener mListener;
+
+        public MessageHandler(Looper looper, CommandListener listener) {
+            super(looper, null, true /* async */);
+            mListener = listener;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_COMMAND:
+                    Command cmd = (Command) msg.obj;
+                    if (!mListener.onCommand(RouteInterfaceHandler.this, cmd.command, cmd.args, cmd.cb)) {
+                        sendResult(cmd.cb, RouteInterface.RESULT_COMMAND_NOT_SUPPORTED,
+                                null);
+                    }
+                    break;
+            }
+        }
+
+        public void post(int what, Object obj) {
+            obtainMessage(what, obj).sendToTarget();
+        }
+    }
+
+    private final static class Command {
+        public final String command;
+        public final Bundle args;
+        public final ResultReceiver cb;
+
+        public Command(String command, Bundle args, ResultReceiver cb) {
+            this.command = command;
+            this.args = args;
+            this.cb = cb;
+        }
+    }
+}
diff --git a/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java b/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java
new file mode 100644
index 0000000..dcef79a
--- /dev/null
+++ b/media/java/android/media/routeprovider/RoutePlaybackControlsHandler.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.routeprovider;
+
+import android.media.session.RoutePlaybackControls;
+import android.media.session.RouteInterface;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+import android.text.TextUtils;
+import android.util.Log;
+
+/**
+ * Standard wrapper for using playback controls over a {@link RouteInterfaceHandler}.
+ * This is the provider half of the interface. Sessions should use
+ * {@link RoutePlaybackControls} to interact with this interface.
+ */
+public final class RoutePlaybackControlsHandler {
+    private static final String TAG = "RoutePlaybackControls";
+
+    private final RouteInterfaceHandler mIface;
+
+    private RoutePlaybackControlsHandler(RouteInterfaceHandler iface) {
+        mIface = iface;
+    }
+
+    /**
+     * Add this interface to the specified route and return a handle for
+     * communicating on the interface.
+     *
+     * @param connection The connection to register this interface on.
+     * @return A handle for communicating on this interface.
+     */
+    public static RoutePlaybackControlsHandler addTo(RouteConnection connection) {
+        if (connection == null) {
+            throw new IllegalArgumentException("connection may not be null");
+        }
+        RouteInterfaceHandler iface = connection
+                .addRouteInterface(RoutePlaybackControls.NAME);
+
+        return new RoutePlaybackControlsHandler(iface);
+    }
+
+    /**
+     * Add a {@link Listener} to this interface. The listener will receive
+     * commands on the caller's thread.
+     *
+     * @param listener The listener to send commands to.
+     */
+    public void addListener(Listener listener) {
+        addListener(listener, null);
+    }
+
+    /**
+     * Add a {@link Listener} to this interface. The listener will receive
+     * updates on the handler's thread. If no handler is specified the caller's
+     * thread will be used instead.
+     *
+     * @param listener The listener to send commands to.
+     * @param handler The handler whose thread calls should be posted on. May be
+     *            null.
+     */
+    public void addListener(Listener listener, Handler handler) {
+        mIface.addListener(listener, handler);
+    }
+
+    /**
+     * Remove a {@link Listener} from this interface.
+     *
+     * @param listener The Listener to remove.
+     */
+    public void removeListener(Listener listener) {
+        mIface.removeListener(listener);
+    }
+
+    /**
+     * Publish the current playback state to the system and any controllers.
+     * Valid values are defined in {@link PlaybackState}. TODO create
+     * RoutePlaybackState.
+     *
+     * @param state
+     */
+    public void sendPlaybackChangeEvent(int state) {
+        Bundle extras = new Bundle();
+        extras.putInt(RoutePlaybackControls.KEY_VALUE1, state);
+        mIface.sendEvent(RoutePlaybackControls.EVENT_PLAYSTATE_CHANGE, extras);
+    }
+
+    /**
+     * Command handler for the RoutePlaybackControls interface. You can add a
+     * Listener to the interface using {@link #addListener}.
+     */
+    public static abstract class Listener extends RouteInterfaceHandler.CommandListener {
+
+        @Override
+        public final boolean onCommand(RouteInterfaceHandler iface, String method, Bundle extras,
+                ResultReceiver cb) {
+            if (RoutePlaybackControls.CMD_FAST_FORWARD.equals(method)) {
+                boolean success = fastForward();
+                // TODO specify type of error
+                RouteInterfaceHandler.sendResult(cb, success
+                        ? RouteInterface.RESULT_SUCCESS
+                        : RouteInterface.RESULT_ERROR, null);
+                return true;
+            } else if (RoutePlaybackControls.CMD_GET_CURRENT_POSITION.equals(method)) {
+                Bundle result = new Bundle();
+                result.putLong(RoutePlaybackControls.KEY_VALUE1, getCurrentPosition());
+                RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS,
+                        result);
+                return true;
+            } else if (RoutePlaybackControls.CMD_GET_CAPABILITIES.equals(method)) {
+                Bundle result = new Bundle();
+                result.putLong(RoutePlaybackControls.KEY_VALUE1, getCapabilities());
+                RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS,
+                        result);
+                return true;
+            } else if (RoutePlaybackControls.CMD_PLAY_NOW.equals(method)) {
+                playNow(extras.getString(RoutePlaybackControls.KEY_VALUE1, null), cb);
+                return true;
+            } else if (RoutePlaybackControls.CMD_RESUME.equals(method)) {
+                boolean success = resume();
+                RouteInterfaceHandler.sendResult(cb, success
+                        ? RouteInterface.RESULT_SUCCESS
+                        : RouteInterface.RESULT_ERROR, null);
+                return true;
+            } else if (RoutePlaybackControls.CMD_PAUSE.equals(method)) {
+                boolean success = pause();
+                RouteInterfaceHandler.sendResult(cb, success
+                        ? RouteInterface.RESULT_SUCCESS
+                        : RouteInterface.RESULT_ERROR, null);
+                return true;
+            } else {
+                // The command wasn't recognized
+            }
+            return false;
+        }
+
+        /**
+         * Override to handle fast forwarding.
+         *
+         * @return true if the request succeeded, false otherwise
+         */
+        public boolean fastForward() {
+            Log.w(TAG, "fastForward is not supported.");
+            return false;
+        }
+
+        /**
+         * Override to handle getting the current position of playback in
+         * millis.
+         *
+         * @return The current position in millis or -1
+         */
+        public long getCurrentPosition() {
+            Log.w(TAG, "getCurrentPosition is not supported");
+            return -1;
+        }
+
+        /**
+         * Override to handle getting the set of capabilities currently
+         * available.
+         *
+         * @return A bit mask of the supported capabilities
+         */
+        public long getCapabilities() {
+            Log.w(TAG, "getCapabilities is not supported");
+            return 0;
+        }
+
+        /**
+         * Override to handle play now requests.
+         *
+         * @param content The uri of the item to play.
+         * @param cb The callback to send the result to.
+         */
+        public void playNow(String content, ResultReceiver cb) {
+            Log.w(TAG, "playNow is not supported");
+            if (cb != null) {
+                // We do this directly since we don't have a reference to the
+                // iface
+                cb.send(RouteInterface.RESULT_COMMAND_NOT_SUPPORTED, null);
+            }
+        }
+
+        /**
+         * Override to handle resume requests. Return true if the call was
+         * handled, even if it was a no-op.
+         *
+         * @return true if the call was handled.
+         */
+        public boolean resume() {
+            Log.w(TAG, "resume is not supported");
+            return false;
+        }
+
+        /**
+         * Override to handle pause requests. Return true if the call was
+         * handled, even if it was a no-op.
+         *
+         * @return true if the call was handled.
+         */
+        public boolean pause() {
+            Log.w(TAG, "pause is not supported");
+            return false;
+        }
+    }
+}
diff --git a/media/java/android/media/routeprovider/RouteProviderService.java b/media/java/android/media/routeprovider/RouteProviderService.java
new file mode 100644
index 0000000..6ebfb5b
--- /dev/null
+++ b/media/java/android/media/routeprovider/RouteProviderService.java
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.routeprovider;
+
+import android.app.Service;
+import android.content.Intent;
+import android.media.routeprovider.IRouteProvider;
+import android.media.routeprovider.IRouteProviderCallback;
+import android.media.session.RouteEvent;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Base class for defining a route provider service.
+ * <p>
+ * A route provider offers media routes which represent destinations to which
+ * applications may connect, control, and send content. This provides a means
+ * for Android applications to interact with a variety of media streaming
+ * devices such as speakers or television sets.
+ * <p>
+ * The system will bind to your provider when an active app is interested in
+ * routes that may be discovered through your provider. After binding, the
+ * system will send updates on which routes to discover through
+ * {@link #updateDiscoveryRequests(List)}. The system will call
+ * {@link #getMatchingRoutes(List)} with a subset of filters when a route is
+ * needed for a specific app.
+ * <p>
+ * TODO add documentation for how the sytem knows an app is interested. Maybe
+ * interface declarations in the manifest.
+ * <p>
+ * The system will only start a provider when an app may discover routes through
+ * it. If your service needs to run at other times you are responsible for
+ * managing its lifecycle.
+ * <p>
+ * Declare your route provider service in your application manifest like this:
+ * <p>
+ *
+ * <pre>
+ *   &lt;service android:name=".MyRouteProviderService"
+ *           android:label="@string/my_route_provider_service">
+ *       &lt;intent-filter>
+ *           &lt;action android:name="com.android.media.session.MediaRouteProvider" />
+ *       &lt;/intent-filter>
+ *   &lt;/service>
+ * </pre>
+ */
+public abstract class RouteProviderService extends Service {
+    private static final String TAG = "RouteProvider";
+    /**
+     * A service that implements a RouteProvider must declare that it handles
+     * this action in its AndroidManifest.
+     */
+    public static final String SERVICE_INTERFACE =
+            "com.android.media.session.MediaRouteProvider";
+
+    /**
+     * @hide
+     */
+    public static final String KEY_ROUTES = "routes";
+    /**
+     * @hide
+     */
+    public static final String KEY_CONNECTION = "connection";
+    /**
+     * @hide
+     */
+    public static final int RESULT_FAILURE = -1;
+    /**
+     * @hide
+     */
+    public static final int RESULT_SUCCESS = 0;
+
+    // The system's callback once it has bound to the service
+    private IRouteProviderCallback mCb;
+
+    /**
+     * If your service overrides onBind it must return super.onBind() in
+     * response to the {@link #SERVICE_INTERFACE} action.
+     */
+    @Override
+    public IBinder onBind(Intent intent) {
+        if (intent != null && RouteProviderService.SERVICE_INTERFACE.equals(intent.getAction())) {
+            return mBinder;
+        }
+        return null;
+    }
+
+    /**
+     * Disconnect the specified RouteConnection. The system will stop sending
+     * commands to this connection.
+     *
+     * @param connection The connection to disconnect.
+     * @hide
+     */
+    public final void disconnect(RouteConnection connection) {
+        if (mCb != null) {
+            try {
+                mCb.onConnectionTerminated(connection.getBinder());
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Error in disconnect.", e);
+            }
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public final void sendRouteEvent(RouteEvent event) {
+        if (mCb != null) {
+            try {
+                mCb.onRouteEvent(event);
+            } catch (RemoteException e) {
+                Log.wtf(TAG, "Unable to send MediaRouteEvent to system", e);
+            }
+        }
+    }
+
+    /**
+     * Override to handle updates to the routes that are of interest. Each
+     * {@link RouteRequest} will specify if it is an active or passive request.
+     * Route discovery may perform more aggressive discovery on behalf of active
+     * requests but should use low power discovery methods otherwise.
+     * <p>
+     * A single app may have more than one request. Your provider is responsible
+     * for deciding the set of features that are important for discovery given
+     * the set of requests. If your provider only has one method of discovery it
+     * may simply verify that one or more requests are valid before starting
+     * discovery.
+     *
+     * @param requests The route requests that are currently relevant.
+     */
+    public void updateDiscoveryRequests(List<RouteRequest> requests) {
+    }
+
+    /**
+     * Return a list of matching routes for the given set of requests. Returning
+     * null or an empty list indicates there are no matches. A route is
+     * considered matching if it supports one or more of the
+     * {@link RouteOptions} specified. Each returned {@link RouteInfo}
+     * should include all the requested connections that it supports.
+     *
+     * @param options The set of requests for routes
+     * @return The routes that this caller may connect to using one or more of
+     *         the route options.
+     */
+    public abstract List<RouteInfo> getMatchingRoutes(List<RouteRequest> options);
+
+    /**
+     * Handle a request to connect to a specific route with a specific request.
+     * The {@link RouteConnection} must be fully defined before being returned,
+     * though the actual connection to the route may be performed in the
+     * background.
+     *
+     * @param route The route to connect to
+     * @param request The connection request parameters
+     * @return A MediaRouteConnection representing the connection to the route
+     */
+    public abstract RouteConnection connect(RouteInfo route, RouteRequest request);
+
+    private IRouteProvider.Stub mBinder = new IRouteProvider.Stub() {
+
+        @Override
+        public void registerCallback(IRouteProviderCallback cb) throws RemoteException {
+            mCb = cb;
+        }
+
+        @Override
+        public void unregisterCallback(IRouteProviderCallback cb) throws RemoteException {
+            mCb = null;
+        }
+
+        @Override
+        public void updateDiscoveryRequests(List<RouteRequest> requests)
+                throws RemoteException {
+            RouteProviderService.this.updateDiscoveryRequests(requests);
+        }
+
+        @Override
+        public void getAvailableRoutes(List<RouteRequest> requests, ResultReceiver cb)
+                throws RemoteException {
+            List<RouteInfo> routes = RouteProviderService.this.getMatchingRoutes(requests);
+            ArrayList<RouteInfo> routesArray;
+            if (routes instanceof ArrayList) {
+                routesArray = (ArrayList<RouteInfo>) routes;
+            } else {
+                routesArray = new ArrayList<RouteInfo>(routes);
+            }
+            Bundle resultData = new Bundle();
+            resultData.putParcelableArrayList(KEY_ROUTES, routesArray);
+            cb.send(routes == null ? RESULT_FAILURE : RESULT_SUCCESS, resultData);
+        }
+
+        @Override
+        public void connect(RouteInfo route, RouteRequest request, ResultReceiver cb)
+                throws RemoteException {
+            RouteConnection connection = RouteProviderService.this.connect(route, request);
+            Bundle resultData = new Bundle();
+            if (connection != null) {
+                connection.publish();
+                resultData.putBinder(KEY_CONNECTION, connection.getBinder());
+            }
+
+            cb.send(connection == null ? RESULT_FAILURE : RESULT_SUCCESS, resultData);
+        }
+    };
+}
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/routeprovider/RouteRequest.aidl
similarity index 90%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to media/java/android/media/routeprovider/RouteRequest.aidl
index 5812682..7bc5722 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/routeprovider/RouteRequest.aidl
@@ -13,6 +13,6 @@
 ** limitations under the License.
 */
 
-package android.media.session;
+package android.media.routeprovider;
 
-parcelable MediaSessionToken;
+parcelable RouteRequest;
diff --git a/media/java/android/media/routeprovider/RouteRequest.java b/media/java/android/media/routeprovider/RouteRequest.java
new file mode 100644
index 0000000..68475c0
--- /dev/null
+++ b/media/java/android/media/routeprovider/RouteRequest.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.routeprovider;
+
+import android.media.session.RouteOptions;
+import android.media.session.SessionInfo;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.io.PrintWriter;
+
+/**
+ * A request to connect or discover routes with certain capabilities.
+ * <p>
+ * Passed to a {@link RouteProviderService} when a request for discovery or to
+ * connect to a route is made. This identifies the app making the request and
+ * provides the full set of connection parameters they would like to use for a
+ * connection. An app that can connect in multiple ways will be represented by
+ * multiple requests.
+ */
+public final class RouteRequest implements Parcelable {
+    private final SessionInfo mSessionInfo;
+    private final RouteOptions mOptions;
+    private final boolean mActive;
+
+    /**
+     * @hide
+     */
+    public RouteRequest(SessionInfo info, RouteOptions connRequest,
+            boolean active) {
+        mSessionInfo = info;
+        mOptions = connRequest;
+        mActive = active;
+    }
+
+    private RouteRequest(Parcel in) {
+        mSessionInfo = SessionInfo.CREATOR.createFromParcel(in);
+        mOptions = RouteOptions.CREATOR.createFromParcel(in);
+        mActive = in.readInt() != 0;
+    }
+
+    /**
+     * Get information about the session making the request.
+     *
+     * @return Info on the session making the request
+     */
+    public SessionInfo getSessionInfo() {
+        return mSessionInfo;
+    }
+
+    /**
+     * Get the connection options, which includes the interfaces and other
+     * connection params the session wants to use with a route.
+     *
+     * @return The connection options
+     */
+    public RouteOptions getConnectionOptions() {
+        return mOptions;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder bob = new StringBuilder();
+        bob.append("RouteRequest {");
+        bob.append("active=").append(mActive);
+        bob.append(", info=").append(mSessionInfo.toString());
+        bob.append(", options=").append(mOptions.toString());
+        bob.append("}");
+        return bob.toString();
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        mSessionInfo.writeToParcel(dest, flags);
+        mOptions.writeToParcel(dest, flags);
+        dest.writeInt(mActive ? 1 : 0);
+    }
+
+    public static final Parcelable.Creator<RouteRequest> CREATOR
+            = new Parcelable.Creator<RouteRequest>() {
+        @Override
+        public RouteRequest createFromParcel(Parcel in) {
+            return new RouteRequest(in);
+        }
+
+        @Override
+        public RouteRequest[] newArray(int size) {
+            return new RouteRequest[size];
+        }
+    };
+}
diff --git a/media/java/android/media/session/IMediaSession.aidl b/media/java/android/media/session/ISession.aidl
similarity index 64%
rename from media/java/android/media/session/IMediaSession.aidl
rename to media/java/android/media/session/ISession.aidl
index aed7641..ca77f04 100644
--- a/media/java/android/media/session/IMediaSession.aidl
+++ b/media/java/android/media/session/ISession.aidl
@@ -15,25 +15,33 @@
 
 package android.media.session;
 
-import android.media.session.IMediaController;
+import android.media.session.ISessionController;
 import android.media.session.MediaMetadata;
+import android.media.session.RouteOptions;
+import android.media.session.RouteCommand;
+import android.media.session.RouteInfo;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
+import android.os.ResultReceiver;
 
 /**
  * Interface to a MediaSession in the system.
  * @hide
  */
-interface IMediaSession {
+interface ISession {
     void sendEvent(String event, in Bundle data);
-    IMediaController getMediaController();
+    ISessionController getController();
     void setTransportPerformerEnabled();
-    void setRouteState(in Bundle routeState);
-    void setRoute(in Bundle mediaRouteDescriptor);
-    List<String> getSupportedInterfaces();
     void publish();
     void destroy();
 
+    // These commands are for setting up and communicating with routes
+    // Returns true if the route was set for this session
+    boolean setRoute(in RouteInfo route);
+    void setRouteOptions(in List<RouteOptions> options);
+    void connectToRoute(in RouteInfo route, in RouteOptions options);
+    void sendRouteCommand(in RouteCommand event, in ResultReceiver cb);
+
     // These commands are for the TransportPerformer
     void setMetadata(in MediaMetadata metadata);
     void setPlaybackState(in PlaybackState state);
diff --git a/media/java/android/media/session/IMediaSessionCallback.aidl b/media/java/android/media/session/ISessionCallback.aidl
similarity index 73%
rename from media/java/android/media/session/IMediaSessionCallback.aidl
rename to media/java/android/media/session/ISessionCallback.aidl
index 7c183e0..f04cbcc 100644
--- a/media/java/android/media/session/IMediaSessionCallback.aidl
+++ b/media/java/android/media/session/ISessionCallback.aidl
@@ -16,6 +16,9 @@
 package android.media.session;
 
 import android.media.Rating;
+import android.media.session.RouteEvent;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.ResultReceiver;
@@ -23,10 +26,13 @@
 /**
  * @hide
  */
-oneway interface IMediaSessionCallback {
+oneway interface ISessionCallback {
     void onCommand(String command, in Bundle extras, in ResultReceiver cb);
-    void onMediaButton(in Intent mediaRequestIntent);
-    void onRequestRouteChange(in Bundle route);
+    void onMediaButton(in Intent mediaButtonIntent);
+    void onRequestRouteChange(in RouteInfo route);
+    void onRouteConnected(in RouteInfo route, in RouteOptions options);
+    void onRouteStateChange(int state);
+    void onRouteEvent(in RouteEvent event);
 
     // These callbacks are for the TransportPerformer
     void onPlay();
diff --git a/media/java/android/media/session/IMediaController.aidl b/media/java/android/media/session/ISessionController.aidl
similarity index 85%
rename from media/java/android/media/session/IMediaController.aidl
rename to media/java/android/media/session/ISessionController.aidl
index d34e973..e2e046f 100644
--- a/media/java/android/media/session/IMediaController.aidl
+++ b/media/java/android/media/session/ISessionController.aidl
@@ -17,7 +17,7 @@
 
 import android.content.Intent;
 import android.media.Rating;
-import android.media.session.IMediaControllerCallback;
+import android.media.session.ISessionControllerCallback;
 import android.media.session.MediaMetadata;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
@@ -28,12 +28,13 @@
  * Interface to a MediaSession in the system.
  * @hide
  */
-interface IMediaController {
+interface ISessionController {
     void sendCommand(String command, in Bundle extras, in ResultReceiver cb);
     void sendMediaButton(in KeyEvent mediaButton);
-    void registerCallbackListener(in IMediaControllerCallback cb);
-    void unregisterCallbackListener(in IMediaControllerCallback cb);
+    void registerCallbackListener(in ISessionControllerCallback cb);
+    void unregisterCallbackListener(in ISessionControllerCallback cb);
     boolean isTransportControlEnabled();
+    void showRoutePicker();
 
     // These commands are for the TransportController
     void play();
diff --git a/media/java/android/media/session/IMediaControllerCallback.aidl b/media/java/android/media/session/ISessionControllerCallback.aidl
similarity index 88%
rename from media/java/android/media/session/IMediaControllerCallback.aidl
rename to media/java/android/media/session/ISessionControllerCallback.aidl
index 3651f1b..bc1ae05 100644
--- a/media/java/android/media/session/IMediaControllerCallback.aidl
+++ b/media/java/android/media/session/ISessionControllerCallback.aidl
@@ -16,15 +16,16 @@
 package android.media.session;
 
 import android.media.session.MediaMetadata;
+import android.media.session.RouteInfo;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
 
 /**
  * @hide
  */
-oneway interface IMediaControllerCallback {
+oneway interface ISessionControllerCallback {
     void onEvent(String event, in Bundle extras);
-    void onRouteChanged(in Bundle route);
+    void onRouteChanged(in RouteInfo route);
 
     // These callbacks are for the TransportController
     void onPlaybackStateChanged(in PlaybackState state);
diff --git a/media/java/android/media/session/IMediaSessionManager.aidl b/media/java/android/media/session/ISessionManager.aidl
similarity index 77%
rename from media/java/android/media/session/IMediaSessionManager.aidl
rename to media/java/android/media/session/ISessionManager.aidl
index 0b4328e..84b9a0f 100644
--- a/media/java/android/media/session/IMediaSessionManager.aidl
+++ b/media/java/android/media/session/ISessionManager.aidl
@@ -15,14 +15,14 @@
 
 package android.media.session;
 
-import android.media.session.IMediaSession;
-import android.media.session.IMediaSessionCallback;
+import android.media.session.ISession;
+import android.media.session.ISessionCallback;
 import android.os.Bundle;
 
 /**
  * Interface to the MediaSessionManagerService
  * @hide
  */
-interface IMediaSessionManager {
-    IMediaSession createSession(String packageName, in IMediaSessionCallback cb, String tag);
+interface ISessionManager {
+    ISession createSession(String packageName, in ISessionCallback cb, String tag);
 }
\ No newline at end of file
diff --git a/media/java/android/media/session/MediaMetadata.java b/media/java/android/media/session/MediaMetadata.java
index e2330f7..56bdf68 100644
--- a/media/java/android/media/session/MediaMetadata.java
+++ b/media/java/android/media/session/MediaMetadata.java
@@ -16,12 +16,15 @@
 package android.media.session;
 
 import android.graphics.Bitmap;
+import android.media.MediaMetadataEditor;
+import android.media.MediaMetadataRetriever;
 import android.media.Rating;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.ArrayMap;
 import android.util.Log;
+import android.util.SparseArray;
 
 /**
  * Contains metadata about an item, such as the title, artist, etc.
@@ -40,7 +43,8 @@
     public static final String METADATA_KEY_ARTIST = "android.media.metadata.ARTIST";
 
     /**
-     * The duration of the media in ms. A duration of 0 is the default.
+     * The duration of the media in ms. A negative duration indicates that the
+     * duration is unknown (or infinite).
      */
     public static final String METADATA_KEY_DURATION = "android.media.metadata.DURATION";
 
@@ -65,12 +69,17 @@
     public static final String METADATA_KEY_COMPOSER = "android.media.metadata.COMPOSER";
 
     /**
+     * The compilation status of the media.
+     */
+    public static final String METADATA_KEY_COMPILATION = "android.media.metadata.COMPILATION";
+
+    /**
      * The date the media was created or published as TODO determine format.
      */
     public static final String METADATA_KEY_DATE = "android.media.metadata.DATE";
 
     /**
-     * The year the media was created or published as a numeric String.
+     * The year the media was created or published as a long.
      */
     public static final String METADATA_KEY_YEAR = "android.media.metadata.YEAR";
 
@@ -151,8 +160,9 @@
         METADATA_KEYS_TYPE.put(METADATA_KEY_AUTHOR, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_WRITER, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_COMPOSER, METADATA_TYPE_STRING);
+        METADATA_KEYS_TYPE.put(METADATA_KEY_COMPILATION, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_DATE, METADATA_TYPE_STRING);
-        METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_STRING);
+        METADATA_KEYS_TYPE.put(METADATA_KEY_YEAR, METADATA_TYPE_LONG);
         METADATA_KEYS_TYPE.put(METADATA_KEY_GENRE, METADATA_TYPE_STRING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_TRACK_NUMBER, METADATA_TYPE_LONG);
         METADATA_KEYS_TYPE.put(METADATA_KEY_NUM_TRACKS, METADATA_TYPE_LONG);
@@ -165,6 +175,36 @@
         METADATA_KEYS_TYPE.put(METADATA_KEY_USER_RATING, METADATA_TYPE_RATING);
         METADATA_KEYS_TYPE.put(METADATA_KEY_RATING, METADATA_TYPE_RATING);
     }
+
+    private static final SparseArray<String> EDITOR_KEY_MAPPING;
+
+    static {
+        EDITOR_KEY_MAPPING = new SparseArray<String>();
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.BITMAP_KEY_ARTWORK, METADATA_KEY_ART);
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_OTHERS, METADATA_KEY_RATING);
+        EDITOR_KEY_MAPPING.put(MediaMetadataEditor.RATING_KEY_BY_USER, METADATA_KEY_USER_RATING);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUM, METADATA_KEY_ALBUM);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ALBUMARTIST,
+                METADATA_KEY_ALBUM_ARTIST);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_ARTIST, METADATA_KEY_ARTIST);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_AUTHOR, METADATA_KEY_AUTHOR);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER,
+                METADATA_KEY_TRACK_NUMBER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPOSER, METADATA_KEY_COMPOSER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_COMPILATION,
+                METADATA_KEY_COMPILATION);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DATE, METADATA_KEY_DATE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DISC_NUMBER,
+                METADATA_KEY_DISC_NUMBER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_DURATION, METADATA_KEY_DURATION);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_GENRE, METADATA_KEY_GENRE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_NUM_TRACKS,
+                METADATA_KEY_NUM_TRACKS);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_TITLE, METADATA_KEY_TITLE);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_WRITER, METADATA_KEY_WRITER);
+        EDITOR_KEY_MAPPING.put(MediaMetadataRetriever.METADATA_KEY_YEAR, METADATA_KEY_YEAR);
+    }
+
     private final Bundle mBundle;
 
     private MediaMetadata(Bundle bundle) {
@@ -176,6 +216,16 @@
     }
 
     /**
+     * Returns true if the given key is contained in the metadata
+     *
+     * @param key a String key
+     * @return true if the key exists in this metadata, false otherwise
+     */
+    public boolean containsKey(String key) {
+        return mBundle.containsKey(key);
+    }
+
+    /**
      * Returns the value associated with the given key, or null if no mapping of
      * the desired type exists for the given key or a null value is explicitly
      * associated with the key.
@@ -195,7 +245,7 @@
      * @return a long value
      */
     public long getLong(String key) {
-        return mBundle.getLong(key);
+        return mBundle.getLong(key, 0);
     }
 
     /**
@@ -244,6 +294,18 @@
         dest.writeBundle(mBundle);
     }
 
+    /**
+     * Helper for getting the String key used by {@link MediaMetadata} from the
+     * integer key that {@link MediaMetadataEditor} uses.
+     *
+     * @param editorKey The key used by the editor
+     * @return The key used by this class or null if no mapping exists
+     * @hide
+     */
+    public static String getKeyFromMetadataEditorKey(int editorKey) {
+        return EDITOR_KEY_MAPPING.get(editorKey, null);
+    }
+
     public static final Parcelable.Creator<MediaMetadata> CREATOR
             = new Parcelable.Creator<MediaMetadata>() {
                 @Override
@@ -295,10 +357,9 @@
          * <li>{@link #METADATA_KEY_WRITER}</li>
          * <li>{@link #METADATA_KEY_COMPOSER}</li>
          * <li>{@link #METADATA_KEY_DATE}</li>
-         * <li>{@link #METADATA_KEY_YEAR}</li>
          * <li>{@link #METADATA_KEY_GENRE}</li>
-         * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>li>
-         * <li>{@link #METADATA_KEY_ART_URI}</li>li>
+         * <li>{@link #METADATA_KEY_ALBUM_ARTIST}</li>
+         * <li>{@link #METADATA_KEY_ART_URI}</li>
          * <li>{@link #METADATA_KEY_ALBUM_ART_URI}</li>
          * </ul>
          *
@@ -326,6 +387,7 @@
          * <li>{@link #METADATA_KEY_TRACK_NUMBER}</li>
          * <li>{@link #METADATA_KEY_NUM_TRACKS}</li>
          * <li>{@link #METADATA_KEY_DISC_NUMBER}</li>
+         * <li>{@link #METADATA_KEY_YEAR}</li>
          * </ul>
          *
          * @param key The key for referencing this value
diff --git a/media/java/android/media/session/MediaSessionLegacyHelper.java b/media/java/android/media/session/MediaSessionLegacyHelper.java
new file mode 100644
index 0000000..4ee67d1
--- /dev/null
+++ b/media/java/android/media/session/MediaSessionLegacyHelper.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.media.session;
+
+import android.app.PendingIntent;
+import android.app.PendingIntent.CanceledException;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Looper;
+import android.util.ArrayMap;
+import android.util.Log;
+import android.view.KeyEvent;
+
+/**
+ * Helper for connecting existing APIs up to the new session APIs. This can be
+ * used by RCC, AudioFocus, etc. to create a single session that translates to
+ * all those components.
+ *
+ * @hide
+ */
+public class MediaSessionLegacyHelper {
+    private static final String TAG = "MediaSessionHelper";
+
+    private static final Object sLock = new Object();
+    private static MediaSessionLegacyHelper sInstance;
+
+    private SessionManager mSessionManager;
+    private Handler mHandler = new Handler(Looper.getMainLooper());
+    // The legacy APIs use PendingIntents to register/unregister media button
+    // receivers and these are associated with RCC.
+    private ArrayMap<PendingIntent, SessionHolder> mSessions = new ArrayMap<PendingIntent, SessionHolder>();
+
+    private MediaSessionLegacyHelper(Context context) {
+        mSessionManager = (SessionManager) context
+                .getSystemService(Context.MEDIA_SESSION_SERVICE);
+    }
+
+    public static MediaSessionLegacyHelper getHelper(Context context) {
+        synchronized (sLock) {
+            if (sInstance == null) {
+                sInstance = new MediaSessionLegacyHelper(context);
+            }
+        }
+        return sInstance;
+    }
+
+    public Session getSession(PendingIntent pi) {
+        SessionHolder holder = mSessions.get(pi);
+        return holder == null ? null : holder.mSession;
+    }
+
+    public void addRccListener(PendingIntent pi, TransportPerformer.Listener listener) {
+
+        SessionHolder holder = getHolder(pi, true);
+        TransportPerformer performer = holder.mSession.getTransportPerformer();
+        if (holder.mRccListener != null) {
+            if (holder.mRccListener == listener) {
+                // This is already the registered listener, ignore
+                return;
+            }
+            // Otherwise it changed so we need to switch to the new one
+            performer.removeListener(holder.mRccListener);
+        }
+        performer.addListener(listener, mHandler);
+        holder.mRccListener = listener;
+        holder.update();
+    }
+
+    public void removeRccListener(PendingIntent pi) {
+        SessionHolder holder = getHolder(pi, false);
+        if (holder != null && holder.mRccListener != null) {
+            holder.mSession.getTransportPerformer().removeListener(holder.mRccListener);
+            holder.mRccListener = null;
+            holder.update();
+        }
+    }
+
+    public void addMediaButtonListener(PendingIntent pi,
+            Context context) {
+        SessionHolder holder = getHolder(pi, true);
+        if (holder.mMediaButtonListener != null) {
+            // Already have this listener registered
+            return;
+        }
+        holder.mMediaButtonListener = new MediaButtonListener(pi, context);
+        holder.mSession.getTransportPerformer().addListener(holder.mMediaButtonListener, mHandler);
+    }
+
+    public void removeMediaButtonListener(PendingIntent pi) {
+        SessionHolder holder = getHolder(pi, false);
+        if (holder != null && holder.mMediaButtonListener != null) {
+            holder.mSession.getTransportPerformer().removeListener(holder.mMediaButtonListener);
+            holder.update();
+        }
+    }
+
+    private SessionHolder getHolder(PendingIntent pi, boolean createIfMissing) {
+        SessionHolder holder = mSessions.get(pi);
+        if (holder == null && createIfMissing) {
+            Session session = mSessionManager.createSession(TAG);
+            session.setTransportPerformerEnabled();
+            session.publish();
+            holder = new SessionHolder(session, pi);
+            mSessions.put(pi, holder);
+        }
+        return holder;
+    }
+
+    public static class MediaButtonListener extends TransportPerformer.Listener {
+        private final PendingIntent mPendingIntent;
+        private final Context mContext;
+
+        public MediaButtonListener(PendingIntent pi, Context context) {
+            mPendingIntent = pi;
+            mContext = context;
+        }
+
+        @Override
+        public void onPlay() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PLAY);
+        }
+
+        @Override
+        public void onPause() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PAUSE);
+        }
+
+        @Override
+        public void onNext() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_NEXT);
+        }
+
+        @Override
+        public void onPrevious() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_PREVIOUS);
+        }
+
+        @Override
+        public void onFastForward() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_FAST_FORWARD);
+        }
+
+        @Override
+        public void onRewind() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_REWIND);
+        }
+
+        @Override
+        public void onStop() {
+            sendKeyEvent(KeyEvent.KEYCODE_MEDIA_STOP);
+        }
+
+        private void sendKeyEvent(int keyCode) {
+            KeyEvent ke = new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
+            Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON);
+
+            intent.putExtra(Intent.EXTRA_KEY_EVENT, ke);
+            try {
+                mPendingIntent.send(mContext, 0, intent);
+            } catch (CanceledException e) {
+                Log.e(TAG, "Error sending media key down event:", e);
+                // Don't bother sending up if down failed
+                return;
+            }
+
+            ke = new KeyEvent(KeyEvent.ACTION_UP, keyCode);
+            intent.putExtra(Intent.EXTRA_KEY_EVENT, ke);
+            try {
+                mPendingIntent.send(mContext, 0, intent);
+            } catch (CanceledException e) {
+                Log.e(TAG, "Error sending media key up event:", e);
+            }
+        }
+    }
+
+    private class SessionHolder {
+        public final Session mSession;
+        public final PendingIntent mPi;
+        public MediaButtonListener mMediaButtonListener;
+        public TransportPerformer.Listener mRccListener;
+
+        public SessionHolder(Session session, PendingIntent pi) {
+            mSession = session;
+            mPi = pi;
+        }
+
+        public void update() {
+            if (mMediaButtonListener == null && mRccListener == null) {
+                mSession.release();
+                mSessions.remove(mPi);
+            } else if (mMediaButtonListener != null && mRccListener != null) {
+                // TODO set session to active
+            } else {
+                // TODO set session to inactive
+            }
+        }
+    }
+}
diff --git a/media/java/android/media/session/PlaybackState.java b/media/java/android/media/session/PlaybackState.java
index b3506b3..9e58ea8 100644
--- a/media/java/android/media/session/PlaybackState.java
+++ b/media/java/android/media/session/PlaybackState.java
@@ -18,9 +18,10 @@
 import android.media.RemoteControlClient;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.os.SystemClock;
 
 /**
- * Playback state for a {@link MediaSession}. This includes a state like
+ * Playback state for a {@link Session}. This includes a state like
  * {@link PlaybackState#PLAYSTATE_PLAYING}, the current playback position,
  * and the current control capabilities.
  */
@@ -89,6 +90,13 @@
     public static final long ACTION_SEEK_TO = 1 << 8;
 
     /**
+     * Indicates this performer supports the play/pause toggle command.
+     *
+     * @see #setActions
+     */
+    public static final long ACTION_PLAY_PAUSE = 1 << 9;
+
+    /**
      * This is the default playback state and indicates that no media has been
      * added yet, or the performer has been reset and has no content to play.
      *
@@ -147,12 +155,41 @@
      */
     public final static int PLAYSTATE_ERROR = 7;
 
+    /**
+     * State indicating the class doing playback is currently connecting to a
+     * route. Depending on the implementation you may return to the previous
+     * state when the connection finishes or enter {@link #PLAYSTATE_NONE}. If
+     * the connection failed {@link #PLAYSTATE_ERROR} should be used.
+     */
+    public final static int PLAYSTATE_CONNECTING = 8;
+
+    /**
+     * State indicating the player is currently skipping to the previous item.
+     *
+     * @see #setState
+     */
+    public final static int PLAYSTATE_SKIPPING_BACKWARDS = 9;
+
+    /**
+     * State indicating the player is currently skipping to the next item.
+     *
+     * @see #setState
+     */
+    public final static int PLAYSTATE_SKIPPING_FORWARDS = 10;
+
+    /**
+     * Set this value on {@link #setPosition(long)} to indicate the position is
+     * not known for this item.
+     */
+    public final static long PLAYBACK_POSITION_UNKNOWN = -1;
+
     private int mState;
     private long mPosition;
     private long mBufferPosition;
-    private float mSpeed;
-    private long mCapabilities;
+    private float mRate;
+    private long mActions;
     private String mErrorMessage;
+    private long mUpdateTime;
 
     /**
      * Create an empty PlaybackState. At minimum a state and actions should be
@@ -168,21 +205,24 @@
      * @param from The PlaybackState to duplicate
      */
     public PlaybackState(PlaybackState from) {
-        this.setState(from.getState());
-        this.setPosition(from.getPosition());
-        this.setBufferPosition(from.getBufferPosition());
-        this.setSpeed(from.getSpeed());
-        this.setActions(from.getActions());
-        this.setErrorMessage(from.getErrorMessage());
+        mState = from.mState;
+        mPosition = from.mPosition;
+        mRate = from.mRate;
+        mUpdateTime = from.mUpdateTime;
+        mBufferPosition = from.mBufferPosition;
+        mActions = from.mActions;
+        mErrorMessage = from.mErrorMessage;
     }
 
     private PlaybackState(Parcel in) {
-        this.setState(in.readInt());
-        this.setPosition(in.readLong());
-        this.setBufferPosition(in.readLong());
-        this.setSpeed(in.readFloat());
-        this.setActions(in.readLong());
-        this.setErrorMessage(in.readString());
+        mState = in.readInt();
+        mPosition = in.readLong();
+        mRate = in.readFloat();
+        mUpdateTime = in.readLong();
+        mBufferPosition = in.readLong();
+        mActions = in.readLong();
+        mErrorMessage = in.readString();
+
     }
 
     @Override
@@ -192,12 +232,13 @@
 
     @Override
     public void writeToParcel(Parcel dest, int flags) {
-        dest.writeInt(getState());
-        dest.writeLong(getPosition());
-        dest.writeLong(getBufferPosition());
-        dest.writeFloat(getSpeed());
-        dest.writeLong(getActions());
-        dest.writeString(getErrorMessage());
+        dest.writeInt(mState);
+        dest.writeLong(mPosition);
+        dest.writeFloat(mRate);
+        dest.writeLong(mUpdateTime);
+        dest.writeLong(mBufferPosition);
+        dest.writeLong(mActions);
+        dest.writeString(mErrorMessage);
     }
 
     /**
@@ -217,7 +258,16 @@
     }
 
     /**
-     * Set the current state of playback. One of the following:
+     * Set the current state of playback.
+     * <p>
+     * The position must be in ms and indicates the current playback position
+     * within the track. If the position is unknown use
+     * {@link #PLAYBACK_POSITION_UNKNOWN}.
+     * <p>
+     * The rate is a multiple of normal playback and should be 0 when paused and
+     * negative when rewinding. Normal playback rate is 1.0.
+     * <p>
+     * The state must be one of the following:
      * <ul>
      * <li> {@link PlaybackState#PLAYSTATE_NONE}</li>
      * <li> {@link PlaybackState#PLAYSTATE_STOPPED}</li>
@@ -227,9 +277,18 @@
      * <li> {@link PlaybackState#PLAYSTATE_REWINDING}</li>
      * <li> {@link PlaybackState#PLAYSTATE_BUFFERING}</li>
      * <li> {@link PlaybackState#PLAYSTATE_ERROR}</li>
+     * </ul>
+     *
+     * @param state The current state of playback.
+     * @param position The position in the current track in ms.
+     * @param rate The current rate of playback as a multiple of normal
+     *            playback.
      */
-    public void setState(int mState) {
-        this.mState = mState;
+    public void setState(int state, long position, float rate) {
+        this.mState = state;
+        this.mPosition = position;
+        this.mRate = rate;
+        mUpdateTime = SystemClock.elapsedRealtime();
     }
 
     /**
@@ -240,13 +299,6 @@
     }
 
     /**
-     * Set the current playback position in ms.
-     */
-    public void setPosition(long position) {
-        mPosition = position;
-    }
-
-    /**
      * Get the current buffer position in ms. This is the farthest playback
      * point that can be reached from the current position using only buffered
      * content.
@@ -265,21 +317,14 @@
     }
 
     /**
-     * Get the current playback speed as a multiple of normal playback. This
+     * Get the current playback rate as a multiple of normal playback. This
      * should be negative when rewinding. A value of 1 means normal playback and
      * 0 means paused.
+     *
+     * @return The current rate of playback.
      */
-    public float getSpeed() {
-        return mSpeed;
-    }
-
-    /**
-     * Set the current playback speed as a multiple of normal playback. This
-     * should be negative when rewinding. A value of 1 means normal playback and
-     * 0 means paused.
-     */
-    public void setSpeed(float speed) {
-        mSpeed = speed;
+    public float getRate() {
+        return mRate;
     }
 
     /**
@@ -298,7 +343,7 @@
      * </ul>
      */
     public long getActions() {
-        return mCapabilities;
+        return mActions;
     }
 
     /**
@@ -317,7 +362,7 @@
      * </ul>
      */
     public void setActions(long capabilities) {
-        mCapabilities = capabilities;
+        mActions = capabilities;
     }
 
     /**
@@ -329,6 +374,17 @@
     }
 
     /**
+     * Get the elapsed real time at which position was last updated. If the
+     * position has never been set this will return 0;
+     *
+     * @return The last time the position was updated.
+     * @hide
+     */
+    public long getLastPositionUpdateTime() {
+        return mUpdateTime;
+    }
+
+    /**
      * Set a user readable error message. This should be set when the state is
      * {@link PlaybackState#PLAYSTATE_ERROR}.
      */
@@ -336,6 +392,80 @@
         mErrorMessage = errorMessage;
     }
 
+    /**
+     * Get the {@link PlaybackState} state for the given
+     * {@link RemoteControlClient} state.
+     *
+     * @param rccState The state used by {@link RemoteControlClient}.
+     * @return The equivalent state used by {@link PlaybackState}.
+     * @hide
+     */
+    public static int getStateFromRccState(int rccState) {
+        switch (rccState) {
+            case RemoteControlClient.PLAYSTATE_BUFFERING:
+                return PLAYSTATE_BUFFERING;
+            case RemoteControlClient.PLAYSTATE_ERROR:
+                return PLAYSTATE_ERROR;
+            case RemoteControlClient.PLAYSTATE_FAST_FORWARDING:
+                return PLAYSTATE_FAST_FORWARDING;
+            case RemoteControlClient.PLAYSTATE_NONE:
+                return PLAYSTATE_NONE;
+            case RemoteControlClient.PLAYSTATE_PAUSED:
+                return PLAYSTATE_PAUSED;
+            case RemoteControlClient.PLAYSTATE_PLAYING:
+                return PLAYSTATE_PLAYING;
+            case RemoteControlClient.PLAYSTATE_REWINDING:
+                return PLAYSTATE_REWINDING;
+            case RemoteControlClient.PLAYSTATE_SKIPPING_BACKWARDS:
+                return PLAYSTATE_SKIPPING_BACKWARDS;
+            case RemoteControlClient.PLAYSTATE_STOPPED:
+                return PLAYSTATE_STOPPED;
+            default:
+                return -1;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public static long getActionsFromRccControlFlags(int rccFlags) {
+        long actions = 0;
+        long flag = 1;
+        while (flag <= rccFlags) {
+            if ((flag & rccFlags) != 0) {
+                actions |= getActionForRccFlag((int) flag);
+            }
+            flag = flag << 1;
+        }
+        return actions;
+    }
+
+    private static long getActionForRccFlag(int flag) {
+        switch (flag) {
+            case RemoteControlClient.FLAG_KEY_MEDIA_PREVIOUS:
+                return ACTION_PREVIOUS_ITEM;
+            case RemoteControlClient.FLAG_KEY_MEDIA_REWIND:
+                return ACTION_REWIND;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PLAY:
+                return ACTION_PLAY;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PLAY_PAUSE:
+                return ACTION_PLAY_PAUSE;
+            case RemoteControlClient.FLAG_KEY_MEDIA_PAUSE:
+                return ACTION_PAUSE;
+            case RemoteControlClient.FLAG_KEY_MEDIA_STOP:
+                return ACTION_STOP;
+            case RemoteControlClient.FLAG_KEY_MEDIA_FAST_FORWARD:
+                return ACTION_FASTFORWARD;
+            case RemoteControlClient.FLAG_KEY_MEDIA_NEXT:
+                return ACTION_NEXT_ITEM;
+            case RemoteControlClient.FLAG_KEY_MEDIA_POSITION_UPDATE:
+                return ACTION_SEEK_TO;
+            case RemoteControlClient.FLAG_KEY_MEDIA_RATING:
+                return ACTION_RATING;
+        }
+        return 0;
+    }
+
     public static final Parcelable.Creator<PlaybackState> CREATOR
             = new Parcelable.Creator<PlaybackState>() {
         @Override
diff --git a/media/java/android/media/session/Route.java b/media/java/android/media/session/Route.java
new file mode 100644
index 0000000..c9530a6
--- /dev/null
+++ b/media/java/android/media/session/Route.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.List;
+
+/**
+ * Represents a destination which an application has connected to and may send
+ * media content.
+ * <p>
+ * This allows a session owner to interact with a route it has been connected
+ * to. The MediaRoute must be used to get {@link RouteInterface}
+ * instances which can be used to communicate over a specific interface on the
+ * route.
+ */
+public final class Route {
+    private static final String TAG = "Route";
+    private final RouteInfo mInfo;
+    private final Session mSession;
+    private final RouteOptions mOptions;
+
+    /**
+     * @hide
+     */
+    public Route(RouteInfo info, RouteOptions options, Session session) {
+        if (info == null || options == null) {
+            throw new IllegalStateException("Route info was not valid!");
+        }
+        mInfo = info;
+        mOptions = options;
+        mSession = session;
+    }
+
+    /**
+     * Get the {@link RouteInfo} for this route.
+     *
+     * @return The info for this route.
+     */
+    public RouteInfo getRouteInfo() {
+        return mInfo;
+    }
+
+    /**
+     * Get the {@link RouteOptions} that were used to connect this route.
+     *
+     * @return The options used to connect to this route.
+     */
+    public RouteOptions getOptions() {
+        return mOptions;
+    }
+
+    /**
+     * Gets an interface provided by this route. If the interface is not
+     * supported by the route, returns null.
+     *
+     * @see RouteInterface
+     * @param iface The name of the interface to create
+     * @return A {@link RouteInterface} or null if the interface is
+     *         not supported.
+     */
+    public RouteInterface getInterface(String iface) {
+        if (TextUtils.isEmpty(iface)) {
+            throw new IllegalArgumentException("iface may not be empty.");
+        }
+        List<String> ifaces = mOptions.getInterfaceNames();
+        if (ifaces != null) {
+            for (int i = ifaces.size() - 1; i >= 0; i--) {
+                if (iface.equals(ifaces.get(i))) {
+                    return new RouteInterface(this, iface, mSession);
+                }
+            }
+        }
+        Log.e(TAG, "Interface not supported by route");
+        return null;
+    }
+
+    /**
+     * @hide
+     */
+    Session getSession() {
+        return mSession;
+    }
+}
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/RouteCommand.aidl
similarity index 95%
rename from media/java/android/media/session/MediaSessionToken.aidl
rename to media/java/android/media/session/RouteCommand.aidl
index 5812682..725b308 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/session/RouteCommand.aidl
@@ -15,4 +15,4 @@
 
 package android.media.session;
 
-parcelable MediaSessionToken;
+parcelable RouteCommand;
diff --git a/media/java/android/media/session/RouteCommand.java b/media/java/android/media/session/RouteCommand.java
new file mode 100644
index 0000000..358bc0a
--- /dev/null
+++ b/media/java/android/media/session/RouteCommand.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a command that an application may send to a route.
+ * <p>
+ * Commands are associated with a specific route and interface supported by that
+ * route and sent through the session. This class isn't used directly by apps.
+ *
+ * @hide
+ */
+public final class RouteCommand implements Parcelable {
+    private final String mRoute;
+    private final String mIface;
+    private final String mEvent;
+    private final Bundle mExtras;
+
+    /**
+     * @param route The id of the route this event is being sent on
+     * @param iface The interface the sender used
+     * @param event The event or command
+     * @param extras Any extras included with the event
+     */
+    public RouteCommand(String route, String iface, String event, Bundle extras) {
+        mRoute = route;
+        mIface = iface;
+        mEvent = event;
+        mExtras = extras;
+    }
+
+    private RouteCommand(Parcel in) {
+        mRoute = in.readString();
+        mIface = in.readString();
+        mEvent = in.readString();
+        mExtras = in.readBundle();
+    }
+
+    /**
+     * Get the id for the route this event was sent on.
+     *
+     * @return The route id this event is using
+     */
+    public String getRouteInfo() {
+        return mRoute;
+    }
+
+    /**
+     * Get the interface this event was sent from
+     *
+     * @return The interface for this event
+     */
+    public String getIface() {
+        return mIface;
+    }
+
+    /**
+     * Get the action/name of the event.
+     *
+     * @return The name of event/command.
+     */
+    public String getEvent() {
+        return mEvent;
+    }
+
+    /**
+     * Get any extras included with the event.
+     *
+     * @return The bundle included with the event or null
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mRoute);
+        dest.writeString(mIface);
+        dest.writeString(mEvent);
+        dest.writeBundle(mExtras);
+    }
+
+    public static final Parcelable.Creator<RouteCommand> CREATOR
+            = new Parcelable.Creator<RouteCommand>() {
+        @Override
+        public RouteCommand createFromParcel(Parcel in) {
+            return new RouteCommand(in);
+        }
+
+        @Override
+        public RouteCommand[] newArray(int size) {
+            return new RouteCommand[size];
+        }
+    };
+}
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/RouteEvent.aidl
similarity index 95%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to media/java/android/media/session/RouteEvent.aidl
index 5812682..6966207 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/session/RouteEvent.aidl
@@ -15,4 +15,4 @@
 
 package android.media.session;
 
-parcelable MediaSessionToken;
+parcelable RouteEvent;
diff --git a/media/java/android/media/session/RouteEvent.java b/media/java/android/media/session/RouteEvent.java
new file mode 100644
index 0000000..918e410
--- /dev/null
+++ b/media/java/android/media/session/RouteEvent.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.media.routeprovider.RouteConnection;
+import android.media.routeprovider.RouteProviderService;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents an event that a route provider is sending to a particular
+ * {@link RouteConnection}. Events are associated with a specific interface
+ * supported by the connection and sent through the {@link RouteProviderService}.
+ * This class isn't used directly by apps.
+ *
+ * @hide
+ */
+public class RouteEvent implements Parcelable {
+    private final IBinder mConnection;
+    private final String mIface;
+    private final String mEvent;
+    private final Bundle mExtras;
+
+    /**
+     * @param connection The connection that this event is for
+     * @param iface The interface the sender used
+     * @param event The event or command
+     * @param extras Any extras included with the event
+     */
+    public RouteEvent(IBinder connection, String iface, String event, Bundle extras) {
+        mConnection = connection;
+        mIface = iface;
+        mEvent = event;
+        mExtras = extras;
+    }
+
+    private RouteEvent(Parcel in) {
+        mConnection = in.readStrongBinder();
+        mIface = in.readString();
+        mEvent = in.readString();
+        mExtras = in.readBundle();
+    }
+
+    /**
+     * Get the connection this event was sent on.
+     *
+     * @return The connection this event is using
+     */
+    public IBinder getConnection() {
+        return mConnection;
+    }
+
+    /**
+     * Get the interface this event was sent from
+     *
+     * @return The interface for this event
+     */
+    public String getIface() {
+        return mIface;
+    }
+
+    /**
+     * Get the action/name of the event.
+     *
+     * @return The name of event/command.
+     */
+    public String getEvent() {
+        return mEvent;
+    }
+
+    /**
+     * Get any extras included with the event.
+     *
+     * @return The bundle included with the event or null
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStrongBinder(mConnection);
+        dest.writeString(mIface);
+        dest.writeString(mEvent);
+        dest.writeBundle(mExtras);
+    }
+
+    public static final Parcelable.Creator<RouteEvent> CREATOR
+            = new Parcelable.Creator<RouteEvent>() {
+        @Override
+        public RouteEvent createFromParcel(Parcel in) {
+            return new RouteEvent(in);
+        }
+
+        @Override
+        public RouteEvent[] newArray(int size) {
+            return new RouteEvent[size];
+        }
+    };
+}
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/RouteInfo.aidl
similarity index 95%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to media/java/android/media/session/RouteInfo.aidl
index 5812682..c5f50c8 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/session/RouteInfo.aidl
@@ -15,4 +15,4 @@
 
 package android.media.session;
 
-parcelable MediaSessionToken;
+parcelable RouteInfo;
diff --git a/media/java/android/media/session/RouteInfo.java b/media/java/android/media/session/RouteInfo.java
new file mode 100644
index 0000000..17df969
--- /dev/null
+++ b/media/java/android/media/session/RouteInfo.java
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Information about a route, including its display name, a way to identify it,
+ * and the ways it can be connected to.
+ */
+public final class RouteInfo implements Parcelable {
+    private final String mName;
+    private final String mId;
+    private final String mProviderId;
+    private final List<RouteOptions> mOptions;
+
+    private RouteInfo(String id, String name, String providerId,
+            List<RouteOptions> connRequests) {
+        mId = id;
+        mName = name;
+        mProviderId = providerId;
+        mOptions = connRequests;
+    }
+
+    private RouteInfo(Parcel in) {
+        mId = in.readString();
+        mName = in.readString();
+        mProviderId = in.readString();
+        mOptions = new ArrayList<RouteOptions>();
+        in.readTypedList(mOptions, RouteOptions.CREATOR);
+    }
+
+    /**
+     * Get the displayable name of this route.
+     *
+     * @return A short, user readable name for this route
+     */
+    public String getName() {
+        return mName;
+    }
+
+    /**
+     * Get the unique id for this route.
+     *
+     * @return A unique route id.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    /**
+     * Get the package name of this route's provider.
+     *
+     * @return The package name of this route's provider.
+     */
+    public String getProvider() {
+        return mProviderId;
+    }
+
+    /**
+     * Get the set of connections that may be used with this route.
+     *
+     * @return An array of connection requests that may be used to connect
+     */
+    public List<RouteOptions> getConnectionMethods() {
+        return mOptions;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        dest.writeString(mName);
+        dest.writeString(mProviderId);
+        dest.writeTypedList(mOptions);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder bob = new StringBuilder();
+        bob.append("RouteInfo: id=").append(mId).append(", name=").append(mName)
+                .append(", provider=").append(mProviderId).append(", options={");
+        for (int i = 0; i < mOptions.size(); i++) {
+            if (i != 0) {
+                bob.append(", ");
+            }
+            bob.append(mOptions.get(i).toString());
+        }
+        bob.append("}");
+        return bob.toString();
+    }
+
+    public static final Parcelable.Creator<RouteInfo> CREATOR
+            = new Parcelable.Creator<RouteInfo>() {
+        @Override
+        public RouteInfo createFromParcel(Parcel in) {
+            return new RouteInfo(in);
+        }
+
+        @Override
+        public RouteInfo[] newArray(int size) {
+            return new RouteInfo[size];
+        }
+    };
+
+    /**
+     * Helper for creating MediaRouteInfos. A route must have a name and an id.
+     * While options are not strictly required the route cannot be connected to
+     * without at least one set of options.
+     */
+    public static final class Builder {
+        private String mName;
+        private String mId;
+        private String mProviderPackage;
+        private ArrayList<RouteOptions> mOptions;
+
+        /**
+         * Copies an existing route info object. TODO Remove once we have
+         * helpers for creating route infos.
+         *
+         * @param from The existing info to copy.
+         */
+        public Builder(RouteInfo from) {
+            mOptions = new ArrayList<RouteOptions>(from.getConnectionMethods());
+            mName = from.mName;
+            mId = from.mId;
+            mProviderPackage = from.mProviderId;
+        }
+
+        public Builder() {
+            mOptions = new ArrayList<RouteOptions>();
+        }
+
+        /**
+         * Set the user visible name for this route.
+         *
+         * @param name The name of the route
+         * @return The builder for easy chaining.
+         */
+        public Builder setName(String name) {
+            mName = name;
+            return this;
+        }
+
+        /**
+         * Set the id of the route. This should be unique to the provider.
+         *
+         * @param id The unique id of the route.
+         * @return The builder for easy chaining.
+         */
+        public Builder setId(String id) {
+            mId = id;
+            return this;
+        }
+
+        /**
+         * @hide
+         */
+        public Builder setProviderId(String packageName) {
+            mProviderPackage = packageName;
+            return this;
+        }
+
+        /**
+         * Add a set of {@link RouteOptions} to the route. Multiple options
+         * may be added to the same route.
+         *
+         * @param options The options to add to this route.
+         * @return The builder for easy chaining.
+         */
+        public Builder addRouteOptions(RouteOptions options) {
+            mOptions.add(options);
+            return this;
+        }
+
+        /**
+         * Clear the set of {@link RouteOptions} on the route.
+         *
+         * @return The builder for easy chaining
+         */
+        public Builder clearRouteOptions() {
+            mOptions.clear();
+            return this;
+        }
+
+        /**
+         * Build a new MediaRouteInfo.
+         *
+         * @return A new MediaRouteInfo with the values that were set.
+         */
+        public RouteInfo build() {
+            if (TextUtils.isEmpty(mName)) {
+                throw new IllegalArgumentException("Must set a name before building");
+            }
+            if (TextUtils.isEmpty(mId)) {
+                throw new IllegalArgumentException("Must set an id before building");
+            }
+            return new RouteInfo(mId, mName, mProviderPackage, mOptions);
+        }
+
+        /**
+         * Get the current number of options that have been added to this
+         * builder.
+         *
+         * @return The number of options that have been added.
+         */
+        public int getOptionsSize() {
+            return mOptions.size();
+        }
+    }
+}
diff --git a/media/java/android/media/session/RouteInterface.java b/media/java/android/media/session/RouteInterface.java
index 2391f27..e9c9fd3 100644
--- a/media/java/android/media/session/RouteInterface.java
+++ b/media/java/android/media/session/RouteInterface.java
@@ -17,136 +17,161 @@
 
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.Parcelable;
 import android.os.ResultReceiver;
+import android.util.Log;
+
+import java.util.ArrayList;
 
 /**
- * Routes can support multiple interfaces for MediaSessions to interact with. To
- * add a standard interface you should implement that interface's RouteInterface
- * Stub and register it with the session. The set of supported commands is
- * dependent on the specific interface's implementation.
- * <p>
- * A MediaInterface can be registered by calling TODO. Once added an interface
- * will be used by Sessions to decide how they communicate with a session and
- * cannot be removed, so all interfaces that you plan to support should be added
- * when the route is created.
+ * A route can support multiple interfaces for a {@link Session} to
+ * interact with. To use a specific interface with a route a
+ * MediaSessionRouteInterface needs to be retrieved from the route. An
+ * implementation of the specific interface, like
+ * {@link RoutePlaybackControls}, should be used to simplify communication
+ * and reduce errors on that interface.
  *
- * @see RouteTransportControls
+ * @see RoutePlaybackControls for an example
  */
 public final class RouteInterface {
-    private static final String TAG = "MediaInterface";
+    private static final String TAG = "RouteInterface";
 
-    private static final String KEY_RESULT = "result";
+    /**
+     * Error indicating the route is currently not connected.
+     */
+    public static final int RESULT_NOT_CONNECTED = -5;
+    /**
+     * Error indicating the session is no longer using the route this command
+     * was sent to.
+     */
+    public static final int RESULT_ROUTE_IS_STALE = -4;
+    /**
+     * Error indicating that the interface does not support the command.
+     */
+    public static final int RESULT_COMMAND_NOT_SUPPORTED = -3;
+    /**
+     * Error indicating that the route does not support the interface.
+     */
+    public static final int RESULT_INTERFACE_NOT_SUPPORTED = -2;
+    /**
+     * Generic error. Extra information about the error may be included in the
+     * result bundle.
+     */
+    public static final int RESULT_ERROR = -1;
+    /**
+     * The command was successful. Extra information may be included in the
+     * result bundle.
+     */
+    public static final int RESULT_SUCCESS = 1;
 
-    private final MediaController mController;
+    private final Route mRoute;
     private final String mIface;
+    private final Session mSession;
+
+    private final Object mLock = new Object();
+    private final ArrayList<EventHandler> mListeners = new ArrayList<EventHandler>();
 
     /**
      * @hide
      */
-    RouteInterface(MediaController controller, String iface) {
-        mController = controller;
+    RouteInterface(Route route, String iface, Session session) {
+        mRoute = route;
         mIface = iface;
+        mSession = session;
+        mSession.addInterfaceListener(iface, mEventListener);
     }
 
-    public void sendCommand(String command, Bundle params, ResultReceiver cb) {
-        // TODO
+    /**
+     * Send a command using this interface.
+     *
+     * @param command The command to send.
+     * @param extras Any extras to include with the command.
+     * @param cb The callback to receive the result on.
+     * @return true if the command was sent, false otherwise.
+     */
+    public boolean sendCommand(String command, Bundle extras, ResultReceiver cb) {
+        RouteCommand cmd = new RouteCommand(mRoute.getRouteInfo().getId(), mIface,
+                command, extras);
+        return mSession.sendRouteCommand(cmd, cb);
     }
 
+    /**
+     * Add a listener to this interface. Events will be sent on the caller's
+     * thread.
+     *
+     * @param listener The listener to receive events on.
+     */
     public void addListener(EventListener listener) {
         addListener(listener, null);
     }
 
+    /**
+     * Add a listener for this interface. If a handler is specified events will
+     * be performed on the handler's thread, otherwise the caller's thread will
+     * be used.
+     *
+     * @param listener The listener to receive events on
+     * @param handler The handler whose thread to post calls on
+     */
     public void addListener(EventListener listener, Handler handler) {
-        // TODO See MediaController for add/remove pattern
+        if (listener == null) {
+            throw new IllegalArgumentException("listener may not be null");
+        }
+        if (handler == null) {
+            handler = new Handler();
+        }
+        synchronized (mLock) {
+            if (findIndexOfListenerLocked(listener) != -1) {
+                Log.d(TAG, "Listener is already added, ignoring");
+                return;
+            }
+            mListeners.add(new EventHandler(handler.getLooper(), listener));
+        }
     }
 
+    /**
+     * Remove a listener from this interface.
+     *
+     * @param listener The listener to stop receiving events on.
+     */
     public void removeListener(EventListener listener) {
-        // TODO
-    }
-
-    // TODO decide on list of supported types
-    private static Bundle writeResultToBundle(Object v) {
-        Bundle b = new Bundle();
-        if (v == null) {
-            // Don't send anything if null
-        } else if (v instanceof String) {
-            b.putString(KEY_RESULT, (String) v);
-        } else if (v instanceof Integer) {
-            b.putInt(KEY_RESULT, (Integer) v);
-        } else if (v instanceof Bundle) {
-            // Must be before Parcelable
-            b.putBundle(KEY_RESULT, (Bundle) v);
-        } else if (v instanceof Parcelable) {
-            b.putParcelable(KEY_RESULT, (Parcelable) v);
-        } else if (v instanceof Short) {
-            b.putShort(KEY_RESULT, (Short) v);
-        } else if (v instanceof Long) {
-            b.putLong(KEY_RESULT, (Long) v);
-        } else if (v instanceof Float) {
-            b.putFloat(KEY_RESULT, (Float) v);
-        } else if (v instanceof Double) {
-            b.putDouble(KEY_RESULT, (Double) v);
-        } else if (v instanceof Boolean) {
-            b.putBoolean(KEY_RESULT, (Boolean) v);
-        } else if (v instanceof CharSequence) {
-            // Must be after String
-            b.putCharSequence(KEY_RESULT, (CharSequence) v);
-        } else if (v instanceof boolean[]) {
-            b.putBooleanArray(KEY_RESULT, (boolean[]) v);
-        } else if (v instanceof byte[]) {
-            b.putByteArray(KEY_RESULT, (byte[]) v);
-        } else if (v instanceof String[]) {
-            b.putStringArray(KEY_RESULT, (String[]) v);
-        } else if (v instanceof CharSequence[]) {
-            // Must be after String[] and before Object[]
-            b.putCharSequenceArray(KEY_RESULT, (CharSequence[]) v);
-        } else if (v instanceof IBinder) {
-            b.putBinder(KEY_RESULT, (IBinder) v);
-        } else if (v instanceof Parcelable[]) {
-            b.putParcelableArray(KEY_RESULT, (Parcelable[]) v);
-        } else if (v instanceof int[]) {
-            b.putIntArray(KEY_RESULT, (int[]) v);
-        } else if (v instanceof long[]) {
-            b.putLongArray(KEY_RESULT, (long[]) v);
-        } else if (v instanceof Byte) {
-            b.putByte(KEY_RESULT, (Byte) v);
+        if (listener == null) {
+            throw new IllegalArgumentException("listener may not be null");
         }
-        return b;
-    }
-
-    public abstract static class Stub {
-
-        /**
-         * The name of an interface should be a fully qualified name to prevent
-         * namespace collisions. Example: "com.myproject.MyPlaybackInterface"
-         *
-         * @return The name of this interface
-         */
-        public abstract String getName();
-
-        /**
-         * This is called when a command is received that matches the interface
-         * you registered. Commands can come from any app with a MediaController
-         * reference to the session.
-         *
-         * @see MediaController
-         * @see MediaSession
-         * @param command The command or method to invoke.
-         * @param args Any args that were included with the command. May be
-         *            null.
-         * @param cb The callback provided to send a response on. May be null.
-         */
-        public abstract void onCommand(String command, Bundle args, ResultReceiver cb);
-
-        public final void sendEvent(MediaSession session, String event, Bundle extras) {
-            // TODO
+        synchronized (mLock) {
+            int index = findIndexOfListenerLocked(listener);
+            if (index != -1) {
+                mListeners.remove(index);
+            }
         }
     }
 
+    private int findIndexOfListenerLocked(EventListener listener) {
+        if (listener == null) {
+            throw new IllegalArgumentException("Callback cannot be null");
+        }
+        for (int i = mListeners.size() - 1; i >= 0; i--) {
+            EventHandler handler = mListeners.get(i);
+            if (listener == handler.mListener) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private EventListener mEventListener = new EventListener() {
+            @Override
+        public void onEvent(String event, Bundle args) {
+            synchronized (mLock) {
+                for (int i = mListeners.size() - 1; i >= 0; i--) {
+                    mListeners.get(i).postEvent(event, args);
+                }
+            }
+        }
+
+    };
+
     /**
      * An EventListener can be registered by an app with TODO to handle events
      * sent by the session on a specific interface.
@@ -166,9 +191,9 @@
 
     private static final class EventHandler extends Handler {
 
-        private final RouteInterface.EventListener mListener;
+        private final EventListener mListener;
 
-        public EventHandler(Looper looper, RouteInterface.EventListener cb) {
+        public EventHandler(Looper looper, EventListener cb) {
             super(looper, null, true);
             mListener = cb;
         }
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/RouteOptions.aidl
similarity index 95%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to media/java/android/media/session/RouteOptions.aidl
index 5812682..feaf517 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/session/RouteOptions.aidl
@@ -15,4 +15,4 @@
 
 package android.media.session;
 
-parcelable MediaSessionToken;
+parcelable RouteOptions;
diff --git a/media/java/android/media/session/RouteOptions.java b/media/java/android/media/session/RouteOptions.java
new file mode 100644
index 0000000..5105867
--- /dev/null
+++ b/media/java/android/media/session/RouteOptions.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.text.TextUtils;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Specifies options that an application might use when connecting to a route.
+ * This includes things like interfaces, connection parameters, and required
+ * features.
+ * <p>
+ * An application may create several different route options that describe
+ * alternative sets of capabilities that it can use and choose the most
+ * appropriate route options when it is ready to connect to the route. Each
+ * route options instance must specify a complete set of capabilities to request
+ * when the connection is established.
+ */
+public final class RouteOptions implements Parcelable {
+    private static final String TAG = "RouteOptions";
+
+    private final ArrayList<String> mIfaces;
+    private final Bundle mConnectionParams;
+
+    private RouteOptions(List<String> ifaces, Bundle params) {
+        mIfaces = new ArrayList<String>(ifaces);
+        mConnectionParams = params;
+    }
+
+    private RouteOptions(Parcel in) {
+        mIfaces = new ArrayList<String>();
+        in.readStringList(mIfaces);
+        mConnectionParams = in.readBundle();
+    }
+
+    /**
+     * Get the interfaces this connection wants to use.
+     *
+     * @return The interfaces for this connection
+     */
+    public List<String> getInterfaceNames() {
+        return mIfaces;
+    }
+
+    /**
+     * Get the parameters that will be used for connecting.
+     *
+     * @return The set of connection parameters this connections uses
+     */
+    public Bundle getConnectionParams() {
+        return mConnectionParams;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeStringList(mIfaces);
+        dest.writeBundle(mConnectionParams);
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder bob = new StringBuilder();
+        bob.append("Options: interfaces={");
+        for (int i = 0; i < mIfaces.size(); i++) {
+            if (i != 0) {
+                bob.append(", ");
+            }
+            bob.append(mIfaces.get(i));
+        }
+        bob.append("}");
+        bob.append(", parameters=");
+        bob.append(mConnectionParams == null ? "null" : mConnectionParams.toString());
+        return bob.toString();
+    }
+
+    public static final Parcelable.Creator<RouteOptions> CREATOR
+            = new Parcelable.Creator<RouteOptions>() {
+        @Override
+        public RouteOptions createFromParcel(Parcel in) {
+            return new RouteOptions(in);
+        }
+
+        @Override
+        public RouteOptions[] newArray(int size) {
+            return new RouteOptions[size];
+        }
+    };
+
+    /**
+     * Builder for creating {@link RouteOptions}.
+     */
+    public final static class Builder {
+        private ArrayList<String> mIfaces = new ArrayList<String>();
+        private Bundle mConnectionParams;
+
+        public Builder() {
+        }
+
+        /**
+         * Add a required interface to the options.
+         *
+         * @param interfaceName The name of the interface to add.
+         * @return The builder to allow chaining commands.
+         */
+        public Builder addInterface(String interfaceName) {
+            if (TextUtils.isEmpty(interfaceName)) {
+                throw new IllegalArgumentException("interfaceName cannot be empty");
+            }
+            if (!mIfaces.contains(interfaceName)) {
+                mIfaces.add(interfaceName);
+            } else {
+                Log.w(TAG, "Attempted to add interface that is already added");
+            }
+            return this;
+        }
+
+        /**
+         * Set the connection parameters to use with the options. TODO replace
+         * with more specific calls once we decide on the standard way to
+         * express parameters.
+         *
+         * @param parameters The parameters to use.
+         * @return The builder to allow chaining commands.
+         */
+        public Builder setParameters(Bundle parameters) {
+            mConnectionParams = parameters;
+            return this;
+        }
+
+        /**
+         * Generate a set of options.
+         *
+         * @return The options with the specified components.
+         */
+        public RouteOptions build() {
+            return new RouteOptions(mIfaces, mConnectionParams);
+        }
+    }
+}
diff --git a/media/java/android/media/session/RoutePlaybackControls.java b/media/java/android/media/session/RoutePlaybackControls.java
new file mode 100644
index 0000000..a3ffb58
--- /dev/null
+++ b/media/java/android/media/session/RoutePlaybackControls.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.ResultReceiver;
+
+/**
+ * A standard media control interface for Routes that support queueing and
+ * transport controls. Routes may support multiple interfaces for MediaSessions
+ * to interact with.
+ */
+public final class RoutePlaybackControls {
+    private static final String TAG = "RoutePlaybackControls";
+    public static final String NAME = "android.media.session.RoutePlaybackControls";
+
+    /** @hide */
+    public static final String KEY_VALUE1 = "value1";
+
+    /** @hide */
+    public static final String CMD_FAST_FORWARD = "fastForward";
+    /** @hide */
+    public static final String CMD_GET_CURRENT_POSITION = "getCurrentPosition";
+    /** @hide */
+    public static final String CMD_GET_CAPABILITIES = "getCapabilities";
+    /** @hide */
+    public static final String CMD_PLAY_NOW = "playNow";
+    /** @hide */
+    public static final String CMD_RESUME = "resume";
+    /** @hide */
+    public static final String CMD_PAUSE = "pause";
+
+    /** @hide */
+    public static final String EVENT_PLAYSTATE_CHANGE = "playstateChange";
+    /** @hide */
+    public static final String EVENT_METADATA_CHANGE = "metadataChange";
+
+    private final RouteInterface mIface;
+
+    private RoutePlaybackControls(RouteInterface iface) {
+        mIface = iface;
+    }
+
+    /**
+     * Get a new MediaRoutePlaybackControls instance for sending commands using
+     * this interface. If the provided route doesn't support this interface null
+     * will be returned.
+     *
+     * @param route The route to send commands to.
+     * @return A MediaRoutePlaybackControls instance or null if not supported.
+     */
+    public static RoutePlaybackControls from(Route route) {
+        RouteInterface iface = route.getInterface(NAME);
+        if (iface != null) {
+            return new RoutePlaybackControls(iface);
+        }
+        return null;
+    }
+
+    /**
+     * Send a resume command to the route.
+     */
+    public void resume() {
+        mIface.sendCommand(CMD_RESUME, null, null);
+    }
+
+    /**
+     * Send a pause command to the route.
+     */
+    public void pause() {
+        mIface.sendCommand(CMD_PAUSE, null, null);
+    }
+
+    /**
+     * Send a fast forward command.
+     */
+    public void fastForward() {
+        Bundle b = new Bundle();
+        mIface.sendCommand(CMD_FAST_FORWARD, b, null);
+    }
+
+    /**
+     * Retrieves the current playback position.
+     *
+     * @param cb The callback to receive the result on.
+     */
+    public void getCurrentPosition(ResultReceiver cb) {
+        mIface.sendCommand(CMD_GET_CURRENT_POSITION, null, cb);
+    }
+
+    public void getCapabilities(ResultReceiver cb) {
+        mIface.sendCommand(CMD_GET_CAPABILITIES, null, cb);
+    }
+
+    public void addListener(Listener listener) {
+        mIface.addListener(listener);
+    }
+
+    public void addListener(Listener listener, Handler handler) {
+        mIface.addListener(listener, handler);
+    }
+
+    public void removeListener(Listener listener) {
+        mIface.removeListener(listener);
+    }
+
+    public void playNow(String content) {
+        Bundle bundle = new Bundle();
+        bundle.putString(KEY_VALUE1, content);
+        mIface.sendCommand(CMD_PLAY_NOW, bundle, null);
+    }
+
+    /**
+     * Register this event listener using {@link #addListener} to receive
+     * RoutePlaybackControl events from a session.
+     */
+    public static abstract class Listener extends RouteInterface.EventListener {
+        @Override
+        public final void onEvent(String event, Bundle args) {
+            if (EVENT_PLAYSTATE_CHANGE.equals(event)) {
+                onPlaybackStateChange(args.getInt(KEY_VALUE1, 0));
+            } else if (EVENT_METADATA_CHANGE.equals(event)) {
+                onMetadataUpdate((MediaMetadata) args.getParcelable(KEY_VALUE1));
+            }
+        }
+
+        /**
+         * Override to handle updates to the playback state. Valid values are in
+         * {@link TransportPerformer}. TODO put playstate values somewhere more
+         * generic.
+         *
+         * @param state
+         */
+        public void onPlaybackStateChange(int state) {
+        }
+
+        /**
+         * Override to handle metadata changes for this session's media. The
+         * default supported fields are those in {@link MediaMetadata}.
+         *
+         * @param metadata
+         */
+        public void onMetadataUpdate(MediaMetadata metadata) {
+        }
+    }
+
+}
diff --git a/media/java/android/media/session/RouteTransportControls.java b/media/java/android/media/session/RouteTransportControls.java
deleted file mode 100644
index 665fd10..0000000
--- a/media/java/android/media/session/RouteTransportControls.java
+++ /dev/null
@@ -1,230 +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.
- */
-package android.media.session;
-
-import android.media.RemoteControlClient;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.ResultReceiver;
-import android.text.TextUtils;
-import android.util.Log;
-
-/**
- * A standard media control interface for Routes. Routes can support multiple
- * interfaces for MediaSessions to interact with. TODO rewrite for routes
- */
-public final class RouteTransportControls {
-    private static final String TAG = "RouteTransportControls";
-    public static final String NAME = "android.media.session.RouteTransportControls";
-
-    private static final String KEY_VALUE1 = "value1";
-
-    private static final String METHOD_FAST_FORWARD = "fastForward";
-    private static final String METHOD_GET_CURRENT_POSITION = "getCurrentPosition";
-    private static final String METHOD_GET_CAPABILITIES = "getCapabilities";
-
-    private static final String EVENT_PLAYSTATE_CHANGE = "playstateChange";
-    private static final String EVENT_METADATA_CHANGE = "metadataChange";
-
-    private final MediaController mController;
-    private final RouteInterface mIface;
-
-    private RouteTransportControls(RouteInterface iface, MediaController controller) {
-        mIface = iface;
-        mController = controller;
-    }
-
-    public static RouteTransportControls from(MediaController controller) {
-//        MediaInterface iface = controller.getInterface(NAME);
-//        if (iface != null) {
-//            return new RouteTransportControls(iface, controller);
-//        }
-        return null;
-    }
-
-    /**
-     * Send a play command to the route. TODO rename resume() and use messaging
-     * protocol, not KeyEvent
-     */
-    public void play() {
-        // TODO
-    }
-
-    /**
-     * Send a pause command to the session.
-     */
-    public void pause() {
-        // TODO
-    }
-
-    /**
-     * Set the rate at which to fastforward. Valid values are in the range [0,1]
-     * with actual rates depending on the implementation.
-     *
-     * @param rate
-     */
-    public void fastForward(float rate) {
-        if (rate < 0 || rate > 1) {
-            throw new IllegalArgumentException("Rate must be between 0 and 1 inclusive");
-        }
-        Bundle b = new Bundle();
-        b.putFloat(KEY_VALUE1, rate);
-        mIface.sendCommand(METHOD_FAST_FORWARD, b, null);
-    }
-
-    public void getCurrentPosition(ResultReceiver cb) {
-        mIface.sendCommand(METHOD_GET_CURRENT_POSITION, null, cb);
-    }
-
-    public void getCapabilities(ResultReceiver cb) {
-        mIface.sendCommand(METHOD_GET_CAPABILITIES, null, cb);
-    }
-
-    public void addListener(Listener listener) {
-        mIface.addListener(listener.mListener);
-    }
-
-    public void addListener(Listener listener, Handler handler) {
-        mIface.addListener(listener.mListener, handler);
-    }
-
-    public void removeListener(Listener listener) {
-        mIface.removeListener(listener.mListener);
-    }
-
-    public static abstract class Stub extends RouteInterface.Stub {
-        private final MediaSession mSession;
-
-        public Stub(MediaSession session) {
-            mSession = session;
-        }
-
-        @Override
-        public String getName() {
-            return NAME;
-        }
-
-        @Override
-        public void onCommand(String method, Bundle extras, ResultReceiver cb) {
-            if (TextUtils.isEmpty(method)) {
-                return;
-            }
-            Bundle result;
-            if (METHOD_FAST_FORWARD.equals(method)) {
-                fastForward(extras.getFloat(KEY_VALUE1, -1));
-            } else if (METHOD_GET_CURRENT_POSITION.equals(method)) {
-                if (cb != null) {
-                    result = new Bundle();
-                    result.putLong(KEY_VALUE1, getCurrentPosition());
-                    cb.send(0, result);
-                }
-            } else if (METHOD_GET_CAPABILITIES.equals(method)) {
-                if (cb != null) {
-                    result = new Bundle();
-                    result.putLong(KEY_VALUE1, getCapabilities());
-                    cb.send(0, result);
-                }
-            }
-        }
-
-        /**
-         * Override to handle fast forwarding. Valid values are [0,1] inclusive.
-         * The interpretation of the rate is up to the implementation. If no
-         * rate was included with the command a rate of -1 will be used by
-         * default.
-         *
-         * @param rate The rate at which to fast forward as a multiplier
-         */
-        public void fastForward(float rate) {
-            Log.w(TAG, "fastForward is not supported.");
-        }
-
-        /**
-         * Override to handle getting the current position of playback in
-         * millis.
-         *
-         * @return The current position in millis or -1
-         */
-        public long getCurrentPosition() {
-            Log.w(TAG, "getCurrentPosition is not supported");
-            return -1;
-        }
-
-        /**
-         * Override to handle getting the set of capabilities currently
-         * available.
-         *
-         * @return A bit mask of the supported capabilities
-         */
-        public long getCapabilities() {
-            Log.w(TAG, "getCapabilities is not supported");
-            return 0;
-        }
-
-        /**
-         * Publish the current playback state to the system and any controllers.
-         * Valid values are defined in {@link RemoteControlClient}. TODO move
-         * play states somewhere else.
-         *
-         * @param state
-         */
-        public final void updatePlaybackState(int state) {
-            Bundle extras = new Bundle();
-            extras.putInt(KEY_VALUE1, state);
-            sendEvent(mSession, EVENT_PLAYSTATE_CHANGE, extras);
-        }
-    }
-
-    /**
-     * Register this event listener using TODO to receive
-     * TransportControlInterface events from a session.
-     *
-     * @see RouteInterface.EventListener
-     */
-    public static abstract class Listener {
-
-        private RouteInterface.EventListener mListener = new RouteInterface.EventListener() {
-            @Override
-            public final void onEvent(String event, Bundle args) {
-                if (EVENT_PLAYSTATE_CHANGE.equals(event)) {
-                    onPlaybackStateChange(args.getInt(KEY_VALUE1));
-                } else if (EVENT_METADATA_CHANGE.equals(event)) {
-                    onMetadataUpdate(args);
-                }
-            }
-        };
-
-        /**
-         * Override to handle updates to the playback state. Valid values are in
-         * {@link TransportPerformer}. TODO put playstate values somewhere more
-         * generic.
-         *
-         * @param state
-         */
-        public void onPlaybackStateChange(int state) {
-        }
-
-        /**
-         * Override to handle metadata changes for this session's media. The
-         * default supported fields are those in {@link MediaMetadata}.
-         *
-         * @param metadata
-         */
-        public void onMetadataUpdate(Bundle metadata) {
-        }
-    }
-
-}
diff --git a/media/java/android/media/session/MediaSession.java b/media/java/android/media/session/Session.java
similarity index 66%
rename from media/java/android/media/session/MediaSession.java
rename to media/java/android/media/session/Session.java
index 23c3035..8ccd788 100644
--- a/media/java/android/media/session/MediaSession.java
+++ b/media/java/android/media/session/Session.java
@@ -18,9 +18,9 @@
 
 import android.content.Intent;
 import android.media.Rating;
-import android.media.session.IMediaController;
-import android.media.session.IMediaSession;
-import android.media.session.IMediaSessionCallback;
+import android.media.session.ISessionController;
+import android.media.session.ISession;
+import android.media.session.ISessionCallback;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
@@ -33,6 +33,7 @@
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.List;
 
 /**
  * Allows interaction with media controllers, media routes, volume keys, media
@@ -44,11 +45,11 @@
  * media to multiple routes or to provide finer grain controls of media.
  * <p>
  * A MediaSession is created by calling
- * {@link MediaSessionManager#createSession(String)}. Once a session is created
+ * {@link SessionManager#createSession(String)}. Once a session is created
  * apps that have the MEDIA_CONTENT_CONTROL permission can interact with the
- * session through {@link MediaSessionManager#getActiveSessions()}. The owner of
+ * session through {@link SessionManager#getActiveSessions()}. The owner of
  * the session may also use {@link #getSessionToken()} to allow apps without
- * this permission to create a {@link MediaController} to interact with this
+ * this permission to create a {@link SessionController} to interact with this
  * session.
  * <p>
  * To receive commands, media keys, and other events a Callback must be set with
@@ -59,12 +60,13 @@
  * <p>
  * MediaSession objects are thread safe
  */
-public final class MediaSession {
-    private static final String TAG = "MediaSession";
+public final class Session {
+    private static final String TAG = "Session";
 
     private static final int MSG_MEDIA_BUTTON = 1;
     private static final int MSG_COMMAND = 2;
     private static final int MSG_ROUTE_CHANGE = 3;
+    private static final int MSG_ROUTE_CONNECTED = 4;
 
     private static final String KEY_COMMAND = "command";
     private static final String KEY_EXTRAS = "extras";
@@ -72,32 +74,33 @@
 
     private final Object mLock = new Object();
 
-    private final MediaSessionToken mSessionToken;
-    private final IMediaSession mBinder;
+    private final SessionToken mSessionToken;
+    private final ISession mBinder;
     private final CallbackStub mCbStub;
 
     private final ArrayList<MessageHandler> mCallbacks = new ArrayList<MessageHandler>();
     // TODO route interfaces
-    private final ArrayMap<String, RouteInterface.Stub> mInterfaces
-            = new ArrayMap<String, RouteInterface.Stub>();
+    private final ArrayMap<String, RouteInterface.EventListener> mInterfaceListeners
+            = new ArrayMap<String, RouteInterface.EventListener>();
 
     private TransportPerformer mPerformer;
+    private Route mRoute;
 
     private boolean mPublished = false;;
 
     /**
      * @hide
      */
-    public MediaSession(IMediaSession binder, CallbackStub cbStub) {
+    public Session(ISession binder, CallbackStub cbStub) {
         mBinder = binder;
         mCbStub = cbStub;
-        IMediaController controllerBinder = null;
+        ISessionController controllerBinder = null;
         try {
-            controllerBinder = mBinder.getMediaController();
+            controllerBinder = mBinder.getController();
         } catch (RemoteException e) {
             throw new RuntimeException("Dead object in MediaSessionController constructor: ", e);
         }
-        mSessionToken = new MediaSessionToken(controllerBinder);
+        mSessionToken = new SessionToken(controllerBinder);
     }
 
     /**
@@ -109,6 +112,13 @@
         addCallback(callback, null);
     }
 
+    /**
+     * Add a callback to receive updates for the MediaSession. This includes
+     * events like route updates, media buttons, and focus changes.
+     *
+     * @param callback The callback to receive updates on.
+     * @param handler The handler that events should be posted on.
+     */
     public void addCallback(Callback callback, Handler handler) {
         if (callback == null) {
             throw new IllegalArgumentException("Callback cannot be null");
@@ -126,6 +136,11 @@
         }
     }
 
+    /**
+     * Remove a callback. It will no longer receive updates.
+     *
+     * @param callback The callback to remove.
+     */
     public void removeCallback(Callback callback) {
         synchronized (mLock) {
             removeCallbackLocked(callback);
@@ -186,30 +201,6 @@
     }
 
     /**
-     * Add an interface that can be used by MediaSessions. TODO make this a
-     * route provider api
-     *
-     * @see RouteInterface
-     * @param iface The interface to add
-     * @hide
-     */
-    public void addInterface(RouteInterface.Stub iface) {
-        if (iface == null) {
-            throw new IllegalArgumentException("Stub cannot be null");
-        }
-        String name = iface.getName();
-        if (TextUtils.isEmpty(name)) {
-            throw new IllegalArgumentException("Stub must return a valid name");
-        }
-        if (mInterfaces.containsKey(iface)) {
-            throw new IllegalArgumentException("Interface is already added");
-        }
-        synchronized (mLock) {
-            mInterfaces.put(iface.getName(), iface);
-        }
-    }
-
-    /**
      * Send a proprietary event to all MediaControllers listening to this
      * Session. It's up to the Controller/Session owner to determine the meaning
      * of any events.
@@ -243,16 +234,92 @@
 
     /**
      * Retrieve a token object that can be used by apps to create a
-     * {@link MediaController} for interacting with this session. The owner of
+     * {@link SessionController} for interacting with this session. The owner of
      * the session is responsible for deciding how to distribute these tokens.
      *
      * @return A token that can be used to create a MediaController for this
      *         session
      */
-    public MediaSessionToken getSessionToken() {
+    public SessionToken getSessionToken() {
         return mSessionToken;
     }
 
+    /**
+     * Connect to the current route using the specified request.
+     * <p>
+     * Connection updates will be sent to the callback's
+     * {@link Callback#onRouteConnected(Route)} and
+     * {@link Callback#onRouteDisconnected(Route, int)} methods. If the
+     * connection fails {@link Callback#onRouteDisconnected(Route, int)}
+     * will be called.
+     * <p>
+     * If you already have a connection to this route it will be disconnected
+     * before the new connection is established. TODO add an easy way to compare
+     * MediaRouteOptions.
+     *
+     * @param route The route the app is trying to connect to.
+     * @param request The connection request to use.
+     */
+    public void connect(RouteInfo route, RouteOptions request) {
+        if (route == null) {
+            throw new IllegalArgumentException("Must specify the route");
+        }
+        if (request == null) {
+            throw new IllegalArgumentException("Must specify the connection request");
+        }
+        try {
+            mBinder.connectToRoute(route, request);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error starting connection to route", e);
+        }
+    }
+
+    /**
+     * Disconnect from the current route. After calling you will be switched
+     * back to the default route.
+     *
+     * @param route The route to disconnect from.
+     */
+    public void disconnect(RouteInfo route) {
+        // TODO
+    }
+
+    /**
+     * Set the list of route options your app is interested in connecting to. It
+     * will be used for picking valid routes.
+     *
+     * @param options The set of route options your app may use to connect.
+     */
+    public void setRouteOptions(List<RouteOptions> options) {
+        try {
+            mBinder.setRouteOptions(options);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error setting route options.", e);
+        }
+    }
+
+    /**
+     * @hide
+     * TODO allow multiple listeners for the same interface, allow removal
+     */
+    public void addInterfaceListener(String iface,
+            RouteInterface.EventListener listener) {
+        mInterfaceListeners.put(iface, listener);
+    }
+
+    /**
+     * @hide
+     */
+    public boolean sendRouteCommand(RouteCommand command, ResultReceiver cb) {
+        try {
+            mBinder.sendRouteCommand(command, cb);
+        } catch (RemoteException e) {
+            Log.wtf(TAG, "Error sending command to route.", e);
+            return false;
+        }
+        return true;
+    }
+
     private MessageHandler getHandlerForCallbackLocked(Callback cb) {
         if (cb == null) {
             throw new IllegalArgumentException("Callback cannot be null");
@@ -297,10 +364,19 @@
         }
     }
 
-    private void postRequestRouteChange(Bundle mediaRouteDescriptor) {
+    private void postRequestRouteChange(RouteInfo route) {
         synchronized (mLock) {
             for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                mCallbacks.get(i).post(MSG_ROUTE_CHANGE, mediaRouteDescriptor);
+                mCallbacks.get(i).post(MSG_ROUTE_CHANGE, route);
+            }
+        }
+    }
+
+    private void postRouteConnected(RouteInfo route, RouteOptions options) {
+        synchronized (mLock) {
+            mRoute = new Route(route, options, this);
+            for (int i = mCallbacks.size() - 1; i >= 0; i--) {
+                mCallbacks.get(i).post(MSG_ROUTE_CONNECTED, mRoute);
             }
         }
     }
@@ -346,26 +422,49 @@
          * The app is responsible for connecting to the new route and migrating
          * ongoing playback if necessary.
          *
-         * @param descriptor
+         * @param route
          */
-        public void onRequestRouteChange(Bundle descriptor) {
+        public void onRequestRouteChange(RouteInfo route) {
+        }
+
+        /**
+         * Called when a route has successfully connected. Calls to the route
+         * are now valid.
+         *
+         * @param route The route that was connected
+         */
+        public void onRouteConnected(Route route) {
+        }
+
+        /**
+         * Called when a route was disconnected. Further calls to the route will
+         * fail. If available a reason for being disconnected will be provided.
+         * <p>
+         * Valid reasons are:
+         * <ul>
+         * </ul>
+         *
+         * @param route The route that disconnected
+         * @param reason The reason for the disconnect
+         */
+        public void onRouteDisconnected(Route route, int reason) {
         }
     }
 
     /**
      * @hide
      */
-    public static class CallbackStub extends IMediaSessionCallback.Stub {
-        private WeakReference<MediaSession> mMediaSession;
+    public static class CallbackStub extends ISessionCallback.Stub {
+        private WeakReference<Session> mMediaSession;
 
-        public void setMediaSession(MediaSession session) {
-            mMediaSession = new WeakReference<MediaSession>(session);
+        public void setMediaSession(Session session) {
+            mMediaSession = new WeakReference<Session>(session);
         }
 
         @Override
         public void onCommand(String command, Bundle extras, ResultReceiver cb)
                 throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 session.postCommand(command, extras, cb);
             }
@@ -373,23 +472,31 @@
 
         @Override
         public void onMediaButton(Intent mediaButtonIntent) throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 session.postMediaButton(mediaButtonIntent);
             }
         }
 
         @Override
-        public void onRequestRouteChange(Bundle mediaRouteDescriptor) throws RemoteException {
-            MediaSession session = mMediaSession.get();
+        public void onRequestRouteChange(RouteInfo route) throws RemoteException {
+            Session session = mMediaSession.get();
             if (session != null) {
-                session.postRequestRouteChange(mediaRouteDescriptor);
+                session.postRequestRouteChange(route);
+            }
+        }
+
+        @Override
+        public void onRouteConnected(RouteInfo route, RouteOptions options) {
+            Session session = mMediaSession.get();
+            if (session != null) {
+                session.postRouteConnected(route, options);
             }
         }
 
         @Override
         public void onPlay() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -400,7 +507,7 @@
 
         @Override
         public void onPause() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -411,7 +518,7 @@
 
         @Override
         public void onStop() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -422,7 +529,7 @@
 
         @Override
         public void onNext() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -433,7 +540,7 @@
 
         @Override
         public void onPrevious() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -444,7 +551,7 @@
 
         @Override
         public void onFastForward() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -455,7 +562,7 @@
 
         @Override
         public void onRewind() throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -466,7 +573,7 @@
 
         @Override
         public void onSeekTo(long pos) throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -477,7 +584,7 @@
 
         @Override
         public void onRate(Rating rating) throws RemoteException {
-            MediaSession session = mMediaSession.get();
+            Session session = mMediaSession.get();
             if (session != null) {
                 TransportPerformer tp = session.getTransportPerformer();
                 if (tp != null) {
@@ -486,12 +593,32 @@
             }
         }
 
+        @Override
+        public void onRouteEvent(RouteEvent event) throws RemoteException {
+            Session session = mMediaSession.get();
+            if (session != null) {
+                RouteInterface.EventListener iface
+                        = session.mInterfaceListeners.get(event.getIface());
+                Log.d(TAG, "Received route event on iface " + event.getIface() + ". Listener is "
+                        + iface);
+                if (iface != null) {
+                    iface.onEvent(event.getEvent(), event.getExtras());
+                }
+            }
+        }
+
+        @Override
+        public void onRouteStateChange(int state) throws RemoteException {
+            // TODO
+
+        }
+
     }
 
     private class MessageHandler extends Handler {
-        private MediaSession.Callback mCallback;
+        private Session.Callback mCallback;
 
-        public MessageHandler(Looper looper, MediaSession.Callback callback) {
+        public MessageHandler(Looper looper, Session.Callback callback) {
             super(looper, null, true);
             mCallback = callback;
         }
@@ -511,11 +638,13 @@
                         mCallback.onCommand(cmd.command, cmd.extras, cmd.stub);
                         break;
                     case MSG_ROUTE_CHANGE:
-                        mCallback.onRequestRouteChange((Bundle) msg.obj);
+                        mCallback.onRequestRouteChange((RouteInfo) msg.obj);
+                        break;
+                    case MSG_ROUTE_CONNECTED:
+                        mCallback.onRouteConnected((Route) msg.obj);
                         break;
                 }
             }
-            msg.recycle();
         }
 
         public void post(int what, Object obj) {
diff --git a/media/java/android/media/session/MediaController.java b/media/java/android/media/session/SessionController.java
similarity index 83%
rename from media/java/android/media/session/MediaController.java
rename to media/java/android/media/session/SessionController.java
index afd8b11..dc4f7d9 100644
--- a/media/java/android/media/session/MediaController.java
+++ b/media/java/android/media/session/SessionController.java
@@ -34,21 +34,21 @@
  * other commands can be sent to the session. A callback may be registered to
  * receive updates from the session, such as metadata and play state changes.
  * <p>
- * A MediaController can be created through {@link MediaSessionManager} if you
+ * A MediaController can be created through {@link SessionManager} if you
  * hold the "android.permission.MEDIA_CONTENT_CONTROL" permission or directly if
- * you have a {@link MediaSessionToken} from the session owner.
+ * you have a {@link SessionToken} from the session owner.
  * <p>
  * MediaController objects are thread-safe.
  */
-public final class MediaController {
-    private static final String TAG = "MediaController";
+public final class SessionController {
+    private static final String TAG = "SessionController";
 
     private static final int MSG_EVENT = 1;
     private static final int MESSAGE_PLAYBACK_STATE = 2;
     private static final int MESSAGE_METADATA = 3;
     private static final int MSG_ROUTE = 4;
 
-    private final IMediaController mSessionBinder;
+    private final ISessionController mSessionBinder;
 
     private final CallbackStub mCbStub = new CallbackStub(this);
     private final ArrayList<MessageHandler> mCallbacks = new ArrayList<MessageHandler>();
@@ -58,15 +58,15 @@
 
     private TransportController mTransportController;
 
-    private MediaController(IMediaController sessionBinder) {
+    private SessionController(ISessionController sessionBinder) {
         mSessionBinder = sessionBinder;
     }
 
     /**
      * @hide
      */
-    public static MediaController fromBinder(IMediaController sessionBinder) {
-        MediaController controller = new MediaController(sessionBinder);
+    public static SessionController fromBinder(ISessionController sessionBinder) {
+        SessionController controller = new SessionController(sessionBinder);
         try {
             controller.mSessionBinder.registerCallbackListener(controller.mCbStub);
             if (controller.mSessionBinder.isTransportControlEnabled()) {
@@ -87,7 +87,7 @@
      * @param token The session token to use
      * @return A controller for the session or null
      */
-    public static MediaController fromToken(MediaSessionToken token) {
+    public static SessionController fromToken(SessionToken token) {
         return fromBinder(token.getBinder());
     }
 
@@ -181,10 +181,22 @@
         }
     }
 
+    /**
+     * Request that the route picker be shown for this session. This should
+     * generally be called in response to a user action.
+     */
+    public void showRoutePicker() {
+        try {
+            mSessionBinder.showRoutePicker();
+        } catch (RemoteException e) {
+            Log.d(TAG, "Dead object in showRoutePicker", e);
+        }
+    }
+
     /*
      * @hide
      */
-    IMediaController getSessionBinder() {
+    ISessionController getSessionBinder() {
         return mSessionBinder;
     }
 
@@ -247,10 +259,10 @@
         }
     }
 
-    private void postRouteChanged(Bundle routeDescriptor) {
+    private void postRouteChanged(RouteInfo route) {
         synchronized (mLock) {
             for (int i = mCallbacks.size() - 1; i >= 0; i--) {
-                mCallbacks.get(i).post(MSG_ROUTE, null, routeDescriptor);
+                mCallbacks.get(i).post(MSG_ROUTE, route, null);
             }
         }
     }
@@ -275,36 +287,36 @@
          *
          * @param route
          */
-        public void onRouteChanged(Bundle route) {
+        public void onRouteChanged(RouteInfo route) {
         }
     }
 
-    private final static class CallbackStub extends IMediaControllerCallback.Stub {
-        private final WeakReference<MediaController> mController;
+    private final static class CallbackStub extends ISessionControllerCallback.Stub {
+        private final WeakReference<SessionController> mController;
 
-        public CallbackStub(MediaController controller) {
-            mController = new WeakReference<MediaController>(controller);
+        public CallbackStub(SessionController controller) {
+            mController = new WeakReference<SessionController>(controller);
         }
 
         @Override
         public void onEvent(String event, Bundle extras) {
-            MediaController controller = mController.get();
+            SessionController controller = mController.get();
             if (controller != null) {
                 controller.postEvent(event, extras);
             }
         }
 
         @Override
-        public void onRouteChanged(Bundle mediaRouteDescriptor) {
-            MediaController controller = mController.get();
+        public void onRouteChanged(RouteInfo route) {
+            SessionController controller = mController.get();
             if (controller != null) {
-                controller.postRouteChanged(mediaRouteDescriptor);
+                controller.postRouteChanged(route);
             }
         }
 
         @Override
         public void onPlaybackStateChanged(PlaybackState state) {
-            MediaController controller = mController.get();
+            SessionController controller = mController.get();
             if (controller != null) {
                 TransportController tc = controller.getTransportController();
                 if (tc != null) {
@@ -315,7 +327,7 @@
 
         @Override
         public void onMetadataChanged(MediaMetadata metadata) {
-            MediaController controller = mController.get();
+            SessionController controller = mController.get();
             if (controller != null) {
                 TransportController tc = controller.getTransportController();
                 if (tc != null) {
@@ -327,9 +339,9 @@
     }
 
     private final static class MessageHandler extends Handler {
-        private final MediaController.Callback mCallback;
+        private final SessionController.Callback mCallback;
 
-        public MessageHandler(Looper looper, MediaController.Callback cb) {
+        public MessageHandler(Looper looper, SessionController.Callback cb) {
             super(looper, null, true);
             mCallback = cb;
         }
@@ -341,7 +353,7 @@
                     mCallback.onEvent((String) msg.obj, msg.getData());
                     break;
                 case MSG_ROUTE:
-                    mCallback.onRouteChanged(msg.getData());
+                    mCallback.onRouteChanged((RouteInfo) msg.obj);
             }
         }
 
diff --git a/media/java/android/media/session/SessionInfo.java b/media/java/android/media/session/SessionInfo.java
new file mode 100644
index 0000000..2b65528
--- /dev/null
+++ b/media/java/android/media/session/SessionInfo.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.media.session;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Information about a media session, including the owner's package name.
+ */
+public final class SessionInfo implements Parcelable {
+    private final String mId;
+    private final String mPackageName;
+
+    /**
+     * @hide
+     */
+    public SessionInfo(String id, String packageName) {
+        mId = id;
+        mPackageName = packageName;
+    }
+
+    private SessionInfo(Parcel in) {
+        mId = in.readString();
+        mPackageName = in.readString();
+    }
+
+    /**
+     * Get the package name of the owner of this session.
+     *
+     * @return The owner's package name
+     */
+    public String getPackageName() {
+        return mPackageName;
+    }
+
+    /**
+     * Get the unique id for this session.
+     *
+     * @return The id for the session.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    @Override
+    public String toString() {
+        return "SessionInfo {id=" + mId + ", pkg=" + mPackageName + "}";
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(mId);
+        dest.writeString(mPackageName);
+    }
+
+    public static final Parcelable.Creator<SessionInfo> CREATOR
+            = new Parcelable.Creator<SessionInfo>() {
+        @Override
+        public SessionInfo createFromParcel(Parcel in) {
+            return new SessionInfo(in);
+        }
+
+        @Override
+        public SessionInfo[] newArray(int size) {
+            return new SessionInfo[size];
+        }
+    };
+}
diff --git a/media/java/android/media/session/MediaSessionManager.java b/media/java/android/media/session/SessionManager.java
similarity index 75%
rename from media/java/android/media/session/MediaSessionManager.java
rename to media/java/android/media/session/SessionManager.java
index e3f2d9c..15bf0e3 100644
--- a/media/java/android/media/session/MediaSessionManager.java
+++ b/media/java/android/media/session/SessionManager.java
@@ -17,7 +17,7 @@
 package android.media.session;
 
 import android.content.Context;
-import android.media.session.IMediaSessionManager;
+import android.media.session.ISessionManager;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -35,37 +35,37 @@
  * get an instance of this class.
  * <p>
  *
- * @see MediaSession
- * @see MediaController
+ * @see Session
+ * @see SessionController
  */
-public final class MediaSessionManager {
-    private static final String TAG = "MediaSessionManager";
+public final class SessionManager {
+    private static final String TAG = "SessionManager";
 
-    private final IMediaSessionManager mService;
+    private final ISessionManager mService;
 
     private Context mContext;
 
     /**
      * @hide
      */
-    public MediaSessionManager(Context context) {
+    public SessionManager(Context context) {
         // Consider rewriting like DisplayManagerGlobal
         // Decide if we need context
         mContext = context;
         IBinder b = ServiceManager.getService(Context.MEDIA_SESSION_SERVICE);
-        mService = IMediaSessionManager.Stub.asInterface(b);
+        mService = ISessionManager.Stub.asInterface(b);
     }
 
     /**
      * Creates a new session.
      *
      * @param tag A short name for debugging purposes
-     * @return a {@link MediaSession} for the new session
+     * @return a {@link Session} for the new session
      */
-    public MediaSession createSession(String tag) {
+    public Session createSession(String tag) {
         try {
-            MediaSession.CallbackStub cbStub = new MediaSession.CallbackStub();
-            MediaSession session = new MediaSession(mService
+            Session.CallbackStub cbStub = new Session.CallbackStub();
+            Session session = new Session(mService
                     .createSession(mContext.getPackageName(), cbStub, tag), cbStub);
             cbStub.setMediaSession(session);
 
@@ -83,8 +83,8 @@
      *
      * @return a list of controllers for ongoing sessions
      */
-    public List<MediaController> getActiveSessions() {
+    public List<SessionController> getActiveSessions() {
         // TODO
-        return new ArrayList<MediaController>();
+        return new ArrayList<SessionController>();
     }
 }
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/media/java/android/media/session/SessionToken.aidl
similarity index 95%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to media/java/android/media/session/SessionToken.aidl
index 5812682..db35f85 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/media/java/android/media/session/SessionToken.aidl
@@ -15,4 +15,4 @@
 
 package android.media.session;
 
-parcelable MediaSessionToken;
+parcelable SessionToken;
diff --git a/media/java/android/media/session/MediaSessionToken.java b/media/java/android/media/session/SessionToken.java
similarity index 62%
rename from media/java/android/media/session/MediaSessionToken.java
rename to media/java/android/media/session/SessionToken.java
index dbb4964..59486f6 100644
--- a/media/java/android/media/session/MediaSessionToken.java
+++ b/media/java/android/media/session/SessionToken.java
@@ -16,28 +16,28 @@
 
 package android.media.session;
 
-import android.media.session.IMediaController;
+import android.media.session.ISessionController;
 import android.os.Parcel;
 import android.os.Parcelable;
 
-public class MediaSessionToken implements Parcelable {
-    private IMediaController mBinder;
+public class SessionToken implements Parcelable {
+    private ISessionController mBinder;
 
     /**
      * @hide
      */
-    MediaSessionToken(IMediaController binder) {
+    SessionToken(ISessionController binder) {
         mBinder = binder;
     }
 
-    private MediaSessionToken(Parcel in) {
-        mBinder = IMediaController.Stub.asInterface(in.readStrongBinder());
+    private SessionToken(Parcel in) {
+        mBinder = ISessionController.Stub.asInterface(in.readStrongBinder());
     }
 
     /**
      * @hide
      */
-    IMediaController getBinder() {
+    ISessionController getBinder() {
         return mBinder;
     }
 
@@ -51,16 +51,16 @@
         dest.writeStrongBinder(mBinder.asBinder());
     }
 
-    public static final Parcelable.Creator<MediaSessionToken> CREATOR
-            = new Parcelable.Creator<MediaSessionToken>() {
+    public static final Parcelable.Creator<SessionToken> CREATOR
+            = new Parcelable.Creator<SessionToken>() {
         @Override
-        public MediaSessionToken createFromParcel(Parcel in) {
-            return new MediaSessionToken(in);
+        public SessionToken createFromParcel(Parcel in) {
+            return new SessionToken(in);
         }
 
         @Override
-        public MediaSessionToken[] newArray(int size) {
-            return new MediaSessionToken[size];
+        public SessionToken[] newArray(int size) {
+            return new SessionToken[size];
         }
     };
 }
diff --git a/media/java/android/media/session/TransportController.java b/media/java/android/media/session/TransportController.java
index 15b11f3..9574df6 100644
--- a/media/java/android/media/session/TransportController.java
+++ b/media/java/android/media/session/TransportController.java
@@ -34,12 +34,12 @@
 
     private final Object mLock = new Object();
     private final ArrayList<MessageHandler> mListeners = new ArrayList<MessageHandler>();
-    private final IMediaController mBinder;
+    private final ISessionController mBinder;
 
     /**
      * @hide
      */
-    public TransportController(IMediaController binder) {
+    public TransportController(ISessionController binder) {
         mBinder = binder;
     }
 
diff --git a/media/java/android/media/session/TransportPerformer.java b/media/java/android/media/session/TransportPerformer.java
index b96db20..187f48d 100644
--- a/media/java/android/media/session/TransportPerformer.java
+++ b/media/java/android/media/session/TransportPerformer.java
@@ -34,12 +34,12 @@
     private final Object mLock = new Object();
     private final ArrayList<MessageHandler> mListeners = new ArrayList<MessageHandler>();
 
-    private IMediaSession mBinder;
+    private ISession mBinder;
 
     /**
      * @hide
      */
-    public TransportPerformer(IMediaSession binder) {
+    public TransportPerformer(ISession binder) {
         mBinder = binder;
     }
 
@@ -280,18 +280,11 @@
         /**
          * Report that audio focus has changed on the app. This only happens if
          * you have indicated you have started playing with
-         * {@link #setPlaybackState}. TODO figure out route focus apis/handling.
+         * {@link #setPlaybackState}.
          *
-         * @param focusChange The type of focus change, TBD. The default
-         *            implementation will deliver a call to {@link #onPause}
-         *            when focus is lost.
+         * @param focusChange The type of focus change, TBD.
          */
         public void onRouteFocusChange(int focusChange) {
-            switch (focusChange) {
-                case AudioManager.AUDIOFOCUS_LOSS:
-                    onPause();
-                    break;
-            }
         }
     }
 
diff --git a/media/java/android/media/videoeditor/AudioTrack.java b/media/java/android/media/videoeditor/AudioTrack.java
deleted file mode 100644
index c5cc2ca..0000000
--- a/media/java/android/media/videoeditor/AudioTrack.java
+++ /dev/null
@@ -1,658 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-
-/**
- * This class allows to handle an audio track. This audio file is mixed with the
- * audio samples of the media items.
- * {@hide}
- */
-public class AudioTrack {
-
-    /**
-     *  Instance variables
-     *  Private object for calling native methods via MediaArtistNativeHelper
-     */
-    private final MediaArtistNativeHelper mMANativeHelper;
-    private final String mUniqueId;
-    private final String mFilename;
-    private long mStartTimeMs;
-    private long mTimelineDurationMs;
-    private int mVolumePercent;
-    private long mBeginBoundaryTimeMs;
-    private long mEndBoundaryTimeMs;
-    private boolean mLoop;
-    private boolean mMuted;
-    private final long mDurationMs;
-    private final int mAudioChannels;
-    private final int mAudioType;
-    private final int mAudioBitrate;
-    private final int mAudioSamplingFrequency;
-    /**
-     *  Ducking variables
-     */
-    private int mDuckingThreshold;
-    private int mDuckedTrackVolume;
-    private boolean mIsDuckingEnabled;
-
-    /**
-     *  The audio waveform filename
-     */
-    private String mAudioWaveformFilename;
-
-    /**
-     *  The audio waveform data
-     */
-    private SoftReference<WaveformData> mWaveformData;
-
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private AudioTrack() throws IOException {
-        this(null, null, null);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param audioTrackId The audio track id
-     * @param filename The absolute file name
-     *
-     * @throws IOException if file is not found
-     * @throws IllegalArgumentException if file format is not supported or if
-     *         the codec is not supported or if editor is not of type
-     *         VideoEditorImpl.
-     */
-    public AudioTrack(VideoEditor editor, String audioTrackId, String filename) throws IOException {
-        this(editor, audioTrackId, filename, 0, 0, MediaItem.END_OF_FILE, false, 100, false, false,
-                0, 0, null);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param audioTrackId The audio track id
-     * @param filename The audio filename. In case file contains Audio and Video,
-     *         only the Audio stream will be used as Audio Track.
-     * @param startTimeMs the start time in milliseconds (relative to the
-     *         timeline)
-     * @param beginMs start time in the audio track in milliseconds (relative to
-     *         the beginning of the audio track)
-     * @param endMs end time in the audio track in milliseconds (relative to the
-     *         beginning of the audio track)
-     * @param loop true to loop the audio track
-     * @param volume The volume in percentage
-     * @param muted true if the audio track is muted
-     * @param threshold Ducking will be activated when the relative energy in
-     *         the media items audio signal goes above this value. The valid
-     *         range of values is 0 to 90.
-     * @param duckedTrackVolume The relative volume of the audio track when
-     *         ducking is active. The valid range of values is 0 to 100.
-     * @param audioWaveformFilename The name of the waveform file
-     *
-     * @throws IOException if file is not found
-     * @throws IllegalArgumentException if file format is not supported or if
-     *             the codec is not supported or if editor is not of type
-     *             VideoEditorImpl.
-     */
-    AudioTrack(VideoEditor editor, String audioTrackId, String filename,
-               long startTimeMs,long beginMs, long endMs, boolean loop,
-               int volume, boolean muted,boolean duckingEnabled,
-               int duckThreshold, int duckedTrackVolume,
-            String audioWaveformFilename) throws IOException {
-        Properties properties = null;
-
-        File file = new File(filename);
-        if (!file.exists()) {
-            throw new IOException(filename + " not found ! ");
-        }
-
-        /*Compare file_size with 2GB*/
-        if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) {
-            throw new IllegalArgumentException("File size is more than 2GB");
-        }
-
-        if (editor instanceof VideoEditorImpl) {
-            mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
-        } else {
-            throw new IllegalArgumentException("editor is not of type VideoEditorImpl");
-        }
-        try {
-          properties = mMANativeHelper.getMediaProperties(filename);
-        } catch (Exception e) {
-            throw new IllegalArgumentException(e.getMessage() + " : " + filename);
-        }
-        int fileType = mMANativeHelper.getFileType(properties.fileType);
-        switch (fileType) {
-            case MediaProperties.FILE_3GP:
-            case MediaProperties.FILE_MP4:
-            case MediaProperties.FILE_MP3:
-            case MediaProperties.FILE_AMR:
-                break;
-
-            default: {
-                throw new IllegalArgumentException("Unsupported input file type: " + fileType);
-            }
-        }
-        switch (mMANativeHelper.getAudioCodecType(properties.audioFormat)) {
-            case MediaProperties.ACODEC_AMRNB:
-            case MediaProperties.ACODEC_AMRWB:
-            case MediaProperties.ACODEC_AAC_LC:
-            case MediaProperties.ACODEC_MP3:
-                break;
-            default:
-                throw new IllegalArgumentException("Unsupported Audio Codec Format in Input File");
-        }
-
-        if (endMs == MediaItem.END_OF_FILE) {
-            endMs = properties.audioDuration;
-        }
-
-        mUniqueId = audioTrackId;
-        mFilename = filename;
-        mStartTimeMs = startTimeMs;
-        mDurationMs = properties.audioDuration;
-        mAudioChannels = properties.audioChannels;
-        mAudioBitrate = properties.audioBitrate;
-        mAudioSamplingFrequency = properties.audioSamplingFrequency;
-        mAudioType = properties.audioFormat;
-        mTimelineDurationMs = endMs - beginMs;
-        mVolumePercent = volume;
-
-        mBeginBoundaryTimeMs = beginMs;
-        mEndBoundaryTimeMs = endMs;
-
-        mLoop = loop;
-        mMuted = muted;
-        mIsDuckingEnabled = duckingEnabled;
-        mDuckingThreshold = duckThreshold;
-        mDuckedTrackVolume = duckedTrackVolume;
-
-        mAudioWaveformFilename = audioWaveformFilename;
-        if (audioWaveformFilename != null) {
-            mWaveformData =
-                new SoftReference<WaveformData>(new WaveformData(audioWaveformFilename));
-        } else {
-            mWaveformData = null;
-        }
-    }
-
-    /**
-     * Get the id of the audio track
-     *
-     * @return The id of the audio track
-     */
-    public String getId() {
-        return mUniqueId;
-    }
-
-    /**
-     * Get the filename for this audio track source.
-     *
-     * @return The filename as an absolute file name
-     */
-    public String getFilename() {
-        return mFilename;
-    }
-
-    /**
-     * Get the number of audio channels in the source of this audio track
-     *
-     * @return The number of audio channels in the source of this audio track
-     */
-    public int getAudioChannels() {
-        return mAudioChannels;
-    }
-
-    /**
-     * Get the audio codec of the source of this audio track
-     *
-     * @return The audio codec of the source of this audio track
-     * {@link android.media.videoeditor.MediaProperties}
-     */
-    public int getAudioType() {
-        return mAudioType;
-    }
-
-    /**
-     * Get the audio sample frequency of the audio track
-     *
-     * @return The audio sample frequency of the audio track
-     */
-    public int getAudioSamplingFrequency() {
-        return mAudioSamplingFrequency;
-    }
-
-    /**
-     * Get the audio bitrate of the audio track
-     *
-     * @return The audio bitrate of the audio track
-     */
-    public int getAudioBitrate() {
-        return mAudioBitrate;
-    }
-
-    /**
-     * Set the volume of this audio track as percentage of the volume in the
-     * original audio source file.
-     *
-     * @param volumePercent Percentage of the volume to apply. If it is set to
-     *         0, then volume becomes mute. It it is set to 100, then volume
-     *         is same as original volume. It it is set to 200, then volume
-     *         is doubled (provided that volume amplification is supported)
-     *
-     * @throws UnsupportedOperationException if volume amplification is
-     *         requested and is not supported.
-     */
-    public void setVolume(int volumePercent) {
-        if (volumePercent > MediaProperties.AUDIO_MAX_VOLUME_PERCENT) {
-            throw new IllegalArgumentException("Volume set exceeds maximum allowed value");
-        }
-
-        if (volumePercent < 0) {
-            throw new IllegalArgumentException("Invalid Volume ");
-        }
-
-        /**
-         *  Force update of preview settings
-         */
-        mMANativeHelper.setGeneratePreview(true);
-
-        mVolumePercent = volumePercent;
-    }
-
-    /**
-     * Get the volume of the audio track as percentage of the volume in the
-     * original audio source file.
-     *
-     * @return The volume in percentage
-     */
-    public int getVolume() {
-        return mVolumePercent;
-    }
-
-    /**
-     * Mute/Unmute the audio track
-     *
-     * @param muted true to mute the audio track. SetMute(true) will make
-     *         the volume of this Audio Track to 0.
-     */
-    public void setMute(boolean muted) {
-        /**
-         *  Force update of preview settings
-         */
-        mMANativeHelper.setGeneratePreview(true);
-        mMuted = muted;
-    }
-
-    /**
-     * Check if the audio track is muted
-     *
-     * @return true if the audio track is muted
-     */
-    public boolean isMuted() {
-        return mMuted;
-    }
-
-    /**
-     * Get the start time of this audio track relative to the storyboard
-     * timeline.
-     *
-     * @return The start time in milliseconds
-     */
-
-    public long getStartTime() {
-        return mStartTimeMs;
-    }
-
-    /**
-     * Get the audio track duration
-     *
-     * @return The duration in milliseconds. This value represents actual audio
-     *         track duration. This value is not effected by 'enableLoop' or
-     *         'setExtractBoundaries'.
-     */
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /**
-     * Get the audio track timeline duration
-     *
-     * @return The timeline duration as defined by the begin and end boundaries
-     */
-    public long getTimelineDuration() {
-        return mTimelineDurationMs;
-    }
-
-    /**
-     * Sets the start and end marks for trimming an audio track
-     *
-     * @param beginMs start time in the audio track in milliseconds (relative to
-     *         the beginning of the audio track)
-     * @param endMs end time in the audio track in milliseconds (relative to the
-     *         beginning of the audio track)
-     */
-    public void setExtractBoundaries(long beginMs, long endMs) {
-        if (beginMs > mDurationMs) {
-            throw new IllegalArgumentException("Invalid start time");
-        }
-        if (endMs > mDurationMs) {
-            throw new IllegalArgumentException("Invalid end time");
-        }
-        if (beginMs < 0) {
-            throw new IllegalArgumentException("Invalid start time; is < 0");
-        }
-        if (endMs < 0) {
-            throw new IllegalArgumentException("Invalid end time; is < 0");
-        }
-
-        /**
-         *  Force update of preview settings
-         */
-        mMANativeHelper.setGeneratePreview(true);
-
-        mBeginBoundaryTimeMs = beginMs;
-        mEndBoundaryTimeMs = endMs;
-
-        mTimelineDurationMs = mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
-    }
-
-    /**
-     * Get the boundary begin time
-     *
-     * @return The boundary begin time
-     */
-    public long getBoundaryBeginTime() {
-        return mBeginBoundaryTimeMs;
-    }
-
-    /**
-     * Get the boundary end time
-     *
-     * @return The boundary end time
-     */
-    public long getBoundaryEndTime() {
-        return mEndBoundaryTimeMs;
-    }
-
-    /**
-     * Enable the loop mode for this audio track. Note that only one of the
-     * audio tracks in the timeline can have the loop mode enabled. When looping
-     * is enabled the samples between mBeginBoundaryTimeMs and
-     * mEndBoundaryTimeMs are looped.
-     */
-    public void enableLoop() {
-        if (!mLoop) {
-            /**
-             *  Force update of preview settings
-             */
-            mMANativeHelper.setGeneratePreview(true);
-            mLoop = true;
-        }
-    }
-
-    /**
-     * Disable the loop mode
-     */
-    public void disableLoop() {
-        if (mLoop) {
-            /**
-             *  Force update of preview settings
-             */
-            mMANativeHelper.setGeneratePreview(true);
-            mLoop = false;
-        }
-    }
-
-    /**
-     * Check if looping is enabled
-     *
-     * @return true if looping is enabled
-     */
-    public boolean isLooping() {
-        return mLoop;
-    }
-
-    /**
-     * Disable the audio duck effect
-     */
-    public void disableDucking() {
-        if (mIsDuckingEnabled) {
-            /**
-             *  Force update of preview settings
-             */
-            mMANativeHelper.setGeneratePreview(true);
-            mIsDuckingEnabled = false;
-        }
-    }
-
-    /**
-     * Enable ducking by specifying the required parameters
-     *
-     * @param threshold Ducking will be activated when the energy in
-     *         the media items audio signal goes above this value. The valid
-     *         range of values is 0db to 90dB. 0dB is equivalent to disabling
-     *         ducking.
-     * @param duckedTrackVolume The relative volume of the audio track when ducking
-     *         is active. The valid range of values is 0 to 100.
-     */
-    public void enableDucking(int threshold, int duckedTrackVolume) {
-        if (threshold < 0 || threshold > 90) {
-            throw new IllegalArgumentException("Invalid threshold value: " + threshold);
-        }
-
-        if (duckedTrackVolume < 0 || duckedTrackVolume > 100) {
-            throw new IllegalArgumentException("Invalid duckedTrackVolume value: "
-                    + duckedTrackVolume);
-        }
-
-        /**
-         *  Force update of preview settings
-         */
-        mMANativeHelper.setGeneratePreview(true);
-
-        mDuckingThreshold = threshold;
-        mDuckedTrackVolume = duckedTrackVolume;
-        mIsDuckingEnabled = true;
-    }
-
-    /**
-     * Check if ducking is enabled
-     *
-     * @return true if ducking is enabled
-     */
-    public boolean isDuckingEnabled() {
-        return mIsDuckingEnabled;
-    }
-
-    /**
-     * Get the ducking threshold.
-     *
-     * @return The ducking threshold
-     */
-    public int getDuckingThreshhold() {
-        return mDuckingThreshold;
-    }
-
-    /**
-     * Get the ducked track volume.
-     *
-     * @return The ducked track volume
-     */
-    public int getDuckedTrackVolume() {
-        return mDuckedTrackVolume;
-    }
-
-    /**
-     * This API allows to generate a file containing the sample volume levels of
-     * this audio track object. This function may take significant time and is
-     * blocking. The filename can be retrieved using getAudioWaveformFilename().
-     *
-     * @param listener The progress listener
-     *
-     * @throws IOException if the output file cannot be created
-     * @throws IllegalArgumentException if the audio file does not have a valid
-     *         audio track
-     * @throws IllegalStateException if the codec type is unsupported
-     */
-    public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
-    throws IOException {
-        if (mAudioWaveformFilename == null) {
-            /**
-             *  AudioWaveformFilename is generated
-             */
-            final String projectPath = mMANativeHelper.getProjectPath();
-            final String audioWaveFilename = String.format(projectPath + "/audioWaveformFile-"
-                    + getId() + ".dat");
-
-            /**
-             * Logic to get frame duration = (no. of frames per sample * 1000)/
-             * sampling frequency
-             */
-            final int frameDuration;
-            final int sampleCount;
-            final int codecType = mMANativeHelper.getAudioCodecType(mAudioType);
-            switch (codecType) {
-                case MediaProperties.ACODEC_AMRNB: {
-                    frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB * 1000)
-                    / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                    sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB;
-                    break;
-                }
-
-                case MediaProperties.ACODEC_AMRWB: {
-                    frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)
-                    / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                    sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB;
-                    break;
-                }
-
-                case MediaProperties.ACODEC_AAC_LC: {
-                    frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)
-                    / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                    sampleCount = MediaProperties.SAMPLES_PER_FRAME_AAC;
-                    break;
-                }
-
-                case MediaProperties.ACODEC_MP3: {
-                    frameDuration = (MediaProperties.SAMPLES_PER_FRAME_MP3 * 1000)
-                    / MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                    sampleCount = MediaProperties.SAMPLES_PER_FRAME_MP3;
-                    break;
-                }
-
-                default: {
-                    throw new IllegalStateException("Unsupported codec type: "
-                                                                   + codecType);
-                }
-            }
-
-            mMANativeHelper.generateAudioGraph( mUniqueId,
-                    mFilename,
-                    audioWaveFilename,
-                    frameDuration,
-                    MediaProperties.DEFAULT_CHANNEL_COUNT,
-                    sampleCount,
-                    listener,
-                    false);
-            /**
-             *  Record the generated file name
-             */
-            mAudioWaveformFilename = audioWaveFilename;
-        }
-        mWaveformData = new SoftReference<WaveformData>(new WaveformData(mAudioWaveformFilename));
-    }
-
-    /**
-     * Get the audio waveform file name if extractAudioWaveform was successful.
-     *
-     * @return the name of the file, null if the file does not exist
-     */
-    String getAudioWaveformFilename() {
-        return mAudioWaveformFilename;
-    }
-
-    /**
-     * Delete the waveform file
-     */
-    void invalidate() {
-        if (mAudioWaveformFilename != null) {
-            new File(mAudioWaveformFilename).delete();
-            mAudioWaveformFilename = null;
-            mWaveformData = null;
-        }
-    }
-
-    /**
-     * Get the audio waveform data.
-     *
-     * @return The waveform data
-     *
-     * @throws IOException if the waveform file cannot be found
-     */
-    public WaveformData getWaveformData() throws IOException {
-        if (mWaveformData == null) {
-            return null;
-        }
-
-        WaveformData waveformData = mWaveformData.get();
-        if (waveformData != null) {
-            return waveformData;
-        } else if (mAudioWaveformFilename != null) {
-            try {
-                waveformData = new WaveformData(mAudioWaveformFilename);
-            } catch (IOException e) {
-                throw e;
-            }
-            mWaveformData = new SoftReference<WaveformData>(waveformData);
-            return waveformData;
-        } else {
-            return null;
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (!(object instanceof AudioTrack)) {
-            return false;
-        }
-        return mUniqueId.equals(((AudioTrack)object).mUniqueId);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return mUniqueId.hashCode();
-    }
-}
diff --git a/media/java/android/media/videoeditor/Effect.java b/media/java/android/media/videoeditor/Effect.java
deleted file mode 100644
index 2f7ae03..0000000
--- a/media/java/android/media/videoeditor/Effect.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-/**
- * This is the super class for all effects. An effect can only be applied to a
- * single media item.
- * {@hide}
- */
-public abstract class Effect {
-    /**
-     *  Instance variables
-     */
-    private final String mUniqueId;
-    /**
-     *  The effect owner
-     */
-    private final MediaItem mMediaItem;
-
-    protected long mDurationMs;
-    /**
-     *  The start time of the effect relative to the beginning
-     *  of the media item
-     */
-    protected long mStartTimeMs;
-
-    /**
-     * Default constructor
-     */
-    @SuppressWarnings("unused")
-    private Effect() {
-        mMediaItem = null;
-        mUniqueId = null;
-        mStartTimeMs = 0;
-        mDurationMs = 0;
-    }
-
-    /**
-     * Constructor
-     *
-     * @param mediaItem The media item owner
-     * @param effectId The effect id
-     * @param startTimeMs The start time relative to the media item to which it
-     *            is applied
-     * @param durationMs The effect duration in milliseconds
-     */
-    public Effect(MediaItem mediaItem, String effectId, long startTimeMs,
-                  long durationMs) {
-        if (mediaItem == null) {
-            throw new IllegalArgumentException("Media item cannot be null");
-        }
-
-        if ((startTimeMs < 0) || (durationMs < 0)) {
-             throw new IllegalArgumentException("Invalid start time Or/And Duration");
-        }
-        if (startTimeMs + durationMs > mediaItem.getDuration()) {
-            throw new IllegalArgumentException("Invalid start time and duration");
-        }
-
-        mMediaItem = mediaItem;
-        mUniqueId = effectId;
-        mStartTimeMs = startTimeMs;
-        mDurationMs = durationMs;
-    }
-
-    /**
-     * Get the id of the effect.
-     *
-     * @return The id of the effect
-     */
-    public String getId() {
-        return mUniqueId;
-    }
-
-    /**
-     * Set the duration of the effect. If a preview or export is in progress,
-     * then this change is effective for next preview or export session.
-     *
-     * @param durationMs of the effect in milliseconds
-     */
-    public void setDuration(long durationMs) {
-        if (durationMs <0) {
-            throw new IllegalArgumentException("Invalid duration");
-        }
-
-        if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Duration is too large");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-
-        final long oldDurationMs = mDurationMs;
-        mDurationMs = durationMs;
-
-        mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the duration of the effect
-     *
-     * @return The duration of the effect in milliseconds
-     */
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /**
-     * Set start time of the effect. If a preview or export is in progress, then
-     * this change is effective for next preview or export session.
-     *
-     * @param startTimeMs The start time of the effect relative to the beginning
-     *            of the media item in milliseconds
-     */
-    public void setStartTime(long startTimeMs) {
-        if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Start time is too large");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-        final long oldStartTimeMs = mStartTimeMs;
-        mStartTimeMs = startTimeMs;
-
-        mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the start time of the effect
-     *
-     * @return The start time in milliseconds
-     */
-    public long getStartTime() {
-        return mStartTimeMs;
-    }
-
-    /**
-     * Set the start time and duration
-     *
-     * @param startTimeMs start time in milliseconds
-     * @param durationMs The duration in milliseconds
-     */
-    public void setStartTimeAndDuration(long startTimeMs, long durationMs) {
-        if (startTimeMs + durationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Invalid start time or duration");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-        final long oldStartTimeMs = mStartTimeMs;
-        final long oldDurationMs = mDurationMs;
-
-        mStartTimeMs = startTimeMs;
-        mDurationMs = durationMs;
-
-        mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the media item owner.
-     *
-     * @return The media item owner
-     */
-    public MediaItem getMediaItem() {
-        return mMediaItem;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (!(object instanceof Effect)) {
-            return false;
-        }
-        return mUniqueId.equals(((Effect)object).mUniqueId);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return mUniqueId.hashCode();
-    }
-}
diff --git a/media/java/android/media/videoeditor/EffectColor.java b/media/java/android/media/videoeditor/EffectColor.java
deleted file mode 100644
index 6c5ac2d..0000000
--- a/media/java/android/media/videoeditor/EffectColor.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-/**
- * This class allows to apply color effect on a media item.
- * {@hide}
- */
-public class EffectColor extends Effect {
-
-    /**
-     * Change the video frame color to the RGB color value provided
-     */
-    public static final int TYPE_COLOR = 1;
-    /**
-     * Change the video frame color to a gradation from RGB color (at the top of
-     * the frame) to black (at the bottom of the frame).
-     */
-    public static final int TYPE_GRADIENT = 2;
-    /**
-     * Change the video frame color to sepia
-     */
-    public static final int TYPE_SEPIA = 3;
-    /**
-     * Invert the video frame color
-     */
-    public static final int TYPE_NEGATIVE = 4;
-    /**
-     * Make the video look like as if it was recorded in 50's
-     */
-    public static final int TYPE_FIFTIES = 5;
-    /**
-     * Change the video frame color to the RGB color value GREEN
-     */
-    public static final int GREEN = 0x0000ff00;
-    /**
-     * Change the video frame color to the RGB color value PINK
-     */
-    public static final int PINK = 0x00ff66cc;
-    /**
-     * Change the video frame color to the RGB color value GRAY
-     */
-    public static final int GRAY = 0x007f7f7f;
-
-    /**
-     *  The effect type
-     */
-    private final int mType;
-
-    /**
-     *  The effect color
-     */
-    private final int mColor;
-
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private EffectColor() {
-        this(null, null, 0, 0, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param mediaItem The media item owner
-     * @param effectId The effect id
-     * @param startTimeMs The start time relative to the media item to which it
-     *            is applied
-     * @param durationMs The duration of this effect in milliseconds
-     * @param type type of the effect. type is one of: TYPE_COLOR,
-     *            TYPE_GRADIENT, TYPE_SEPIA, TYPE_NEGATIVE, TYPE_FIFTIES.
-     * @param color If type is TYPE_COLOR, color is the RGB color as 888.
-     *              If type is TYPE_GRADIENT, color is the RGB color at the
-     *              top of the frame. Otherwise, color is ignored
-     */
-    public EffectColor(MediaItem mediaItem, String effectId, long startTimeMs,
-                      long durationMs, int type, int color) {
-        super(mediaItem, effectId, startTimeMs, durationMs);
-        switch (type) {
-            case TYPE_COLOR:
-            case TYPE_GRADIENT: {
-                switch (color) {
-                    case GREEN:
-                    case PINK:
-                    case GRAY:
-                        mColor = color;
-                        break;
-
-                    default:
-                        throw new IllegalArgumentException("Invalid Color: " + color);
-                    }
-                    break;
-            }
-            case TYPE_SEPIA:
-            case TYPE_NEGATIVE:
-            case TYPE_FIFTIES: {
-                mColor = -1;
-                break;
-            }
-
-            default: {
-                throw new IllegalArgumentException("Invalid type: " + type);
-            }
-        }
-        mType = type;
-    }
-
-    /**
-     * Get the effect type.
-     *
-     * @return The effect type
-     */
-    public int getType() {
-        return mType;
-    }
-
-    /**
-     * Get the color if effect type is TYPE_COLOR or TYPE_GRADIENT.
-     *
-     * @return the color as RGB 888 if type is TYPE_COLOR or TYPE_GRADIENT.
-     */
-    public int getColor() {
-        return mColor;
-    }
-}
diff --git a/media/java/android/media/videoeditor/EffectKenBurns.java b/media/java/android/media/videoeditor/EffectKenBurns.java
deleted file mode 100644
index 64be6b8..0000000
--- a/media/java/android/media/videoeditor/EffectKenBurns.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import android.graphics.Rect;
-
-/**
- * This class represents a Ken Burns effect.
- * {@hide}
- */
-public class EffectKenBurns extends Effect {
-    /**
-     *  Instance variables
-     */
-    private Rect mStartRect;
-    private Rect mEndRect;
-
-    /**
-     * Objects of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private EffectKenBurns() {
-        this(null, null, null, null, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param mediaItem The media item owner
-     * @param effectId The effect id
-     * @param startRect The start rectangle
-     * @param endRect The end rectangle
-     * @param startTimeMs The start time
-     * @param durationMs The duration of the Ken Burns effect in milliseconds
-     */
-    public EffectKenBurns(MediaItem mediaItem, String effectId, Rect startRect,
-                         Rect endRect, long startTimeMs, long durationMs) {
-        super(mediaItem, effectId, startTimeMs, durationMs);
-
-        if ( (startRect.width() <= 0) || (startRect.height() <= 0) ) {
-            throw new IllegalArgumentException("Invalid Start rectangle");
-        }
-        if ( (endRect.width() <= 0) || (endRect.height() <= 0) ) {
-            throw new IllegalArgumentException("Invalid End rectangle");
-        }
-
-        mStartRect = startRect;
-        mEndRect = endRect;
-    }
-
-
-    /**
-     * Get the start rectangle.
-     *
-     * @return The start rectangle
-     */
-    public Rect getStartRect() {
-        return mStartRect;
-    }
-
-
-    /**
-     * Get the end rectangle.
-     *
-     * @return The end rectangle
-     */
-    public Rect getEndRect() {
-        return mEndRect;
-    }
-
-    /**
-     * Get the KenBurn effect start and end rectangle coordinates
-     * @param start The rect object to be populated with start
-     * rectangle coordinates
-     *
-     * @param end The rect object to be populated with end
-     * rectangle coordinates
-     */
-    void getKenBurnsSettings(Rect start, Rect end) {
-        start.left = getStartRect().left;
-        start.top = getStartRect().top;
-        start.right = getStartRect().right;
-        start.bottom = getStartRect().bottom;
-        end.left = getEndRect().left;
-        end.top = getEndRect().top;
-        end.right = getEndRect().right;
-        end.bottom = getEndRect().bottom;
-    }
-}
diff --git a/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java b/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java
deleted file mode 100644
index 7ba7de3..0000000
--- a/media/java/android/media/videoeditor/ExtractAudioWaveformProgressListener.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-/**
- * This listener interface is used by
- * {@link MediaVideoItem#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
- * or
- * {@link AudioTrack#extractAudioWaveform(ExtractAudioWaveformProgressListener listener)}
- * {@hide}
- */
-public interface ExtractAudioWaveformProgressListener {
-    /**
-     * This method notifies the listener of the progress status of
-     * an extractAudioWaveform operation.
-     * This method may be called maximum 100 times for one operation.
-     *
-     * @param progress The progress in %. At the beginning of the operation,
-     *          this value is set to 0; at the end, the value is set to 100.
-     */
-    public void onProgress(int progress);
-}
-
diff --git a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java b/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
deleted file mode 100644
index 2d3de85..0000000
--- a/media/java/android/media/videoeditor/MediaArtistNativeHelper.java
+++ /dev/null
@@ -1,4034 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.math.BigDecimal;
-import java.nio.IntBuffer;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Matrix;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.PreviewProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.util.Log;
-import android.util.Pair;
-import android.view.Surface;
-
-/**
- *This class provide Native methods to be used by MediaArtist {@hide}
- */
-class MediaArtistNativeHelper {
-    private static final String TAG = "MediaArtistNativeHelper";
-
-    static {
-        System.loadLibrary("videoeditor_jni");
-    }
-
-    private static final int MAX_THUMBNAIL_PERMITTED = 8;
-
-    public static final int TASK_LOADING_SETTINGS = 1;
-    public static final int TASK_ENCODING = 2;
-
-    /**
-     *  The resize paint
-     */
-    private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
-    private final VideoEditor mVideoEditor;
-    /*
-     *  Semaphore to control preview calls
-     */
-    private final Semaphore mLock;
-
-    private EditSettings mStoryBoardSettings;
-
-    private String mOutputFilename;
-
-    private PreviewClipProperties mClipProperties = null;
-
-    private EditSettings mPreviewEditSettings;
-
-    private AudioSettings mAudioSettings = null;
-
-    private AudioTrack mAudioTrack = null;
-
-    private boolean mInvalidatePreviewArray = true;
-
-    private boolean mRegenerateAudio = true;
-
-    private String mExportFilename = null;
-    private int mExportVideoCodec = 0;
-    private int mExportAudioCodec = 0;
-    private int mProgressToApp;
-
-    private String mRenderPreviewOverlayFile;
-    private int mRenderPreviewRenderingMode;
-
-    private boolean mIsFirstProgress;
-
-    private static final String AUDIO_TRACK_PCM_FILE = "AudioPcm.pcm";
-
-    // Processing indication
-    public static final int PROCESSING_NONE          = 0;
-    public static final int PROCESSING_AUDIO_PCM     = 1;
-    public static final int PROCESSING_TRANSITION    = 2;
-    public static final int PROCESSING_KENBURNS      = 3;
-    public static final int PROCESSING_INTERMEDIATE1 = 11;
-    public static final int PROCESSING_INTERMEDIATE2 = 12;
-    public static final int PROCESSING_INTERMEDIATE3 = 13;
-    public static final int PROCESSING_EXPORT        = 20;
-
-    private int mProcessingState;
-    private Object mProcessingObject;
-    private PreviewProgressListener mPreviewProgressListener;
-    private ExportProgressListener mExportProgressListener;
-    private ExtractAudioWaveformProgressListener mExtractAudioWaveformProgressListener;
-    private MediaProcessingProgressListener mMediaProcessingProgressListener;
-    private final String mProjectPath;
-
-    private long mPreviewProgress;
-
-    private String mAudioTrackPCMFilePath;
-
-    private int mTotalClips = 0;
-
-    private boolean mErrorFlagSet = false;
-
-    @SuppressWarnings("unused")
-    private long mManualEditContext;
-
-    /* Listeners */
-
-    /**
-     * Interface definition for a listener to be invoked when there is an update
-     * in a running task.
-     */
-    public interface OnProgressUpdateListener {
-        /**
-         * Called when there is an update.
-         *
-         * @param taskId id of the task reporting an update.
-         * @param progress progress of the task [0..100].
-         * @see BasicEdit#TASK_ENCODING
-         */
-        public void OnProgressUpdate(int taskId, int progress);
-    }
-
-    /** Defines the version. */
-    public final class Version {
-
-        /** Major version number */
-        public int major;
-
-        /** Minor version number */
-        public int minor;
-
-        /** Revision number */
-        public int revision;
-
-        /** VIDEOEDITOR major version number */
-        private static final int VIDEOEDITOR_MAJOR_VERSION = 0;
-
-        /** VIDEOEDITOR minor version number */
-        private static final int VIDEOEDITOR_MINOR_VERSION = 0;
-
-        /** VIDEOEDITOR revision number */
-        private static final int VIDEOEDITOR_REVISION_VERSION = 1;
-
-        /** Method which returns the current VIDEOEDITOR version */
-        public Version getVersion() {
-            Version version = new Version();
-
-            version.major = Version.VIDEOEDITOR_MAJOR_VERSION;
-            version.minor = Version.VIDEOEDITOR_MINOR_VERSION;
-            version.revision = Version.VIDEOEDITOR_REVISION_VERSION;
-
-            return version;
-        }
-    }
-
-    /**
-     * Defines output audio formats.
-     */
-    public final class AudioFormat {
-        /** No audio present in output clip. Used to generate video only clip */
-        public static final int NO_AUDIO = 0;
-
-        /** AMR Narrow Band. */
-        public static final int AMR_NB = 1;
-
-        /** Advanced Audio Coding (AAC). */
-        public static final int AAC = 2;
-
-        /** Advanced Audio Codec Plus (HE-AAC v1). */
-        public static final int AAC_PLUS = 3;
-
-        /** Advanced Audio Codec Plus (HE-AAC v2). */
-        public static final int ENHANCED_AAC_PLUS = 4;
-
-        /** MPEG layer 3 (MP3). */
-        public static final int MP3 = 5;
-
-        /** Enhanced Variable RateCodec (EVRC). */
-        public static final int EVRC = 6;
-
-        /** PCM (PCM). */
-        public static final int PCM = 7;
-
-        /** No transcoding. Output audio format is same as input audio format */
-        public static final int NULL_AUDIO = 254;
-
-        /** Unsupported audio format. */
-        public static final int UNSUPPORTED_AUDIO = 255;
-    }
-
-    /**
-     * Defines audio sampling frequencies.
-     */
-    public final class AudioSamplingFrequency {
-        /**
-         * Default sampling frequency. Uses the default frequency for a specific
-         * audio format. For AAC the only supported (and thus default) sampling
-         * frequency is 16 kHz. For this audio format the sampling frequency in
-         * the OutputParams.
-         **/
-        public static final int FREQ_DEFAULT = 0;
-
-        /** Audio sampling frequency of 8000 Hz. */
-        public static final int FREQ_8000 = 8000;
-
-        /** Audio sampling frequency of 11025 Hz. */
-        public static final int FREQ_11025 = 11025;
-
-        /** Audio sampling frequency of 12000 Hz. */
-        public static final int FREQ_12000 = 12000;
-
-        /** Audio sampling frequency of 16000 Hz. */
-        public static final int FREQ_16000 = 16000;
-
-        /** Audio sampling frequency of 22050 Hz. */
-        public static final int FREQ_22050 = 22050;
-
-        /** Audio sampling frequency of 24000 Hz. */
-        public static final int FREQ_24000 = 24000;
-
-        /** Audio sampling frequency of 32000 Hz. */
-        public static final int FREQ_32000 = 32000;
-
-        /** Audio sampling frequency of 44100 Hz. */
-        public static final int FREQ_44100 = 44100;
-
-        /** Audio sampling frequency of 48000 Hz. Not available for output file. */
-        public static final int FREQ_48000 = 48000;
-    }
-
-    /**
-     * Defines the supported fixed audio and video bitrates. These values are
-     * for output audio video only.
-     */
-    public final class Bitrate {
-        /** Variable bitrate. Means no bitrate regulation */
-        public static final int VARIABLE = -1;
-
-        /** An undefined bitrate. */
-        public static final int UNDEFINED = 0;
-
-        /** A bitrate of 9.2 kbits/s. */
-        public static final int BR_9_2_KBPS = 9200;
-
-        /** A bitrate of 12.2 kbits/s. */
-        public static final int BR_12_2_KBPS = 12200;
-
-        /** A bitrate of 16 kbits/s. */
-        public static final int BR_16_KBPS = 16000;
-
-        /** A bitrate of 24 kbits/s. */
-        public static final int BR_24_KBPS = 24000;
-
-        /** A bitrate of 32 kbits/s. */
-        public static final int BR_32_KBPS = 32000;
-
-        /** A bitrate of 48 kbits/s. */
-        public static final int BR_48_KBPS = 48000;
-
-        /** A bitrate of 64 kbits/s. */
-        public static final int BR_64_KBPS = 64000;
-
-        /** A bitrate of 96 kbits/s. */
-        public static final int BR_96_KBPS = 96000;
-
-        /** A bitrate of 128 kbits/s. */
-        public static final int BR_128_KBPS = 128000;
-
-        /** A bitrate of 192 kbits/s. */
-        public static final int BR_192_KBPS = 192000;
-
-        /** A bitrate of 256 kbits/s. */
-        public static final int BR_256_KBPS = 256000;
-
-        /** A bitrate of 288 kbits/s. */
-        public static final int BR_288_KBPS = 288000;
-
-        /** A bitrate of 384 kbits/s. */
-        public static final int BR_384_KBPS = 384000;
-
-        /** A bitrate of 512 kbits/s. */
-        public static final int BR_512_KBPS = 512000;
-
-        /** A bitrate of 800 kbits/s. */
-        public static final int BR_800_KBPS = 800000;
-
-        /** A bitrate of 2 Mbits/s. */
-        public static final int BR_2_MBPS = 2000000;
-
-        /** A bitrate of 5 Mbits/s. */
-        public static final int BR_5_MBPS = 5000000;
-
-        /** A bitrate of 8 Mbits/s. */
-        public static final int BR_8_MBPS = 8000000;
-    }
-
-    /**
-     * Defines all supported file types.
-     */
-    public final class FileType {
-        /** 3GPP file type. */
-        public static final int THREE_GPP = 0;
-
-        /** MP4 file type. */
-        public static final int MP4 = 1;
-
-        /** AMR file type. */
-        public static final int AMR = 2;
-
-        /** MP3 audio file type. */
-        public static final int MP3 = 3;
-
-        /** PCM audio file type. */
-        public static final int PCM = 4;
-
-        /** JPEG image file type. */
-        public static final int JPG = 5;
-
-        /** GIF image file type. */
-        public static final int GIF = 7;
-
-        /** PNG image file type. */
-        public static final int PNG = 8;
-
-        /** M4V file type. */
-        public static final int M4V = 10;
-
-        /** Unsupported file type. */
-        public static final int UNSUPPORTED = 255;
-    }
-
-    /**
-     * Defines rendering types. Rendering can only be applied to files
-     * containing video streams.
-     **/
-    public final class MediaRendering {
-        /**
-         * Resize to fit the output video with changing the aspect ratio if
-         * needed.
-         */
-        public static final int RESIZING = 0;
-
-        /**
-         * Crop the input video to fit it with the output video resolution.
-         **/
-        public static final int CROPPING = 1;
-
-        /**
-         * Resize to fit the output video resolution but maintain the aspect
-         * ratio. This framing type adds black borders if needed.
-         */
-        public static final int BLACK_BORDERS = 2;
-    }
-
-    /**
-     * Defines the results.
-     */
-    public final class Result {
-        /** No error. result OK */
-        public static final int NO_ERROR = 0;
-
-        /** File not found */
-        public static final int ERR_FILE_NOT_FOUND = 1;
-
-        /**
-         * In case of UTF8 conversion, the size of the converted path will be
-         * more than the corresponding allocated buffer.
-         */
-        public static final int ERR_BUFFER_OUT_TOO_SMALL = 2;
-
-        /** Invalid file type. */
-        public static final int ERR_INVALID_FILE_TYPE = 3;
-
-        /** Invalid effect kind. */
-        public static final int ERR_INVALID_EFFECT_KIND = 4;
-
-        /** Invalid video effect. */
-        public static final int ERR_INVALID_VIDEO_EFFECT_TYPE = 5;
-
-        /** Invalid audio effect. */
-        public static final int ERR_INVALID_AUDIO_EFFECT_TYPE = 6;
-
-        /** Invalid video transition. */
-        public static final int ERR_INVALID_VIDEO_TRANSITION_TYPE = 7;
-
-        /** Invalid audio transition. */
-        public static final int ERR_INVALID_AUDIO_TRANSITION_TYPE = 8;
-
-        /** Invalid encoding frame rate. */
-        public static final int ERR_INVALID_VIDEO_ENCODING_FRAME_RATE = 9;
-
-        /** External effect is called but this function is not set. */
-        public static final int ERR_EXTERNAL_EFFECT_NULL = 10;
-
-        /** External transition is called but this function is not set. */
-        public static final int ERR_EXTERNAL_TRANSITION_NULL = 11;
-
-        /** Begin time cut is larger than the video clip duration. */
-        public static final int ERR_BEGIN_CUT_LARGER_THAN_DURATION = 12;
-
-        /** Begin cut time is larger or equal than end cut. */
-        public static final int ERR_BEGIN_CUT_LARGER_THAN_END_CUT = 13;
-
-        /** Two consecutive transitions are overlapping on one clip. */
-        public static final int ERR_OVERLAPPING_TRANSITIONS = 14;
-
-        /** Internal error, type size mismatch. */
-        public static final int ERR_ANALYSIS_DATA_SIZE_TOO_SMALL = 15;
-
-        /** An input 3GPP file is invalid/corrupted. */
-        public static final int ERR_INVALID_3GPP_FILE = 16;
-
-        /** A file contains an unsupported video format. */
-        public static final int ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT = 17;
-
-        /** A file contains an unsupported audio format. */
-        public static final int ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT = 18;
-
-        /** A file format is not supported. */
-        public static final int ERR_AMR_EDITING_UNSUPPORTED = 19;
-
-        /** An input clip has an unexpectedly large Video AU. */
-        public static final int ERR_INPUT_VIDEO_AU_TOO_LARGE = 20;
-
-        /** An input clip has an unexpectedly large Audio AU. */
-        public static final int ERR_INPUT_AUDIO_AU_TOO_LARGE = 21;
-
-        /** An input clip has a corrupted Audio AU. */
-        public static final int ERR_INPUT_AUDIO_CORRUPTED_AU = 22;
-
-        /** The video encoder encountered an Access Unit error. */
-        public static final int ERR_ENCODER_ACCES_UNIT_ERROR = 23;
-
-        /** Unsupported video format for Video Editing. */
-        public static final int ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT = 24;
-
-        /** Unsupported H263 profile for Video Editing. */
-        public static final int ERR_EDITING_UNSUPPORTED_H263_PROFILE = 25;
-
-        /** Unsupported MPEG-4 profile for Video Editing. */
-        public static final int ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE = 26;
-
-        /** Unsupported MPEG-4 RVLC tool for Video Editing. */
-        public static final int ERR_EDITING_UNSUPPORTED_MPEG4_RVLC = 27;
-
-        /** Unsupported audio format for Video Editing. */
-        public static final int ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT = 28;
-
-        /** File contains no supported stream. */
-        public static final int ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE = 29;
-
-        /** File contains no video stream or an unsupported video stream. */
-        public static final int ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 30;
-
-        /** Internal error, clip analysis version mismatch. */
-        public static final int ERR_INVALID_CLIP_ANALYSIS_VERSION = 31;
-
-        /**
-         * At least one of the clip analysis has been generated on another
-         * platform (WIN32, ARM, etc.).
-         */
-        public static final int ERR_INVALID_CLIP_ANALYSIS_PLATFORM = 32;
-
-        /** Clips don't have the same video format (H263 or MPEG4). */
-        public static final int ERR_INCOMPATIBLE_VIDEO_FORMAT = 33;
-
-        /** Clips don't have the same frame size. */
-        public static final int ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE = 34;
-
-        /** Clips don't have the same MPEG-4 time scale. */
-        public static final int ERR_INCOMPATIBLE_VIDEO_TIME_SCALE = 35;
-
-        /** Clips don't have the same use of MPEG-4 data partitioning. */
-        public static final int ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING = 36;
-
-        /** MP3 clips can't be assembled. */
-        public static final int ERR_UNSUPPORTED_MP3_ASSEMBLY = 37;
-
-        /**
-         * The input 3GPP file does not contain any supported audio or video
-         * track.
-         */
-        public static final int ERR_NO_SUPPORTED_STREAM_IN_FILE = 38;
-
-        /**
-         * The Volume of the added audio track (AddVolume) must be strictly
-         * superior than zero.
-         */
-        public static final int ERR_ADDVOLUME_EQUALS_ZERO = 39;
-
-        /**
-         * The time at which an audio track is added can't be higher than the
-         * input video track duration..
-         */
-        public static final int ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION = 40;
-
-        /** The audio track file format setting is undefined. */
-        public static final int ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT = 41;
-
-        /** The added audio track stream has an unsupported format. */
-        public static final int ERR_UNSUPPORTED_ADDED_AUDIO_STREAM = 42;
-
-        /** The audio mixing feature doesn't support the audio track type. */
-        public static final int ERR_AUDIO_MIXING_UNSUPPORTED = 43;
-
-        /** The audio mixing feature doesn't support MP3 audio tracks. */
-        public static final int ERR_AUDIO_MIXING_MP3_UNSUPPORTED = 44;
-
-        /**
-         * An added audio track limits the available features: uiAddCts must be
-         * 0 and bRemoveOriginal must be true.
-         */
-        public static final int ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK = 45;
-
-        /**
-         * An added audio track limits the available features: uiAddCts must be
-         * 0 and bRemoveOriginal must be true.
-         */
-        public static final int ERR_FEATURE_UNSUPPORTED_WITH_AAC = 46;
-
-        /** Input audio track is not of a type that can be mixed with output. */
-        public static final int ERR_AUDIO_CANNOT_BE_MIXED = 47;
-
-        /** Input audio track is not AMR-NB, so it can't be mixed with output. */
-        public static final int ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED = 48;
-
-        /**
-         * An added EVRC audio track limit the available features: uiAddCts must
-         * be 0 and bRemoveOriginal must be true.
-         */
-        public static final int ERR_FEATURE_UNSUPPORTED_WITH_EVRC = 49;
-
-        /** H263 profiles other than 0 are not supported. */
-        public static final int ERR_H263_PROFILE_NOT_SUPPORTED = 51;
-
-        /** File contains no video stream or an unsupported video stream. */
-        public static final int ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE = 52;
-
-        /** Transcoding of the input file(s) is necessary. */
-        public static final int WAR_TRANSCODING_NECESSARY = 53;
-
-        /**
-         * The size of the output file will exceed the maximum configured value.
-         */
-        public static final int WAR_MAX_OUTPUT_SIZE_EXCEEDED = 54;
-
-        /** The time scale is too big. */
-        public static final int WAR_TIMESCALE_TOO_BIG = 55;
-
-        /** The year is out of range */
-        public static final int ERR_CLOCK_BAD_REF_YEAR = 56;
-
-        /** The directory could not be opened */
-        public static final int ERR_DIR_OPEN_FAILED = 57;
-
-        /** The directory could not be read */
-        public static final int ERR_DIR_READ_FAILED = 58;
-
-        /** There are no more entries in the current directory */
-        public static final int ERR_DIR_NO_MORE_ENTRY = 59;
-
-        /** The input parameter/s has error */
-        public static final int ERR_PARAMETER = 60;
-
-        /** There is a state machine error */
-        public static final int ERR_STATE = 61;
-
-        /** Memory allocation failed */
-        public static final int ERR_ALLOC = 62;
-
-        /** Context is invalid */
-        public static final int ERR_BAD_CONTEXT = 63;
-
-        /** Context creation failed */
-        public static final int ERR_CONTEXT_FAILED = 64;
-
-        /** Invalid stream ID */
-        public static final int ERR_BAD_STREAM_ID = 65;
-
-        /** Invalid option ID */
-        public static final int ERR_BAD_OPTION_ID = 66;
-
-        /** The option is write only */
-        public static final int ERR_WRITE_ONLY = 67;
-
-        /** The option is read only */
-        public static final int ERR_READ_ONLY = 68;
-
-        /** The feature is not implemented in this version */
-        public static final int ERR_NOT_IMPLEMENTED = 69;
-
-        /** The media type is not supported */
-        public static final int ERR_UNSUPPORTED_MEDIA_TYPE = 70;
-
-        /** No data to be encoded */
-        public static final int WAR_NO_DATA_YET = 71;
-
-        /** No data to be decoded */
-        public static final int WAR_NO_MORE_STREAM = 72;
-
-        /** Time stamp is invalid */
-        public static final int WAR_INVALID_TIME = 73;
-
-        /** No more data to be decoded */
-        public static final int WAR_NO_MORE_AU = 74;
-
-        /** Semaphore timed out */
-        public static final int WAR_TIME_OUT = 75;
-
-        /** Memory buffer is full */
-        public static final int WAR_BUFFER_FULL = 76;
-
-        /** Server has asked for redirection */
-        public static final int WAR_REDIRECT = 77;
-
-        /** Too many streams in input */
-        public static final int WAR_TOO_MUCH_STREAMS = 78;
-
-        /** The file cannot be opened/ written into as it is locked */
-        public static final int ERR_FILE_LOCKED = 79;
-
-        /** The file access mode is invalid */
-        public static final int ERR_FILE_BAD_MODE_ACCESS = 80;
-
-        /** The file pointer points to an invalid location */
-        public static final int ERR_FILE_INVALID_POSITION = 81;
-
-        /** Invalid string */
-        public static final int ERR_STR_BAD_STRING = 94;
-
-        /** The input string cannot be converted */
-        public static final int ERR_STR_CONV_FAILED = 95;
-
-        /** The string size is too large */
-        public static final int ERR_STR_OVERFLOW = 96;
-
-        /** Bad string arguments */
-        public static final int ERR_STR_BAD_ARGS = 97;
-
-        /** The string value is larger than maximum size allowed */
-        public static final int WAR_STR_OVERFLOW = 98;
-
-        /** The string value is not present in this comparison operation */
-        public static final int WAR_STR_NOT_FOUND = 99;
-
-        /** The thread is not started */
-        public static final int ERR_THREAD_NOT_STARTED = 100;
-
-        /** Trancoding done warning */
-        public static final int WAR_TRANSCODING_DONE = 101;
-
-        /** Unsupported mediatype */
-        public static final int WAR_MEDIATYPE_NOT_SUPPORTED = 102;
-
-        /** Input file contains invalid/unsupported streams */
-        public static final int ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM = 103;
-
-        /** Invalid input file */
-        public static final int ERR_INVALID_INPUT_FILE = 104;
-
-        /** Invalid output video format */
-        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT = 105;
-
-        /** Invalid output video frame size */
-        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE = 106;
-
-        /** Invalid output video frame rate */
-        public static final int ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE = 107;
-
-        /** Invalid output audio format */
-        public static final int ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT = 108;
-
-        /** Invalid video frame size for H.263 */
-        public static final int ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263 = 109;
-
-        /** Invalid video frame rate for H.263 */
-        public static final int ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263 = 110;
-
-        /** invalid playback duration */
-        public static final int ERR_DURATION_IS_NULL = 111;
-
-        /** Invalid H.263 profile in file */
-        public static final int ERR_H263_FORBIDDEN_IN_MP4_FILE = 112;
-
-        /** Invalid AAC sampling frequency */
-        public static final int ERR_INVALID_AAC_SAMPLING_FREQUENCY = 113;
-
-        /** Audio conversion failure */
-        public static final int ERR_AUDIO_CONVERSION_FAILED = 114;
-
-        /** Invalid trim start and end times */
-        public static final int ERR_BEGIN_CUT_EQUALS_END_CUT = 115;
-
-        /** End time smaller than start time for trim */
-        public static final int ERR_END_CUT_SMALLER_THAN_BEGIN_CUT = 116;
-
-        /** Output file size is small */
-        public static final int ERR_MAXFILESIZE_TOO_SMALL = 117;
-
-        /** Output video bitrate is too low */
-        public static final int ERR_VIDEOBITRATE_TOO_LOW = 118;
-
-        /** Output audio bitrate is too low */
-        public static final int ERR_AUDIOBITRATE_TOO_LOW = 119;
-
-        /** Output video bitrate is too high */
-        public static final int ERR_VIDEOBITRATE_TOO_HIGH = 120;
-
-        /** Output audio bitrate is too high */
-        public static final int ERR_AUDIOBITRATE_TOO_HIGH = 121;
-
-        /** Output file size is too small */
-        public static final int ERR_OUTPUT_FILE_SIZE_TOO_SMALL = 122;
-
-        /** Unknown stream type */
-        public static final int ERR_READER_UNKNOWN_STREAM_TYPE = 123;
-
-        /** Invalid metadata in input stream */
-        public static final int WAR_READER_NO_METADATA = 124;
-
-        /** Invalid file reader info warning */
-        public static final int WAR_READER_INFORMATION_NOT_PRESENT = 125;
-
-        /** Warning to indicate the the writer is being stopped */
-        public static final int WAR_WRITER_STOP_REQ = 131;
-
-        /** Video decoder failed to provide frame for transcoding */
-        public static final int WAR_VIDEORENDERER_NO_NEW_FRAME = 132;
-
-        /** Video deblocking filter is not implemented */
-        public static final int WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED = 133;
-
-        /** H.263 decoder profile not supported */
-        public static final int ERR_DECODER_H263_PROFILE_NOT_SUPPORTED = 134;
-
-        /** The input file contains unsupported H.263 profile */
-        public static final int ERR_DECODER_H263_NOT_BASELINE = 135;
-
-        /** There is no more space to store the output file */
-        public static final int ERR_NOMORE_SPACE_FOR_FILE = 136;
-
-        /** Internal error. */
-        public static final int ERR_INTERNAL = 255;
-    }
-
-    /**
-     * Defines output video formats.
-     */
-    public final class VideoFormat {
-        /** No video present in output clip. Used to generate audio only clip */
-        public static final int NO_VIDEO = 0;
-
-        /** H263 video format. */
-        public static final int H263 = 1;
-
-        /** H264 video */
-        public static final int H264 = 2;
-
-        /** MPEG4 video format. */
-        public static final int MPEG4 = 3;
-
-        /** No transcoding. Output video format is same as input video format */
-        public static final int NULL_VIDEO = 254;
-
-        /** Unsupported video format. */
-        public static final int UNSUPPORTED = 255;
-    }
-
-    /** Defines video frame sizes. */
-    public final class VideoFrameSize {
-
-        public static final int SIZE_UNDEFINED = -1;
-
-        /** SQCIF 128 x 96 pixels. */
-        public static final int SQCIF = 0;
-
-        /** QQVGA 160 x 120 pixels. */
-        public static final int QQVGA = 1;
-
-        /** QCIF 176 x 144 pixels. */
-        public static final int QCIF = 2;
-
-        /** QVGA 320 x 240 pixels. */
-        public static final int QVGA = 3;
-
-        /** CIF 352 x 288 pixels. */
-        public static final int CIF = 4;
-
-        /** VGA 640 x 480 pixels. */
-        public static final int VGA = 5;
-
-        /** WVGA 800 X 480 pixels */
-        public static final int WVGA = 6;
-
-        /** NTSC 720 X 480 pixels */
-        public static final int NTSC = 7;
-
-        /** 640 x 360 */
-        public static final int nHD = 8;
-
-        /** 854 x 480 */
-        public static final int WVGA16x9 = 9;
-
-        /** 720p 1280 X 720 */
-        public static final int V720p = 10;
-
-        /** W720p 1080 x 720 */
-        public static final int W720p = 11;
-
-        /** S720p 960 x 720 */
-        public static final int S720p = 12;
-
-        /** 1080p 1920 x 1080 */
-        public static final int V1080p = 13;
-    }
-
-    /**
-     * Defines output video frame rates.
-     */
-    public final class VideoFrameRate {
-        /** Frame rate of 5 frames per second. */
-        public static final int FR_5_FPS = 0;
-
-        /** Frame rate of 7.5 frames per second. */
-        public static final int FR_7_5_FPS = 1;
-
-        /** Frame rate of 10 frames per second. */
-        public static final int FR_10_FPS = 2;
-
-        /** Frame rate of 12.5 frames per second. */
-        public static final int FR_12_5_FPS = 3;
-
-        /** Frame rate of 15 frames per second. */
-        public static final int FR_15_FPS = 4;
-
-        /** Frame rate of 20 frames per second. */
-        public static final int FR_20_FPS = 5;
-
-        /** Frame rate of 25 frames per second. */
-        public static final int FR_25_FPS = 6;
-
-        /** Frame rate of 30 frames per second. */
-        public static final int FR_30_FPS = 7;
-    }
-
-    /**
-     * Defines Video Effect Types.
-     */
-    public static class VideoEffect {
-
-        public static final int NONE = 0;
-
-        public static final int FADE_FROM_BLACK = 8;
-
-        public static final int FADE_TO_BLACK = 16;
-
-        public static final int EXTERNAL = 256;
-
-        public static final int BLACK_AND_WHITE = 257;
-
-        public static final int PINK = 258;
-
-        public static final int GREEN = 259;
-
-        public static final int SEPIA = 260;
-
-        public static final int NEGATIVE = 261;
-
-        public static final int FRAMING = 262;
-
-        public static final int TEXT = 263;
-
-        public static final int ZOOM_IN = 264;
-
-        public static final int ZOOM_OUT = 265;
-
-        public static final int FIFTIES = 266;
-
-        public static final int COLORRGB16 = 267;
-
-        public static final int GRADIENT = 268;
-    }
-
-    /**
-     * Defines the video transitions.
-     */
-    public static class VideoTransition {
-        /** No transition */
-        public static final int NONE = 0;
-
-        /** Cross fade transition */
-        public static final int CROSS_FADE = 1;
-
-        /** External transition. Currently not available. */
-        public static final int EXTERNAL = 256;
-
-        /** AlphaMagic transition. */
-        public static final int ALPHA_MAGIC = 257;
-
-        /** Slide transition. */
-        public static final int SLIDE_TRANSITION = 258;
-
-        /** Fade to black transition. */
-        public static final int FADE_BLACK = 259;
-    }
-
-    /**
-     * Defines settings for the AlphaMagic transition
-     */
-    public static class AlphaMagicSettings {
-        /** Name of the alpha file (JPEG file). */
-        public String file;
-
-        /** Blending percentage [0..100] 0 = no blending. */
-        public int blendingPercent;
-
-        /** Invert the default rotation direction of the AlphaMagic effect. */
-        public boolean invertRotation;
-
-        public int rgbWidth;
-        public int rgbHeight;
-    }
-
-    /** Defines the direction of the Slide transition. */
-    public static final class SlideDirection {
-
-        /** Right out left in. */
-        public static final int RIGHT_OUT_LEFT_IN = 0;
-
-        /** Left out right in. */
-        public static final int LEFT_OUT_RIGTH_IN = 1;
-
-        /** Top out bottom in. */
-        public static final int TOP_OUT_BOTTOM_IN = 2;
-
-        /** Bottom out top in */
-        public static final int BOTTOM_OUT_TOP_IN = 3;
-    }
-
-    /** Defines the Slide transition settings. */
-    public static class SlideTransitionSettings {
-        /**
-         * Direction of the slide transition. See {@link SlideDirection
-         * SlideDirection} for valid values.
-         */
-        public int direction;
-    }
-
-    /**
-     * Defines the settings of a single clip.
-     */
-    public static class ClipSettings {
-
-        /**
-         * The path to the clip file.
-         * <p>
-         * File format of the clip, it can be:
-         * <ul>
-         * <li>3GP file containing MPEG4/H263/H264 video and AAC/AMR audio
-         * <li>JPG file
-         * </ul>
-         */
-
-        public String clipPath;
-
-        /**
-         * The path of the decoded file. This is used only for image files.
-         */
-        public String clipDecodedPath;
-
-        /**
-         * The path of the Original file. This is used only for image files.
-         */
-        public String clipOriginalPath;
-
-        /**
-         * File type of the clip. See {@link FileType FileType} for valid
-         * values.
-         */
-        public int fileType;
-
-        /** Begin of the cut in the clip in milliseconds. */
-        public int beginCutTime;
-
-        /**
-         * End of the cut in the clip in milliseconds. Set both
-         * <code>beginCutTime</code> and <code>endCutTime</code> to
-         * <code>0</code> to get the full length of the clip without a cut. In
-         * case of JPG clip, this is the duration of the JPEG file.
-         */
-        public int endCutTime;
-
-        /**
-         * Begin of the cut in the clip in percentage of the file duration.
-         */
-        public int beginCutPercent;
-
-        /**
-         * End of the cut in the clip in percentage of the file duration. Set
-         * both <code>beginCutPercent</code> and <code>endCutPercent</code> to
-         * <code>0</code> to get the full length of the clip without a cut.
-         */
-        public int endCutPercent;
-
-        /** Enable panning and zooming. */
-        public boolean panZoomEnabled;
-
-        /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
-        public int panZoomPercentStart;
-
-        /** Top left X coordinate at start of clip. */
-        public int panZoomTopLeftXStart;
-
-        /** Top left Y coordinate at start of clip. */
-        public int panZoomTopLeftYStart;
-
-        /** Zoom percentage at start of clip. 0 = no zoom, 100 = full zoom */
-        public int panZoomPercentEnd;
-
-        /** Top left X coordinate at end of clip. */
-        public int panZoomTopLeftXEnd;
-
-        /** Top left Y coordinate at end of clip. */
-        public int panZoomTopLeftYEnd;
-
-        /**
-         * Set The media rendering. See {@link MediaRendering MediaRendering}
-         * for valid values.
-         */
-        public int mediaRendering;
-
-        /**
-         * RGB width and Height
-         */
-         public int rgbWidth;
-         public int rgbHeight;
-         /**
-         * Video rotation degree.
-         */
-         public int rotationDegree;
-    }
-
-    /**
-     * Defines settings for a transition.
-     */
-    public static class TransitionSettings {
-
-        /** Duration of the transition in msec. */
-        public int duration;
-
-        /**
-         * Transition type for video. See {@link VideoTransition
-         * VideoTransition} for valid values.
-         */
-        public int videoTransitionType;
-
-        /**
-         * Transition type for audio. See {@link AudioTransition
-         * AudioTransition} for valid values.
-         */
-        public int audioTransitionType;
-
-        /**
-         * Transition behaviour. See {@link TransitionBehaviour
-         * TransitionBehaviour} for valid values.
-         */
-        public int transitionBehaviour;
-
-        /**
-         * Settings for AlphaMagic transition. Only needs to be set if
-         * <code>videoTransitionType</code> is set to
-         * <code>VideoTransition.ALPHA_MAGIC</code>. See
-         * {@link AlphaMagicSettings AlphaMagicSettings}.
-         */
-        public AlphaMagicSettings alphaSettings;
-
-        /**
-         * Settings for the Slide transition. See
-         * {@link SlideTransitionSettings SlideTransitionSettings}.
-         */
-        public SlideTransitionSettings slideSettings;
-    }
-
-    public static final class AudioTransition {
-        /** No audio transition. */
-        public static final int NONE = 0;
-
-        /** Cross-fade audio transition. */
-        public static final int CROSS_FADE = 1;
-    }
-
-    /**
-     * Defines transition behaviors.
-     */
-    public static final class TransitionBehaviour {
-
-        /** The transition uses an increasing speed. */
-        public static final int SPEED_UP = 0;
-
-        /** The transition uses a linear (constant) speed. */
-        public static final int LINEAR = 1;
-
-        /** The transition uses a decreasing speed. */
-        public static final int SPEED_DOWN = 2;
-
-        /**
-         * The transition uses a constant speed, but slows down in the middle
-         * section.
-         */
-        public static final int SLOW_MIDDLE = 3;
-
-        /**
-         * The transition uses a constant speed, but increases speed in the
-         * middle section.
-         */
-        public static final int FAST_MIDDLE = 4;
-    }
-
-    /**
-     * Defines settings for the background music.
-     */
-    public static class BackgroundMusicSettings {
-
-        /** Background music file. */
-        public String file;
-
-        /** File type. See {@link FileType FileType} for valid values. */
-        public int fileType;
-
-        /**
-         * Insertion time in milliseconds, in the output video where the
-         * background music must be inserted.
-         */
-        public long insertionTime;
-
-        /**
-         * Volume, as a percentage of the background music track, to use. If
-         * this field is set to 100, the background music will replace the audio
-         * from the video input file(s).
-         */
-        public int volumePercent;
-
-        /**
-         * Start time in milliseconds in the background muisc file from where
-         * the background music should loop. Set both <code>beginLoop</code> and
-         * <code>endLoop</code> to <code>0</code> to disable looping.
-         */
-        public long beginLoop;
-
-        /**
-         * End time in milliseconds in the background music file to where the
-         * background music should loop. Set both <code>beginLoop</code> and
-         * <code>endLoop</code> to <code>0</code> to disable looping.
-         */
-        public long endLoop;
-
-        public boolean enableDucking;
-
-        public int duckingThreshold;
-
-        public int lowVolume;
-
-        public boolean isLooping;
-    }
-
-    /** Defines settings for an effect. */
-    public static class AudioEffect {
-        /** No audio effect. */
-        public static final int NONE = 0;
-
-        /** Fade-in effect. */
-        public static final int FADE_IN = 8;
-
-        /** Fade-out effect. */
-        public static final int FADE_OUT = 16;
-    }
-
-    /** Defines the effect settings. */
-    public static class EffectSettings {
-
-        /** Start time of the effect in milliseconds. */
-        public int startTime;
-
-        /** Duration of the effect in milliseconds. */
-        public int duration;
-
-        /**
-         * Video effect type. See {@link VideoEffect VideoEffect} for valid
-         * values.
-         */
-        public int videoEffectType;
-
-        /**
-         * Audio effect type. See {@link AudioEffect AudioEffect} for valid
-         * values.
-         */
-        public int audioEffectType;
-
-        /**
-         * Start time of the effect in percents of the duration of the clip. A
-         * value of 0 percent means start time is from the beginning of the
-         * clip.
-         */
-        public int startPercent;
-
-        /**
-         * Duration of the effect in percents of the duration of the clip.
-         */
-        public int durationPercent;
-
-        /**
-         * Framing file.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
-         * this field is ignored.
-         */
-        public String framingFile;
-
-        /**
-         * Framing buffer.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
-         * this field is ignored.
-         */
-        public int[] framingBuffer;
-
-        /**
-         * Bitmap type Can be from RGB_565 (4), ARGB_4444 (5), ARGB_8888 (6);
-         **/
-
-        public int bitmapType;
-
-        public int width;
-
-        public int height;
-
-        /**
-         * Top left x coordinate. This coordinate is used to set the x
-         * coordinate of the picture in the framing file when the framing file
-         * is selected. The x coordinate is also used to set the location of the
-         * text in the text effect.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
-         * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
-         * ignored.
-         */
-        public int topLeftX;
-
-        /**
-         * Top left y coordinate. This coordinate is used to set the y
-         * coordinate of the picture in the framing file when the framing file
-         * is selected. The y coordinate is also used to set the location of the
-         * text in the text effect.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING} or
-         * {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this field is
-         * ignored.
-         */
-        public int topLeftY;
-
-        /**
-         * Should the frame be resized or not. If this field is set to
-         * <link>true</code> then the frame size is matched with the output
-         * video size.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise
-         * this field is ignored.
-         */
-        public boolean framingResize;
-
-        /**
-         * Size to which the framing buffer needs to be resized to
-         * This is valid only if framingResize is true
-         */
-        public int framingScaledSize;
-        /**
-         * Text to insert in the video.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
-         * field is ignored.
-         */
-        public String text;
-
-        /**
-         * Text attributes for the text to insert in the video.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT}. Otherwise this
-         * field is ignored. For more details about this field see the
-         * integration guide.
-         */
-        public String textRenderingData;
-
-        /** Width of the text buffer in pixels. */
-        public int textBufferWidth;
-
-        /** Height of the text buffer in pixels. */
-        public int textBufferHeight;
-
-        /**
-         * Processing rate for the fifties effect. A high value (e.g. 30)
-         * results in high effect strength.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#FIFTIES VideoEffect.FIFTIES}. Otherwise
-         * this field is ignored.
-         */
-        public int fiftiesFrameRate;
-
-        /**
-         * RGB 16 color of the RGB16 and gradient color effect.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#COLORRGB16 VideoEffect.COLORRGB16} or
-         * {@link VideoEffect#GRADIENT VideoEffect.GRADIENT}. Otherwise this
-         * field is ignored.
-         */
-        public int rgb16InputColor;
-
-        /**
-         * Start alpha blending percentage.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
-         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
-         * is ignored.
-         */
-        public int alphaBlendingStartPercent;
-
-        /**
-         * Middle alpha blending percentage.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
-         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
-         * is ignored.
-         */
-        public int alphaBlendingMiddlePercent;
-
-        /**
-         * End alpha blending percentage.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
-         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
-         * is ignored.
-         */
-        public int alphaBlendingEndPercent;
-
-        /**
-         * Duration, in percentage of effect duration of the fade-in phase.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
-         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
-         * is ignored.
-         */
-        public int alphaBlendingFadeInTimePercent;
-
-        /**
-         * Duration, in percentage of effect duration of the fade-out phase.
-         * <p>
-         * This field is only used when the field <code>videoEffectType</code>
-         * is set to {@link VideoEffect#TEXT VideoEffect.TEXT} or
-         * {@link VideoEffect#FRAMING VideoEffect.FRAMING}. Otherwise this field
-         * is ignored.
-         */
-        public int alphaBlendingFadeOutTimePercent;
-    }
-
-    /** Defines the clip properties for preview */
-    public static class PreviewClips {
-
-        /**
-         * The path to the clip file.
-         * <p>
-         * File format of the clip, it can be:
-         * <ul>
-         * <li>3GP file containing MPEG4/H263 video and AAC/AMR audio
-         * <li>JPG file
-         * </ul>
-         */
-
-        public String clipPath;
-
-        /**
-         * File type of the clip. See {@link FileType FileType} for valid
-         * values.
-         */
-        public int fileType;
-
-        /** Begin of the cut in the clip in milliseconds. */
-        public long beginPlayTime;
-
-        public long endPlayTime;
-
-        /**
-         * Set The media rendering. See {@link MediaRendering MediaRendering}
-         * for valid values.
-         */
-        public int mediaRendering;
-
-    }
-
-    /** Defines the audio settings. */
-    public static class AudioSettings {
-
-        String pFile;
-
-        /** < PCM file path */
-        String Id;
-
-        boolean bRemoveOriginal;
-
-        /** < If true, the original audio track is not taken into account */
-        int channels;
-
-        /** < Number of channels (1=mono, 2=stereo) of BGM clip */
-        int Fs;
-
-        /**
-         * < Sampling audio frequency (8000 for amr, 16000 or more for aac) of
-         * BGM clip
-         */
-        int ExtendedFs;
-
-        /** < Extended frequency for AAC+, eAAC+ streams of BGM clip */
-        long startMs;
-
-        /** < Time, in milliseconds, at which the added audio track is inserted */
-        long beginCutTime;
-
-        long endCutTime;
-
-        int fileType;
-
-        int volume;
-
-        /** < Volume, in percentage, of the added audio track */
-        boolean loop;
-
-        /** < Looping on/off > **/
-
-        /** Audio mix and Duck **/
-        int ducking_threshold;
-
-        int ducking_lowVolume;
-
-        boolean bInDucking_enable;
-
-        String pcmFilePath;
-    }
-
-    /** Encapsulates preview clips and effect settings */
-    public static class PreviewSettings {
-
-        public PreviewClips[] previewClipsArray;
-
-        /** The effect settings. */
-        public EffectSettings[] effectSettingsArray;
-
-    }
-
-    /** Encapsulates clip properties */
-    public static class PreviewClipProperties {
-
-        public Properties[] clipProperties;
-
-    }
-
-    /** Defines the editing settings. */
-    public static class EditSettings {
-
-        /**
-         * Array of clip settings. There is one <code>clipSetting</code> for
-         * each clip.
-         */
-        public ClipSettings[] clipSettingsArray;
-
-        /**
-         * Array of transition settings. If there are n clips (and thus n
-         * <code>clipSettings</code>) then there are (n-1) transitions and (n-1)
-         * <code>transistionSettings</code> in
-         * <code>transistionSettingsArray</code>.
-         */
-        public TransitionSettings[] transitionSettingsArray;
-
-        /** The effect settings. */
-        public EffectSettings[] effectSettingsArray;
-
-        /**
-         * Video frame rate of the output clip. See {@link VideoFrameRate
-         * VideoFrameRate} for valid values.
-         */
-        public int videoFrameRate;
-
-        /** Output file name. Must be an absolute path. */
-        public String outputFile;
-
-        /**
-         * Size of the video frames in the output clip. See
-         * {@link VideoFrameSize VideoFrameSize} for valid values.
-         */
-        public int videoFrameSize;
-
-        /**
-         * Format of the video stream in the output clip. See
-         * {@link VideoFormat VideoFormat} for valid values.
-         */
-        public int videoFormat;
-
-        /**
-         * Profile of the video stream in the output clip.
-         */
-        public int videoProfile;
-
-        /**
-         * Level of the video stream in the output clip.
-         */
-        public int videoLevel;
-
-        /**
-         * Format of the audio stream in the output clip. See
-         * {@link AudioFormat AudioFormat} for valid values.
-         */
-        public int audioFormat;
-
-        /**
-         * Sampling frequency of the audio stream in the output clip. See
-         * {@link AudioSamplingFrequency AudioSamplingFrequency} for valid
-         * values.
-         */
-        public int audioSamplingFreq;
-
-        /**
-         * Maximum file size. By setting this you can set the maximum size of
-         * the output clip. Set it to <code>0</code> to let the class ignore
-         * this filed.
-         */
-        public int maxFileSize;
-
-        /**
-         * Number of audio channels in output clip. Use <code>0</code> for none,
-         * <code>1</code> for mono or <code>2</code> for stereo. None is only
-         * allowed when the <code>audioFormat</code> field is set to
-         * {@link AudioFormat#NO_AUDIO AudioFormat.NO_AUDIO} or
-         * {@link AudioFormat#NULL_AUDIO AudioFormat.NULL_AUDIO} Mono is only
-         * allowed when the <code>audioFormat</code> field is set to
-         * {@link AudioFormat#AAC AudioFormat.AAC}
-         */
-        public int audioChannels;
-
-        /** Video bitrate. See {@link Bitrate Bitrate} for valid values. */
-        public int videoBitrate;
-
-        /** Audio bitrate. See {@link Bitrate Bitrate} for valid values. */
-        public int audioBitrate;
-
-        /**
-         * Background music settings. See {@link BackgroundMusicSettings
-         * BackgroundMusicSettings} for valid values.
-         */
-        public BackgroundMusicSettings backgroundMusicSettings;
-
-        public int primaryTrackVolume;
-
-    }
-
-    /**
-     * Defines the media properties.
-     **/
-
-    public static class Properties {
-
-        /**
-         * Duration of the media in milliseconds.
-         */
-
-        public int duration;
-
-        /**
-         * File type.
-         */
-
-        public int fileType;
-
-        /**
-         * Video format.
-         */
-
-        public int videoFormat;
-
-        /**
-         * Duration of the video stream of the media in milliseconds.
-         */
-
-        public int videoDuration;
-
-        /**
-         * Bitrate of the video stream of the media.
-         */
-
-        public int videoBitrate;
-
-        /**
-         * Width of the video frames or the width of the still picture in
-         * pixels.
-         */
-
-        public int width;
-
-        /**
-         * Height of the video frames or the height of the still picture in
-         * pixels.
-         */
-
-        public int height;
-
-        /**
-         * Average frame rate of video in the media in frames per second.
-         */
-
-        public float averageFrameRate;
-
-        /**
-         * Profile of the video in the media.
-         */
-
-        public int profile;
-
-        /**
-         * Level of the video in the media.
-         */
-
-        public int level;
-
-        /**
-         * Is Video Profile supported.
-         */
-
-        public boolean profileSupported;
-
-        /**
-         * Is Video Level supported.
-         */
-
-        public boolean levelSupported;
-
-        /**
-         * Audio format.
-         */
-
-        public int audioFormat;
-
-        /**
-         * Duration of the audio stream of the media in milliseconds.
-         */
-
-        public int audioDuration;
-
-        /**
-         * Bitrate of the audio stream of the media.
-         */
-
-        public int audioBitrate;
-
-        /**
-         * Number of audio channels in the media.
-         */
-
-        public int audioChannels;
-
-        /**
-         * Sampling frequency of the audio stream in the media in samples per
-         * second.
-         */
-
-        public int audioSamplingFrequency;
-
-        /**
-         * Volume value of the audio track as percentage.
-         */
-        public int audioVolumeValue;
-
-        /**
-         * Video rotation degree.
-         */
-        public int videoRotation;
-
-        public String Id;
-    }
-
-    /**
-     * Constructor
-     *
-     * @param projectPath The path where the VideoEditor stores all files
-     *        related to the project
-     * @param lock The semaphore
-     * @param veObj The video editor reference
-     */
-    public MediaArtistNativeHelper(String projectPath, Semaphore lock, VideoEditor veObj) {
-        mProjectPath = projectPath;
-        if (veObj != null) {
-            mVideoEditor = veObj;
-        } else {
-            mVideoEditor = null;
-            throw new IllegalArgumentException("video editor object is null");
-        }
-        if (mStoryBoardSettings == null) {
-            mStoryBoardSettings = new EditSettings();
-        }
-
-        mLock = lock;
-
-        _init(mProjectPath, "null");
-        mAudioTrackPCMFilePath = null;
-    }
-
-    /**
-     * @return The project path
-     */
-    String getProjectPath() {
-        return mProjectPath;
-    }
-
-    /**
-     * @return The Audio Track PCM file path
-     */
-    String getProjectAudioTrackPCMFilePath() {
-        return mAudioTrackPCMFilePath;
-    }
-
-    /**
-     * Invalidates the PCM file
-     */
-    void invalidatePcmFile() {
-        if (mAudioTrackPCMFilePath != null) {
-            new File(mAudioTrackPCMFilePath).delete();
-            mAudioTrackPCMFilePath = null;
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private void onProgressUpdate(int taskId, int progress) {
-        if (mProcessingState == PROCESSING_EXPORT) {
-            if (mExportProgressListener != null) {
-                if (mProgressToApp < progress) {
-                    mExportProgressListener.onProgress(mVideoEditor, mOutputFilename, progress);
-                    /* record previous progress */
-                    mProgressToApp = progress;
-                }
-            }
-        }
-        else {
-            // Adapt progress depending on current state
-            int actualProgress = 0;
-            int action = 0;
-
-            if (mProcessingState == PROCESSING_AUDIO_PCM) {
-                action = MediaProcessingProgressListener.ACTION_DECODE;
-            } else {
-                action = MediaProcessingProgressListener.ACTION_ENCODE;
-            }
-
-            switch (mProcessingState) {
-                case PROCESSING_AUDIO_PCM:
-                    actualProgress = progress;
-                    break;
-                case PROCESSING_TRANSITION:
-                    actualProgress = progress;
-                    break;
-                case PROCESSING_KENBURNS:
-                    actualProgress = progress;
-                    break;
-                case PROCESSING_INTERMEDIATE1:
-                    if ((progress == 0) && (mProgressToApp != 0)) {
-                        mProgressToApp = 0;
-                    }
-                    if ((progress != 0) || (mProgressToApp != 0)) {
-                        actualProgress = progress/4;
-                    }
-                    break;
-                case PROCESSING_INTERMEDIATE2:
-                    if ((progress != 0) || (mProgressToApp != 0)) {
-                        actualProgress = 25 + progress/4;
-                    }
-                    break;
-                case PROCESSING_INTERMEDIATE3:
-                    if ((progress != 0) || (mProgressToApp != 0)) {
-                        actualProgress = 50 + progress/2;
-                    }
-                    break;
-                case PROCESSING_NONE:
-
-                default:
-                    Log.e(TAG, "ERROR unexpected State=" + mProcessingState);
-                    return;
-            }
-            if ((mProgressToApp != actualProgress) && (actualProgress != 0)) {
-
-                mProgressToApp = actualProgress;
-
-                if (mMediaProcessingProgressListener != null) {
-                    // Send the progress indication
-                    mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
-                                                                actualProgress);
-                }
-            }
-            /* avoid 0 in next intermediate call */
-            if (mProgressToApp == 0) {
-                if (mMediaProcessingProgressListener != null) {
-                    /*
-                     *  Send the progress indication
-                     */
-                    mMediaProcessingProgressListener.onProgress(mProcessingObject, action,
-                                                                actualProgress);
-                }
-                mProgressToApp = 1;
-            }
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private void onPreviewProgressUpdate(int progress, boolean isFinished,
-                  boolean updateOverlay, String filename, int renderingMode, int error) {
-        if (mPreviewProgressListener != null) {
-            if (mIsFirstProgress) {
-                mPreviewProgressListener.onStart(mVideoEditor);
-                mIsFirstProgress = false;
-            }
-
-            final VideoEditor.OverlayData overlayData;
-            if (updateOverlay) {
-                overlayData = new VideoEditor.OverlayData();
-                if (filename != null) {
-                    overlayData.set(BitmapFactory.decodeFile(filename), renderingMode);
-                } else {
-                    overlayData.setClear();
-                }
-            } else {
-                overlayData = null;
-            }
-
-            if (progress != 0) {
-                mPreviewProgress = progress;
-            }
-
-            if (isFinished) {
-                mPreviewProgressListener.onStop(mVideoEditor);
-            } else if (error != 0) {
-                mPreviewProgressListener.onError(mVideoEditor, error);
-            } else {
-                mPreviewProgressListener.onProgress(mVideoEditor, progress, overlayData);
-            }
-        }
-    }
-
-    /**
-     * Release the native helper object
-     */
-    void releaseNativeHelper() throws InterruptedException {
-        release();
-    }
-
-    /**
-     * Release the native helper to end the Audio Graph process
-     */
-    @SuppressWarnings("unused")
-    private void onAudioGraphExtractProgressUpdate(int progress, boolean isVideo) {
-        if ((mExtractAudioWaveformProgressListener != null) && (progress > 0)) {
-            mExtractAudioWaveformProgressListener.onProgress(progress);
-        }
-    }
-
-    /**
-     * Populates the Effect Settings in EffectSettings
-     *
-     * @param effects The reference of EffectColor
-     *
-     * @return The populated effect settings in EffectSettings reference
-     */
-    EffectSettings getEffectSettings(EffectColor effects) {
-        EffectSettings effectSettings = new EffectSettings();
-        effectSettings.startTime = (int)effects.getStartTime();
-        effectSettings.duration = (int)effects.getDuration();
-        effectSettings.videoEffectType = getEffectColorType(effects);
-        effectSettings.audioEffectType = 0;
-        effectSettings.startPercent = 0;
-        effectSettings.durationPercent = 0;
-        effectSettings.framingFile = null;
-        effectSettings.topLeftX = 0;
-        effectSettings.topLeftY = 0;
-        effectSettings.framingResize = false;
-        effectSettings.text = null;
-        effectSettings.textRenderingData = null;
-        effectSettings.textBufferWidth = 0;
-        effectSettings.textBufferHeight = 0;
-        if (effects.getType() == EffectColor.TYPE_FIFTIES) {
-            effectSettings.fiftiesFrameRate = 15;
-        } else {
-            effectSettings.fiftiesFrameRate = 0;
-        }
-
-        if ((effectSettings.videoEffectType == VideoEffect.COLORRGB16)
-                || (effectSettings.videoEffectType == VideoEffect.GRADIENT)) {
-            effectSettings.rgb16InputColor = effects.getColor();
-        }
-
-        effectSettings.alphaBlendingStartPercent = 0;
-        effectSettings.alphaBlendingMiddlePercent = 0;
-        effectSettings.alphaBlendingEndPercent = 0;
-        effectSettings.alphaBlendingFadeInTimePercent = 0;
-        effectSettings.alphaBlendingFadeOutTimePercent = 0;
-        return effectSettings;
-    }
-
-    /**
-     * Populates the Overlay Settings in EffectSettings
-     *
-     * @param overlay The reference of OverlayFrame
-     *
-     * @return The populated overlay settings in EffectSettings reference
-     */
-    EffectSettings getOverlaySettings(OverlayFrame overlay) {
-        EffectSettings effectSettings = new EffectSettings();
-        Bitmap bitmap = null;
-
-        effectSettings.startTime = (int)overlay.getStartTime();
-        effectSettings.duration = (int)overlay.getDuration();
-        effectSettings.videoEffectType = VideoEffect.FRAMING;
-        effectSettings.audioEffectType = 0;
-        effectSettings.startPercent = 0;
-        effectSettings.durationPercent = 0;
-        effectSettings.framingFile = null;
-
-        if ((bitmap = overlay.getBitmap()) != null) {
-            effectSettings.framingFile = overlay.getFilename();
-
-            if (effectSettings.framingFile == null) {
-                try {
-                    (overlay).save(mProjectPath);
-                } catch (IOException e) {
-                    Log.e(TAG, "getOverlaySettings : File not found");
-                }
-                effectSettings.framingFile = overlay.getFilename();
-            }
-            if (bitmap.getConfig() == Bitmap.Config.ARGB_8888)
-                effectSettings.bitmapType = 6;
-            else if (bitmap.getConfig() == Bitmap.Config.ARGB_4444)
-                effectSettings.bitmapType = 5;
-            else if (bitmap.getConfig() == Bitmap.Config.RGB_565)
-                effectSettings.bitmapType = 4;
-            else if (bitmap.getConfig() == Bitmap.Config.ALPHA_8)
-                throw new RuntimeException("Bitmap config not supported");
-
-            effectSettings.width = bitmap.getWidth();
-            effectSettings.height = bitmap.getHeight();
-            effectSettings.framingBuffer = new int[effectSettings.width];
-            int tmp = 0;
-            short maxAlpha = 0;
-            short minAlpha = (short)0xFF;
-            short alpha = 0;
-            while (tmp < effectSettings.height) {
-                bitmap.getPixels(effectSettings.framingBuffer, 0,
-                                 effectSettings.width, 0, tmp,
-                                 effectSettings.width, 1);
-                for (int i = 0; i < effectSettings.width; i++) {
-                    alpha = (short)((effectSettings.framingBuffer[i] >> 24) & 0xFF);
-                    if (alpha > maxAlpha) {
-                        maxAlpha = alpha;
-                    }
-                    if (alpha < minAlpha) {
-                        minAlpha = alpha;
-                    }
-                }
-                tmp += 1;
-            }
-            alpha = (short)((maxAlpha + minAlpha) / 2);
-            alpha = (short)((alpha * 100) / 256);
-            effectSettings.alphaBlendingEndPercent = alpha;
-            effectSettings.alphaBlendingMiddlePercent = alpha;
-            effectSettings.alphaBlendingStartPercent = alpha;
-            effectSettings.alphaBlendingFadeInTimePercent = 100;
-            effectSettings.alphaBlendingFadeOutTimePercent = 100;
-            effectSettings.framingBuffer = null;
-
-            /*
-             * Set the resized RGB file dimensions
-             */
-            effectSettings.width = overlay.getResizedRGBSizeWidth();
-            if(effectSettings.width == 0) {
-                effectSettings.width = bitmap.getWidth();
-            }
-
-            effectSettings.height = overlay.getResizedRGBSizeHeight();
-            if(effectSettings.height == 0) {
-                effectSettings.height = bitmap.getHeight();
-            }
-
-        }
-
-        effectSettings.topLeftX = 0;
-        effectSettings.topLeftY = 0;
-
-        effectSettings.framingResize = true;
-        effectSettings.text = null;
-        effectSettings.textRenderingData = null;
-        effectSettings.textBufferWidth = 0;
-        effectSettings.textBufferHeight = 0;
-        effectSettings.fiftiesFrameRate = 0;
-        effectSettings.rgb16InputColor = 0;
-        int mediaItemHeight;
-        int aspectRatio;
-        if (overlay.getMediaItem() instanceof MediaImageItem) {
-            if (((MediaImageItem)overlay.getMediaItem()).getGeneratedImageClip() != null) {
-                // Ken Burns was applied
-                mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipHeight();
-                aspectRatio = getAspectRatio(
-                    ((MediaImageItem)overlay.getMediaItem()).getGeneratedClipWidth()
-                    , mediaItemHeight);
-            } else {
-                //For image get the scaled height. Aspect ratio would remain the same
-                mediaItemHeight = ((MediaImageItem)overlay.getMediaItem()).getScaledHeight();
-                aspectRatio = overlay.getMediaItem().getAspectRatio();
-            }
-        } else {
-            aspectRatio = overlay.getMediaItem().getAspectRatio();
-            mediaItemHeight = overlay.getMediaItem().getHeight();
-        }
-        effectSettings.framingScaledSize = findVideoResolution(aspectRatio, mediaItemHeight);
-        return effectSettings;
-    }
-
-     /* get Video Editor aspect ratio */
-    int nativeHelperGetAspectRatio() {
-        return mVideoEditor.getAspectRatio();
-    }
-
-    /**
-     * Sets the export audio codec
-     *
-     * @param export audio codec
-     *
-     */
-    void setAudioCodec(int codec) {
-        mExportAudioCodec = codec;
-    }
-    /**
-     * Sets the export video codec
-     *
-     * @param export video codec
-     *
-     */
-    void setVideoCodec(int codec) {
-        mExportVideoCodec = codec;
-    }
-
-    /**
-     * Sets the audio regenerate flag
-     *
-     * @param flag The boolean to set the audio regenerate flag
-     *
-     */
-    void setAudioflag(boolean flag) {
-        //check if the file exists.
-        if (!(new File(String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE)).exists())) {
-            flag = true;
-        }
-        mRegenerateAudio = flag;
-    }
-
-    /**
-     * Gets the audio regenerate flag
-     *
-     * @param return The boolean to get the audio regenerate flag
-     *
-     */
-    boolean getAudioflag() {
-        return mRegenerateAudio;
-    }
-
-    /**
-     * Maps the average frame rate to one of the defined enum values
-     *
-     * @param averageFrameRate The average frame rate of video item
-     *
-     * @return The frame rate from one of the defined enum values
-     */
-    int GetClosestVideoFrameRate(int averageFrameRate) {
-        if (averageFrameRate >= 25) {
-            return VideoFrameRate.FR_30_FPS;
-        } else if (averageFrameRate >= 20) {
-            return VideoFrameRate.FR_25_FPS;
-        } else if (averageFrameRate >= 15) {
-            return VideoFrameRate.FR_20_FPS;
-        } else if (averageFrameRate >= 12) {
-            return VideoFrameRate.FR_15_FPS;
-        } else if (averageFrameRate >= 10) {
-            return VideoFrameRate.FR_12_5_FPS;
-        } else if (averageFrameRate >= 7) {
-            return VideoFrameRate.FR_10_FPS;
-        } else if (averageFrameRate >= 5) {
-            return VideoFrameRate.FR_7_5_FPS;
-        } else {
-            return -1;
-        }
-    }
-
-    /**
-     * Helper function to adjust the effect or overlay start time
-     * depending on the begin and end boundary time of meddia item
-     */
-    public void adjustEffectsStartTimeAndDuration(EffectSettings lEffect, int beginCutTime,
-                                                  int endCutTime) {
-
-        int effectStartTime = 0;
-        int effectDuration = 0;
-
-        /**
-         * cbct -> clip begin cut time
-         * cect -> clip end cut time
-         ****************************************
-         *  |                                 |
-         *  |         cbct        cect        |
-         *  | <-1-->   |           |          |
-         *  |       <--|-2->       |          |
-         *  |          | <---3---> |          |
-         *  |          |        <--|-4--->    |
-         *  |          |           | <--5-->  |
-         *  |      <---|------6----|---->     |
-         *  |                                 |
-         *  < : effectStart
-         *  > : effectStart + effectDuration
-         ****************************************
-         **/
-
-        /** 1 & 5 */
-        /**
-         * Effect falls out side the trim duration. In such a case effects shall
-         * not be applied.
-         */
-        if ((lEffect.startTime > endCutTime)
-                || ((lEffect.startTime + lEffect.duration) <= beginCutTime)) {
-
-            effectStartTime = 0;
-            effectDuration = 0;
-
-            lEffect.startTime = effectStartTime;
-            lEffect.duration = effectDuration;
-            return;
-        }
-
-        /** 2 */
-        if ((lEffect.startTime < beginCutTime)
-                && ((lEffect.startTime + lEffect.duration) > beginCutTime)
-                && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
-            effectStartTime = 0;
-            effectDuration = lEffect.duration;
-
-            effectDuration -= (beginCutTime - lEffect.startTime);
-            lEffect.startTime = effectStartTime;
-            lEffect.duration = effectDuration;
-            return;
-        }
-
-        /** 3 */
-        if ((lEffect.startTime >= beginCutTime)
-                && ((lEffect.startTime + lEffect.duration) <= endCutTime)) {
-            effectStartTime = lEffect.startTime - beginCutTime;
-            lEffect.startTime = effectStartTime;
-            lEffect.duration = lEffect.duration;
-            return;
-        }
-
-        /** 4 */
-        if ((lEffect.startTime >= beginCutTime)
-                && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
-            effectStartTime = lEffect.startTime - beginCutTime;
-            effectDuration = endCutTime - lEffect.startTime;
-            lEffect.startTime = effectStartTime;
-            lEffect.duration = effectDuration;
-            return;
-        }
-
-        /** 6 */
-        if ((lEffect.startTime < beginCutTime)
-                && ((lEffect.startTime + lEffect.duration) > endCutTime)) {
-            effectStartTime = 0;
-            effectDuration = endCutTime - beginCutTime;
-            lEffect.startTime = effectStartTime;
-            lEffect.duration = effectDuration;
-            return;
-        }
-
-    }
-
-    /**
-     * Generates the clip for preview or export
-     *
-     * @param editSettings The EditSettings reference for generating
-     * a clip for preview or export
-     *
-     * @return error value
-     */
-    public int generateClip(EditSettings editSettings) {
-        int err = 0;
-
-        try {
-            err = nativeGenerateClip(editSettings);
-        } catch (IllegalArgumentException ex) {
-            Log.e(TAG, "Illegal Argument exception in load settings");
-            return -1;
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "Illegal state exception in load settings");
-            return -1;
-        } catch (RuntimeException ex) {
-            Log.e(TAG, "Runtime exception in load settings");
-            return -1;
-        }
-        return err;
-    }
-
-    /**
-     * Init function to initialiZe the  ClipSettings reference to
-     * default values
-     *
-     * @param lclipSettings The ClipSettings reference
-     */
-    void initClipSettings(ClipSettings lclipSettings) {
-        lclipSettings.clipPath = null;
-        lclipSettings.clipDecodedPath = null;
-        lclipSettings.clipOriginalPath = null;
-        lclipSettings.fileType = 0;
-        lclipSettings.endCutTime = 0;
-        lclipSettings.beginCutTime = 0;
-        lclipSettings.beginCutPercent = 0;
-        lclipSettings.endCutPercent = 0;
-        lclipSettings.panZoomEnabled = false;
-        lclipSettings.panZoomPercentStart = 0;
-        lclipSettings.panZoomTopLeftXStart = 0;
-        lclipSettings.panZoomTopLeftYStart = 0;
-        lclipSettings.panZoomPercentEnd = 0;
-        lclipSettings.panZoomTopLeftXEnd = 0;
-        lclipSettings.panZoomTopLeftYEnd = 0;
-        lclipSettings.mediaRendering = 0;
-        lclipSettings.rotationDegree = 0;
-    }
-
-
-    /**
-     * Populates the settings for generating an effect clip
-     *
-     * @param lMediaItem The media item for which the effect clip
-     * needs to be generated
-     * @param lclipSettings The ClipSettings reference containing
-     * clips data
-     * @param e The EditSettings reference containing effect specific data
-     * @param uniqueId The unique id used in the name of the output clip
-     * @param clipNo Used for internal purpose
-     *
-     * @return The name and path of generated clip
-     */
-    String generateEffectClip(MediaItem lMediaItem, ClipSettings lclipSettings,
-            EditSettings e,String uniqueId,int clipNo) {
-        int err = 0;
-        EditSettings editSettings = null;
-        String EffectClipPath = null;
-        int outVideoProfile = 0;
-        int outVideoLevel = 0;
-        editSettings = new EditSettings();
-
-        editSettings.clipSettingsArray = new ClipSettings[1];
-        editSettings.clipSettingsArray[0] = lclipSettings;
-
-        editSettings.backgroundMusicSettings = null;
-        editSettings.transitionSettingsArray = null;
-        editSettings.effectSettingsArray = e.effectSettingsArray;
-
-        EffectClipPath = String.format(mProjectPath + "/" + "ClipEffectIntermediate" + "_"
-                + lMediaItem.getId() + uniqueId + ".3gp");
-
-        File tmpFile = new File(EffectClipPath);
-        if (tmpFile.exists()) {
-            tmpFile.delete();
-        }
-
-        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
-        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
-        editSettings.videoProfile = outVideoProfile;
-        editSettings.videoLevel= outVideoLevel;
-
-        if (lMediaItem instanceof MediaVideoItem) {
-            MediaVideoItem m = (MediaVideoItem)lMediaItem;
-
-            editSettings.audioFormat = AudioFormat.AAC;
-            editSettings.audioChannels = 2;
-            editSettings.audioBitrate = Bitrate.BR_64_KBPS;
-            editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
-            editSettings.videoFormat = VideoFormat.H264;
-            editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
-            editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
-                    m.getHeight());
-            editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
-        } else {
-            MediaImageItem m = (MediaImageItem)lMediaItem;
-            editSettings.audioBitrate = Bitrate.BR_64_KBPS;
-            editSettings.audioChannels = 2;
-            editSettings.audioFormat = AudioFormat.AAC;
-            editSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
-            editSettings.videoFormat = VideoFormat.H264;
-            editSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
-            editSettings.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
-                    m.getScaledHeight());
-            editSettings.videoBitrate = findVideoBitrate(editSettings.videoFrameSize);
-        }
-
-        editSettings.outputFile = EffectClipPath;
-
-        if (clipNo == 1) {
-            mProcessingState  = PROCESSING_INTERMEDIATE1;
-        } else if (clipNo == 2) {
-            mProcessingState  = PROCESSING_INTERMEDIATE2;
-        }
-        mProcessingObject = lMediaItem;
-        err = generateClip(editSettings);
-        mProcessingState  = PROCESSING_NONE;
-
-        if (err == 0) {
-            lclipSettings.clipPath = EffectClipPath;
-            lclipSettings.fileType = FileType.THREE_GPP;
-            return EffectClipPath;
-        } else {
-            throw new RuntimeException("preview generation cannot be completed");
-        }
-    }
-
-
-    /**
-     * Populates the settings for generating a Ken Burn effect clip
-     *
-     * @param m The media image item for which the Ken Burn effect clip
-     * needs to be generated
-     * @param e The EditSettings reference clip specific data
-     *
-     * @return The name and path of generated clip
-     */
-    String generateKenBurnsClip(EditSettings e, MediaImageItem m) {
-        String output = null;
-        int err = 0;
-        int outVideoProfile = 0;
-        int outVideoLevel = 0;
-
-        e.backgroundMusicSettings = null;
-        e.transitionSettingsArray = null;
-        e.effectSettingsArray = null;
-        output = String.format(mProjectPath + "/" + "ImageClip-" + m.getId() + ".3gp");
-
-        File tmpFile = new File(output);
-        if (tmpFile.exists()) {
-            tmpFile.delete();
-        }
-
-        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
-        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
-        e.videoProfile = outVideoProfile;
-        e.videoLevel = outVideoLevel;
-
-        e.outputFile = output;
-        e.audioBitrate = Bitrate.BR_64_KBPS;
-        e.audioChannels = 2;
-        e.audioFormat = AudioFormat.AAC;
-        e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
-        e.videoFormat = VideoFormat.H264;
-        e.videoFrameRate = VideoFrameRate.FR_30_FPS;
-        e.videoFrameSize = findVideoResolution(mVideoEditor.getAspectRatio(),
-                                                           m.getScaledHeight());
-        e.videoBitrate = findVideoBitrate(e.videoFrameSize);
-
-        mProcessingState  = PROCESSING_KENBURNS;
-        mProcessingObject = m;
-        err = generateClip(e);
-        // Reset the processing state and check for errors
-        mProcessingState  = PROCESSING_NONE;
-        if (err != 0) {
-            throw new RuntimeException("preview generation cannot be completed");
-        }
-        return output;
-    }
-
-
-    /**
-     * Calculates the output resolution for transition clip
-     *
-     * @param m1 First media item associated with transition
-     * @param m2 Second media item associated with transition
-     *
-     * @return The transition resolution
-     */
-    private int getTransitionResolution(MediaItem m1, MediaItem m2) {
-        int clip1Height = 0;
-        int clip2Height = 0;
-        int videoSize = 0;
-
-        if (m1 != null && m2 != null) {
-            if (m1 instanceof MediaVideoItem) {
-                clip1Height = m1.getHeight();
-            } else if (m1 instanceof MediaImageItem) {
-                clip1Height = ((MediaImageItem)m1).getScaledHeight();
-            }
-            if (m2 instanceof MediaVideoItem) {
-                clip2Height = m2.getHeight();
-            } else if (m2 instanceof MediaImageItem) {
-                clip2Height = ((MediaImageItem)m2).getScaledHeight();
-            }
-            if (clip1Height > clip2Height) {
-                videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
-            } else {
-                videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
-            }
-        } else if (m1 == null && m2 != null) {
-            if (m2 instanceof MediaVideoItem) {
-                clip2Height = m2.getHeight();
-            } else if (m2 instanceof MediaImageItem) {
-                clip2Height = ((MediaImageItem)m2).getScaledHeight();
-            }
-            videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip2Height);
-        } else if (m1 != null && m2 == null) {
-            if (m1 instanceof MediaVideoItem) {
-                clip1Height = m1.getHeight();
-            } else if (m1 instanceof MediaImageItem) {
-                clip1Height = ((MediaImageItem)m1).getScaledHeight();
-            }
-            videoSize = findVideoResolution(mVideoEditor.getAspectRatio(), clip1Height);
-        }
-        return videoSize;
-    }
-
-    /**
-     * Populates the settings for generating an transition clip
-     *
-     * @param m1 First media item associated with transition
-     * @param m2 Second media item associated with transition
-     * @param e The EditSettings reference containing
-     * clip specific data
-     * @param uniqueId The unique id used in the name of the output clip
-     * @param t The Transition specific data
-     *
-     * @return The name and path of generated clip
-     */
-    String generateTransitionClip(EditSettings e, String uniqueId,
-            MediaItem m1, MediaItem m2,Transition t) {
-        String outputFilename = null;
-        int err = 0;
-        int outVideoProfile = 0;
-        int outVideoLevel = 0;
-        outputFilename = String.format(mProjectPath + "/" + uniqueId + ".3gp");
-
-        outVideoProfile = VideoEditorProfile.getExportProfile(VideoFormat.H264);
-        outVideoLevel = VideoEditorProfile.getExportLevel(VideoFormat.H264);
-        e.videoProfile = outVideoProfile;
-        e.videoLevel = outVideoLevel;
-
-        e.outputFile = outputFilename;
-        e.audioBitrate = Bitrate.BR_64_KBPS;
-        e.audioChannels = 2;
-        e.audioFormat = AudioFormat.AAC;
-        e.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-
-        e.videoFormat = VideoFormat.H264;
-        e.videoFrameRate = VideoFrameRate.FR_30_FPS;
-        e.videoFrameSize = getTransitionResolution(m1, m2);
-        e.videoBitrate = findVideoBitrate(e.videoFrameSize);
-
-        if (new File(outputFilename).exists()) {
-            new File(outputFilename).delete();
-        }
-        mProcessingState  = PROCESSING_INTERMEDIATE3;
-        mProcessingObject = t;
-        err = generateClip(e);
-        // Reset the processing state and check for errors
-        mProcessingState  = PROCESSING_NONE;
-        if (err != 0) {
-            throw new RuntimeException("preview generation cannot be completed");
-        }
-        return outputFilename;
-    }
-
-    /**
-     * Populates effects and overlays in EffectSettings structure
-     * and also adjust the start time and duration of effects and overlays
-     * w.r.t to total story board time
-     *
-     * @param m1 Media item associated with effect
-     * @param effectSettings The EffectSettings reference containing
-     *      effect specific data
-     * @param beginCutTime The begin cut time of the clip associated with effect
-     * @param endCutTime The end cut time of the clip associated with effect
-     * @param storyBoardTime The current story board time
-     *
-     * @return The updated index
-     */
-    private int populateEffects(MediaItem m, EffectSettings[] effectSettings, int i,
-            int beginCutTime, int endCutTime, int storyBoardTime) {
-
-        if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
-                && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
-            beginCutTime += m.getBeginTransition().getDuration();
-            endCutTime -= m.getEndTransition().getDuration();
-        } else if (m.getBeginTransition() == null && m.getEndTransition() != null
-                && m.getEndTransition().getDuration() > 0) {
-            endCutTime -= m.getEndTransition().getDuration();
-        } else if (m.getEndTransition() == null && m.getBeginTransition() != null
-                && m.getBeginTransition().getDuration() > 0) {
-            beginCutTime += m.getBeginTransition().getDuration();
-        }
-
-        final List<Effect> effects = m.getAllEffects();
-        final List<Overlay> overlays = m.getAllOverlays();
-
-        for (Overlay overlay : overlays) {
-            effectSettings[i] = getOverlaySettings((OverlayFrame)overlay);
-            adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
-            effectSettings[i].startTime += storyBoardTime;
-            i++;
-        }
-
-        for (Effect effect : effects) {
-            if (effect instanceof EffectColor) {
-                effectSettings[i] = getEffectSettings((EffectColor)effect);
-                adjustEffectsStartTimeAndDuration(effectSettings[i], beginCutTime, endCutTime);
-                effectSettings[i].startTime += storyBoardTime;
-                i++;
-            }
-        }
-
-        return i;
-    }
-
-    /**
-     * Adjusts the media item boundaries for use in export or preview
-     *
-     * @param clipSettings The ClipSettings reference
-     * @param clipProperties The Properties reference
-     * @param m The media item
-     */
-    private void adjustMediaItemBoundary(ClipSettings clipSettings,
-                                         Properties clipProperties, MediaItem m) {
-        if (m.getBeginTransition() != null && m.getBeginTransition().getDuration() > 0
-                && m.getEndTransition() != null && m.getEndTransition().getDuration() > 0) {
-            clipSettings.beginCutTime += m.getBeginTransition().getDuration();
-            clipSettings.endCutTime -= m.getEndTransition().getDuration();
-        } else if (m.getBeginTransition() == null && m.getEndTransition() != null
-                && m.getEndTransition().getDuration() > 0) {
-            clipSettings.endCutTime -= m.getEndTransition().getDuration();
-        } else if (m.getEndTransition() == null && m.getBeginTransition() != null
-                && m.getBeginTransition().getDuration() > 0) {
-            clipSettings.beginCutTime += m.getBeginTransition().getDuration();
-        }
-
-        clipProperties.duration = clipSettings.endCutTime - clipSettings.beginCutTime;
-
-        if (clipProperties.videoDuration != 0) {
-            clipProperties.videoDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
-        }
-
-        if (clipProperties.audioDuration != 0) {
-            clipProperties.audioDuration = clipSettings.endCutTime - clipSettings.beginCutTime;
-        }
-    }
-
-    /**
-     * Generates the transition if transition is present
-     * and is in invalidated state
-     *
-     * @param transition The Transition reference
-     * @param editSettings The EditSettings reference
-     * @param clipPropertiesArray The clip Properties array
-     * @param i The index in clip Properties array for current clip
-     */
-    private void generateTransition(Transition transition, EditSettings editSettings,
-            PreviewClipProperties clipPropertiesArray, int index) {
-        if (!(transition.isGenerated())) {
-            transition.generate();
-        }
-        editSettings.clipSettingsArray[index] = new ClipSettings();
-        editSettings.clipSettingsArray[index].clipPath = transition.getFilename();
-        editSettings.clipSettingsArray[index].fileType = FileType.THREE_GPP;
-        editSettings.clipSettingsArray[index].beginCutTime = 0;
-        editSettings.clipSettingsArray[index].endCutTime = (int)transition.getDuration();
-        editSettings.clipSettingsArray[index].mediaRendering = MediaRendering.BLACK_BORDERS;
-
-        try {
-            clipPropertiesArray.clipProperties[index] =
-                getMediaProperties(transition.getFilename());
-        } catch (Exception e) {
-            throw new IllegalArgumentException("Unsupported file or file not found");
-        }
-
-        clipPropertiesArray.clipProperties[index].Id = null;
-        clipPropertiesArray.clipProperties[index].audioVolumeValue = 100;
-        clipPropertiesArray.clipProperties[index].duration = (int)transition.getDuration();
-        if (clipPropertiesArray.clipProperties[index].videoDuration != 0) {
-            clipPropertiesArray.clipProperties[index].videoDuration = (int)transition.getDuration();
-        }
-
-        if (clipPropertiesArray.clipProperties[index].audioDuration != 0) {
-            clipPropertiesArray.clipProperties[index].audioDuration = (int)transition.getDuration();
-        }
-    }
-
-    /**
-     * Sets the volume for current media item in clip properties array
-     *
-     * @param m The media item
-     * @param clipProperties The clip properties array reference
-     * @param i The index in clip Properties array for current clip
-     */
-    private void adjustVolume(MediaItem m, PreviewClipProperties clipProperties,
-                              int index) {
-        if (m instanceof MediaVideoItem) {
-            final boolean videoMuted = ((MediaVideoItem)m).isMuted();
-            if (videoMuted == false) {
-                mClipProperties.clipProperties[index].audioVolumeValue =
-                    ((MediaVideoItem)m).getVolume();
-            } else {
-                mClipProperties.clipProperties[index].audioVolumeValue = 0;
-            }
-        } else if (m instanceof MediaImageItem) {
-            mClipProperties.clipProperties[index].audioVolumeValue = 0;
-        }
-    }
-
-    /**
-     * Checks for odd size image width and height
-     *
-     * @param m The media item
-     * @param clipProperties The clip properties array reference
-     * @param i The index in clip Properties array for current clip
-     */
-    private void checkOddSizeImage(MediaItem m, PreviewClipProperties clipProperties, int index) {
-        if (m instanceof MediaImageItem) {
-            int width = mClipProperties.clipProperties[index].width;
-            int height = mClipProperties.clipProperties[index].height;
-
-            if ((width % 2) != 0) {
-                width -= 1;
-            }
-            if ((height % 2) != 0) {
-                height -= 1;
-            }
-            mClipProperties.clipProperties[index].width = width;
-            mClipProperties.clipProperties[index].height = height;
-        }
-    }
-
-    /**
-     * Populates the media item properties and calculates the maximum
-     * height among all the clips
-     *
-     * @param m The media item
-     * @param i The index in clip Properties array for current clip
-     * @param maxHeight The max height from the clip properties
-     *
-     * @return Updates the max height if current clip's height is greater
-     * than all previous clips height
-     */
-    private int populateMediaItemProperties(MediaItem m, int index, int maxHeight) {
-        mPreviewEditSettings.clipSettingsArray[index] = new ClipSettings();
-        if (m instanceof MediaVideoItem) {
-            mPreviewEditSettings.clipSettingsArray[index] =
-                ((MediaVideoItem)m).getVideoClipProperties();
-            if (((MediaVideoItem)m).getHeight() > maxHeight) {
-                maxHeight = ((MediaVideoItem)m).getHeight();
-            }
-        } else if (m instanceof MediaImageItem) {
-            mPreviewEditSettings.clipSettingsArray[index] =
-                ((MediaImageItem)m).getImageClipProperties();
-            if (((MediaImageItem)m).getScaledHeight() > maxHeight) {
-                maxHeight = ((MediaImageItem)m).getScaledHeight();
-            }
-        }
-        /** + Handle the image files here */
-        if (mPreviewEditSettings.clipSettingsArray[index].fileType == FileType.JPG) {
-            mPreviewEditSettings.clipSettingsArray[index].clipDecodedPath =
-                ((MediaImageItem)m).getDecodedImageFileName();
-
-            mPreviewEditSettings.clipSettingsArray[index].clipOriginalPath =
-                         mPreviewEditSettings.clipSettingsArray[index].clipPath;
-        }
-        return maxHeight;
-    }
-
-    /**
-     * Populates the background music track properties
-     *
-     * @param mediaBGMList The background music list
-     *
-     */
-    private void populateBackgroundMusicProperties(List<AudioTrack> mediaBGMList) {
-
-        if (mediaBGMList.size() == 1) {
-            mAudioTrack = mediaBGMList.get(0);
-        } else {
-            mAudioTrack = null;
-        }
-
-        if (mAudioTrack != null) {
-            mAudioSettings = new AudioSettings();
-            Properties mAudioProperties = new Properties();
-            mAudioSettings.pFile = null;
-            mAudioSettings.Id = mAudioTrack.getId();
-            try {
-                mAudioProperties = getMediaProperties(mAudioTrack.getFilename());
-            } catch (Exception e) {
-               throw new IllegalArgumentException("Unsupported file or file not found");
-            }
-            mAudioSettings.bRemoveOriginal = false;
-            mAudioSettings.channels = mAudioProperties.audioChannels;
-            mAudioSettings.Fs = mAudioProperties.audioSamplingFrequency;
-            mAudioSettings.loop = mAudioTrack.isLooping();
-            mAudioSettings.ExtendedFs = 0;
-            mAudioSettings.pFile = mAudioTrack.getFilename();
-            mAudioSettings.startMs = mAudioTrack.getStartTime();
-            mAudioSettings.beginCutTime = mAudioTrack.getBoundaryBeginTime();
-            mAudioSettings.endCutTime = mAudioTrack.getBoundaryEndTime();
-            if (mAudioTrack.isMuted()) {
-                mAudioSettings.volume = 0;
-            } else {
-                mAudioSettings.volume = mAudioTrack.getVolume();
-            }
-            mAudioSettings.fileType = mAudioProperties.fileType;
-            mAudioSettings.ducking_lowVolume = mAudioTrack.getDuckedTrackVolume();
-            mAudioSettings.ducking_threshold = mAudioTrack.getDuckingThreshhold();
-            mAudioSettings.bInDucking_enable = mAudioTrack.isDuckingEnabled();
-            mAudioTrackPCMFilePath = String.format(mProjectPath + "/" + AUDIO_TRACK_PCM_FILE);
-            mAudioSettings.pcmFilePath = mAudioTrackPCMFilePath;
-
-            mPreviewEditSettings.backgroundMusicSettings = new BackgroundMusicSettings();
-            mPreviewEditSettings.backgroundMusicSettings.file = mAudioTrackPCMFilePath;
-            mPreviewEditSettings.backgroundMusicSettings.fileType = mAudioProperties.fileType;
-            mPreviewEditSettings.backgroundMusicSettings.insertionTime =
-                mAudioTrack.getStartTime();
-            mPreviewEditSettings.backgroundMusicSettings.volumePercent = mAudioTrack.getVolume();
-            mPreviewEditSettings.backgroundMusicSettings.beginLoop =
-                mAudioTrack.getBoundaryBeginTime();
-            mPreviewEditSettings.backgroundMusicSettings.endLoop =
-                                               mAudioTrack.getBoundaryEndTime();
-            mPreviewEditSettings.backgroundMusicSettings.enableDucking =
-                mAudioTrack.isDuckingEnabled();
-            mPreviewEditSettings.backgroundMusicSettings.duckingThreshold =
-                mAudioTrack.getDuckingThreshhold();
-            mPreviewEditSettings.backgroundMusicSettings.lowVolume =
-                mAudioTrack.getDuckedTrackVolume();
-            mPreviewEditSettings.backgroundMusicSettings.isLooping = mAudioTrack.isLooping();
-            mPreviewEditSettings.primaryTrackVolume = 100;
-            mProcessingState  = PROCESSING_AUDIO_PCM;
-            mProcessingObject = mAudioTrack;
-        } else {
-            mAudioSettings = null;
-            mPreviewEditSettings.backgroundMusicSettings = null;
-            mAudioTrackPCMFilePath = null;
-        }
-    }
-
-    /**
-     * Calculates all the effects in all the media items
-     * in media items list
-     *
-     * @param mediaItemsList The media item list
-     *
-     * @return The total number of effects
-     *
-     */
-    private int getTotalEffects(List<MediaItem> mediaItemsList) {
-        int totalEffects = 0;
-        final Iterator<MediaItem> it = mediaItemsList.iterator();
-        while (it.hasNext()) {
-            final MediaItem t = it.next();
-            totalEffects += t.getAllEffects().size();
-            totalEffects += t.getAllOverlays().size();
-            final Iterator<Effect> ef = t.getAllEffects().iterator();
-            while (ef.hasNext()) {
-                final Effect e = ef.next();
-                if (e instanceof EffectKenBurns) {
-                    totalEffects--;
-                }
-            }
-        }
-        return totalEffects;
-    }
-
-    /**
-     * This function is responsible for forming clip settings
-     * array and clip properties array including transition clips
-     * and effect settings for preview purpose or export.
-     *
-     *
-     * @param mediaItemsList The media item list
-     * @param mediaTransitionList The transitions list
-     * @param mediaBGMList The background music list
-     * @param listener The MediaProcessingProgressListener
-     *
-     */
-    void previewStoryBoard(List<MediaItem> mediaItemsList,
-            List<Transition> mediaTransitionList, List<AudioTrack> mediaBGMList,
-            MediaProcessingProgressListener listener) {
-        if (mInvalidatePreviewArray) {
-            int previewIndex = 0;
-            int totalEffects = 0;
-            int storyBoardTime = 0;
-            int maxHeight = 0;
-            int beginCutTime = 0;
-            int endCutTime = 0;
-            int effectIndex = 0;
-            Transition lTransition = null;
-            MediaItem lMediaItem = null;
-            mPreviewEditSettings = new EditSettings();
-            mClipProperties = new PreviewClipProperties();
-            mTotalClips = 0;
-
-            mTotalClips = mediaItemsList.size();
-            for (Transition transition : mediaTransitionList) {
-                if (transition.getDuration() > 0) {
-                    mTotalClips++;
-                }
-            }
-
-            totalEffects = getTotalEffects(mediaItemsList);
-
-            mPreviewEditSettings.clipSettingsArray = new ClipSettings[mTotalClips];
-            mPreviewEditSettings.effectSettingsArray = new EffectSettings[totalEffects];
-            mClipProperties.clipProperties = new Properties[mTotalClips];
-
-            /** record the call back progress listener */
-            mMediaProcessingProgressListener = listener;
-            mProgressToApp = 0;
-
-            if (mediaItemsList.size() > 0) {
-                for (int i = 0; i < mediaItemsList.size(); i++) {
-                    /* Get the Media Item from the list */
-                    lMediaItem = mediaItemsList.get(i);
-                    if (lMediaItem instanceof MediaVideoItem) {
-                        beginCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryBeginTime();
-                        endCutTime = (int)((MediaVideoItem)lMediaItem).getBoundaryEndTime();
-                    } else if (lMediaItem instanceof MediaImageItem) {
-                        beginCutTime = 0;
-                        endCutTime = (int)((MediaImageItem)lMediaItem).getTimelineDuration();
-                    }
-                    /* Get the transition associated with Media Item */
-                    lTransition = lMediaItem.getBeginTransition();
-                    if (lTransition != null && (lTransition.getDuration() > 0)) {
-                        /* generate transition clip */
-                        generateTransition(lTransition, mPreviewEditSettings,
-                                           mClipProperties, previewIndex);
-                        storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
-                        previewIndex++;
-                    }
-                    /* Populate media item properties */
-                    maxHeight = populateMediaItemProperties(lMediaItem, previewIndex, maxHeight);
-                    /* Get the clip properties of the media item. */
-                    if (lMediaItem instanceof MediaImageItem) {
-                        int tmpCnt = 0;
-                        boolean bEffectKbPresent = false;
-                        final List<Effect> effectList = lMediaItem.getAllEffects();
-                        /**
-                         * Check if Ken Burns effect is present
-                         */
-                        while (tmpCnt < effectList.size()) {
-                            if (effectList.get(tmpCnt) instanceof EffectKenBurns) {
-                                bEffectKbPresent = true;
-                                break;
-                            }
-                            tmpCnt++;
-                        }
-
-                        if (bEffectKbPresent) {
-                            try {
-                                  if(((MediaImageItem)lMediaItem).getGeneratedImageClip() != null) {
-                                     mClipProperties.clipProperties[previewIndex]
-                                        = getMediaProperties(((MediaImageItem)lMediaItem).
-                                                             getGeneratedImageClip());
-                                  }
-                                  else {
-                                   mClipProperties.clipProperties[previewIndex]
-                                      = getMediaProperties(((MediaImageItem)lMediaItem).
-                                                             getScaledImageFileName());
-                                   mClipProperties.clipProperties[previewIndex].width =
-                                             ((MediaImageItem)lMediaItem).getScaledWidth();
-                                   mClipProperties.clipProperties[previewIndex].height =
-                                             ((MediaImageItem)lMediaItem).getScaledHeight();
-                                  }
-                                } catch (Exception e) {
-                                   throw new IllegalArgumentException("Unsupported file or file not found");
-                                }
-                         } else {
-                              try {
-                                  mClipProperties.clipProperties[previewIndex]
-                                      = getMediaProperties(((MediaImageItem)lMediaItem).
-                                                               getScaledImageFileName());
-                              } catch (Exception e) {
-                                throw new IllegalArgumentException("Unsupported file or file not found");
-                              }
-                            mClipProperties.clipProperties[previewIndex].width =
-                                        ((MediaImageItem)lMediaItem).getScaledWidth();
-                            mClipProperties.clipProperties[previewIndex].height =
-                                        ((MediaImageItem)lMediaItem).getScaledHeight();
-                        }
-                    } else {
-                        try {
-                            mClipProperties.clipProperties[previewIndex]
-                                 = getMediaProperties(lMediaItem.getFilename());
-                            } catch (Exception e) {
-                              throw new IllegalArgumentException("Unsupported file or file not found");
-                          }
-                    }
-                    mClipProperties.clipProperties[previewIndex].Id = lMediaItem.getId();
-                    checkOddSizeImage(lMediaItem, mClipProperties, previewIndex);
-                    adjustVolume(lMediaItem, mClipProperties, previewIndex);
-
-                    /*
-                     * Adjust media item start time and end time w.r.t to begin
-                     * and end transitions associated with media item
-                     */
-
-                    adjustMediaItemBoundary(mPreviewEditSettings.clipSettingsArray[previewIndex],
-                            mClipProperties.clipProperties[previewIndex], lMediaItem);
-
-                    /*
-                     * Get all the effects and overlays for that media item and
-                     * adjust start time and duration of effects
-                     */
-
-                    effectIndex = populateEffects(lMediaItem,
-                            mPreviewEditSettings.effectSettingsArray, effectIndex, beginCutTime,
-                            endCutTime, storyBoardTime);
-                    storyBoardTime += mClipProperties.clipProperties[previewIndex].duration;
-                    previewIndex++;
-
-                    /* Check if there is any end transition at last media item */
-
-                    if (i == (mediaItemsList.size() - 1)) {
-                        lTransition = lMediaItem.getEndTransition();
-                        if (lTransition != null && (lTransition.getDuration() > 0)) {
-                            generateTransition(lTransition, mPreviewEditSettings, mClipProperties,
-                                    previewIndex);
-                            break;
-                        }
-                    }
-                }
-
-                if (!mErrorFlagSet) {
-                    mPreviewEditSettings.videoFrameSize = findVideoResolution(mVideoEditor
-                            .getAspectRatio(), maxHeight);
-                    populateBackgroundMusicProperties(mediaBGMList);
-
-                    /** call to native populate settings */
-                    try {
-                        nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-                    } catch (IllegalArgumentException ex) {
-                        Log.e(TAG, "Illegal argument exception in nativePopulateSettings");
-                        throw ex;
-                    } catch (IllegalStateException ex) {
-                        Log.e(TAG, "Illegal state exception in nativePopulateSettings");
-                        throw ex;
-                    } catch (RuntimeException ex) {
-                        Log.e(TAG, "Runtime exception in nativePopulateSettings");
-                        throw ex;
-                    }
-                    mInvalidatePreviewArray = false;
-                    mProcessingState  = PROCESSING_NONE;
-                }
-            }
-            if (mErrorFlagSet) {
-                mErrorFlagSet = false;
-                throw new RuntimeException("preview generation cannot be completed");
-            }
-        }
-    } /* END of previewStoryBoard */
-
-    /**
-     * This function is responsible for starting the preview
-     *
-     *
-     * @param surface The surface on which preview has to be displayed
-     * @param fromMs The time in ms from which preview has to be started
-     * @param toMs The time in ms till preview has to be played
-     * @param loop To loop the preview or not
-     * @param callbackAfterFrameCount INdicated after how many frames
-     * the callback is needed
-     * @param listener The PreviewProgressListener
-     */
-    void doPreview(Surface surface, long fromMs, long toMs, boolean loop,
-            int callbackAfterFrameCount, PreviewProgressListener listener) {
-        mPreviewProgress = fromMs;
-        mIsFirstProgress = true;
-        mPreviewProgressListener = listener;
-
-        if (!mInvalidatePreviewArray) {
-            try {
-                /** Modify the image files names to rgb image files. */
-                for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
-                    clipCnt++) {
-                    if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
-                        mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
-                            mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
-                    }
-                }
-                nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-                nativeStartPreview(surface, fromMs, toMs, callbackAfterFrameCount, loop);
-            } catch (IllegalArgumentException ex) {
-                Log.e(TAG, "Illegal argument exception in nativeStartPreview");
-                throw ex;
-            } catch (IllegalStateException ex) {
-                Log.e(TAG, "Illegal state exception in nativeStartPreview");
-                throw ex;
-            } catch (RuntimeException ex) {
-                Log.e(TAG, "Runtime exception in nativeStartPreview");
-                throw ex;
-            }
-        } else {
-            throw new IllegalStateException("generatePreview is in progress");
-        }
-    }
-
-    /**
-     * This function is responsible for stopping the preview
-     */
-    long stopPreview() {
-        return nativeStopPreview();
-    }
-
-    /**
-     * This function is responsible for rendering a single frame
-     * from the complete story board on the surface
-     *
-     * @param surface The surface on which frame has to be rendered
-     * @param time The time in ms at which the frame has to be rendered
-     * @param surfaceWidth The surface width
-     * @param surfaceHeight The surface height
-     * @param overlayData The overlay data
-     *
-     * @return The actual time from the story board at which the  frame was extracted
-     * and rendered
-     */
-    long renderPreviewFrame(Surface surface, long time, int surfaceWidth,
-            int surfaceHeight, VideoEditor.OverlayData overlayData) {
-        if (mInvalidatePreviewArray) {
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                Log.d(TAG, "Call generate preview first");
-            }
-            throw new IllegalStateException("Call generate preview first");
-        }
-
-        long timeMs = 0;
-        try {
-            for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length;
-                  clipCnt++) {
-                if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
-                    mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
-                        mPreviewEditSettings.clipSettingsArray[clipCnt].clipDecodedPath;
-                }
-            }
-
-            // Reset the render preview frame params that shall be set by native.
-            mRenderPreviewOverlayFile = null;
-            mRenderPreviewRenderingMode = MediaRendering.RESIZING;
-
-            nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-
-            timeMs = (long)nativeRenderPreviewFrame(surface, time, surfaceWidth, surfaceHeight);
-
-            if (mRenderPreviewOverlayFile != null) {
-                overlayData.set(BitmapFactory.decodeFile(mRenderPreviewOverlayFile),
-                        mRenderPreviewRenderingMode);
-            } else {
-                overlayData.setClear();
-            }
-        } catch (IllegalArgumentException ex) {
-            Log.e(TAG, "Illegal Argument exception in nativeRenderPreviewFrame");
-            throw ex;
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "Illegal state exception in nativeRenderPreviewFrame");
-            throw ex;
-        } catch (RuntimeException ex) {
-            Log.e(TAG, "Runtime exception in nativeRenderPreviewFrame");
-            throw ex;
-        }
-
-        return timeMs;
-    }
-
-    private void previewFrameEditInfo(String filename, int renderingMode) {
-        mRenderPreviewOverlayFile = filename;
-        mRenderPreviewRenderingMode = renderingMode;
-    }
-
-
-    /**
-     * This function is responsible for rendering a single frame
-     * from a single media item on the surface
-     *
-     * @param surface The surface on which frame has to be rendered
-     * @param filepath The file path for which the frame needs to be displayed
-     * @param time The time in ms at which the frame has to be rendered
-     * @param framewidth The frame width
-     * @param framewidth The frame height
-     *
-     * @return The actual time from media item at which the  frame was extracted
-     * and rendered
-     */
-    long renderMediaItemPreviewFrame(Surface surface, String filepath,
-                                            long time, int framewidth, int frameheight) {
-        long timeMs = 0;
-        try {
-            timeMs = (long)nativeRenderMediaItemPreviewFrame(surface, filepath, framewidth,
-                    frameheight, 0, 0, time);
-        } catch (IllegalArgumentException ex) {
-            Log.e(TAG, "Illegal Argument exception in renderMediaItemPreviewFrame");
-            throw ex;
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "Illegal state exception in renderMediaItemPreviewFrame");
-            throw ex;
-        } catch (RuntimeException ex) {
-            Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
-            throw ex;
-        }
-
-        return timeMs;
-    }
-
-    /**
-     * This function sets the flag to invalidate the preview array
-     * and for generating the preview again
-     */
-    void setGeneratePreview(boolean isRequired) {
-        boolean semAcquiredDone = false;
-        try {
-            lock();
-            semAcquiredDone = true;
-            mInvalidatePreviewArray = isRequired;
-        } catch (InterruptedException ex) {
-            Log.e(TAG, "Runtime exception in renderMediaItemPreviewFrame");
-        } finally {
-            if (semAcquiredDone) {
-                unlock();
-            }
-        }
-    }
-
-    /**
-     * @return Returns the current status of preview invalidation
-     * flag
-     */
-    boolean getGeneratePreview() {
-        return mInvalidatePreviewArray;
-    }
-
-    /**
-     * Calculates the aspect ratio from widht and height
-     *
-     * @param w The width of media item
-     * @param h The height of media item
-     *
-     * @return The calculated aspect ratio
-     */
-    int getAspectRatio(int w, int h) {
-        double apRatio = (double)(w) / (double)(h);
-        BigDecimal bd = new BigDecimal(apRatio);
-        bd = bd.setScale(3, BigDecimal.ROUND_HALF_UP);
-        apRatio = bd.doubleValue();
-        int var = MediaProperties.ASPECT_RATIO_16_9;
-        if (apRatio >= 1.7) {
-            var = MediaProperties.ASPECT_RATIO_16_9;
-        } else if (apRatio >= 1.6) {
-            var = MediaProperties.ASPECT_RATIO_5_3;
-        } else if (apRatio >= 1.5) {
-            var = MediaProperties.ASPECT_RATIO_3_2;
-        } else if (apRatio > 1.3) {
-            var = MediaProperties.ASPECT_RATIO_4_3;
-        } else if (apRatio >= 1.2) {
-            var = MediaProperties.ASPECT_RATIO_11_9;
-        }
-        return var;
-    }
-
-    /**
-     * Maps the file type used in native layer
-     * to file type used in JAVA layer
-     *
-     * @param fileType The file type in native layer
-     *
-     * @return The File type in JAVA layer
-     */
-    int getFileType(int fileType) {
-        int retValue = -1;
-        switch (fileType) {
-            case FileType.UNSUPPORTED:
-                retValue = MediaProperties.FILE_UNSUPPORTED;
-                break;
-            case FileType.THREE_GPP:
-                retValue = MediaProperties.FILE_3GP;
-                break;
-            case FileType.MP4:
-                retValue = MediaProperties.FILE_MP4;
-                break;
-            case FileType.JPG:
-                retValue = MediaProperties.FILE_JPEG;
-                break;
-            case FileType.PNG:
-                retValue = MediaProperties.FILE_PNG;
-                break;
-            case FileType.MP3:
-                retValue = MediaProperties.FILE_MP3;
-                break;
-            case FileType.M4V:
-                retValue = MediaProperties.FILE_M4V;
-                break;
-            case FileType.AMR:
-                retValue = MediaProperties.FILE_AMR;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the video codec type used in native layer
-     * to video codec type used in JAVA layer
-     *
-     * @param codecType The video codec type in native layer
-     *
-     * @return The video codec type in JAVA layer
-     */
-    int getVideoCodecType(int codecType) {
-        int retValue = -1;
-        switch (codecType) {
-            case VideoFormat.H263:
-                retValue = MediaProperties.VCODEC_H263;
-                break;
-            case VideoFormat.H264:
-                retValue = MediaProperties.VCODEC_H264;
-                break;
-            case VideoFormat.MPEG4:
-                retValue = MediaProperties.VCODEC_MPEG4;
-                break;
-            case VideoFormat.UNSUPPORTED:
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the audio codec type used in native layer
-     * to audio codec type used in JAVA layer
-     *
-     * @param audioType The audio codec type in native layer
-     *
-     * @return The audio codec type in JAVA layer
-     */
-    int getAudioCodecType(int codecType) {
-        int retValue = -1;
-        switch (codecType) {
-            case AudioFormat.AMR_NB:
-                retValue = MediaProperties.ACODEC_AMRNB;
-                break;
-            case AudioFormat.AAC:
-                retValue = MediaProperties.ACODEC_AAC_LC;
-                break;
-            case AudioFormat.MP3:
-                retValue = MediaProperties.ACODEC_MP3;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Returns the frame rate as integer
-     *
-     * @param fps The fps as enum
-     *
-     * @return The frame rate as integer
-     */
-    int getFrameRate(int fps) {
-        int retValue = -1;
-        switch (fps) {
-            case VideoFrameRate.FR_5_FPS:
-                retValue = 5;
-                break;
-            case VideoFrameRate.FR_7_5_FPS:
-                retValue = 8;
-                break;
-            case VideoFrameRate.FR_10_FPS:
-                retValue = 10;
-                break;
-            case VideoFrameRate.FR_12_5_FPS:
-                retValue = 13;
-                break;
-            case VideoFrameRate.FR_15_FPS:
-                retValue = 15;
-                break;
-            case VideoFrameRate.FR_20_FPS:
-                retValue = 20;
-                break;
-            case VideoFrameRate.FR_25_FPS:
-                retValue = 25;
-                break;
-            case VideoFrameRate.FR_30_FPS:
-                retValue = 30;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the file type used in JAVA layer
-     * to file type used in native layer
-     *
-     * @param fileType The file type in JAVA layer
-     *
-     * @return The File type in native layer
-     */
-    int getMediaItemFileType(int fileType) {
-        int retValue = -1;
-
-        switch (fileType) {
-            case MediaProperties.FILE_UNSUPPORTED:
-                retValue = FileType.UNSUPPORTED;
-                break;
-            case MediaProperties.FILE_3GP:
-                retValue = FileType.THREE_GPP;
-                break;
-            case MediaProperties.FILE_MP4:
-                retValue = FileType.MP4;
-                break;
-            case MediaProperties.FILE_JPEG:
-                retValue = FileType.JPG;
-                break;
-            case MediaProperties.FILE_PNG:
-                retValue = FileType.PNG;
-                break;
-            case MediaProperties.FILE_M4V:
-                retValue = FileType.M4V;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-
-    }
-
-    /**
-     * Maps the rendering mode used in native layer
-     * to rendering mode used in JAVA layer
-     *
-     * @param renderingMode The rendering mode in JAVA layer
-     *
-     * @return The rendering mode in native layer
-     */
-    int getMediaItemRenderingMode(int renderingMode) {
-        int retValue = -1;
-        switch (renderingMode) {
-            case MediaItem.RENDERING_MODE_BLACK_BORDER:
-                retValue = MediaRendering.BLACK_BORDERS;
-                break;
-            case MediaItem.RENDERING_MODE_STRETCH:
-                retValue = MediaRendering.RESIZING;
-                break;
-            case MediaItem.RENDERING_MODE_CROPPING:
-                retValue = MediaRendering.CROPPING;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the transition behavior used in JAVA layer
-     * to transition behavior used in native layer
-     *
-     * @param transitionType The transition behavior in JAVA layer
-     *
-     * @return The transition behavior in native layer
-     */
-    int getVideoTransitionBehaviour(int transitionType) {
-        int retValue = -1;
-        switch (transitionType) {
-            case Transition.BEHAVIOR_SPEED_UP:
-                retValue = TransitionBehaviour.SPEED_UP;
-                break;
-            case Transition.BEHAVIOR_SPEED_DOWN:
-                retValue = TransitionBehaviour.SPEED_DOWN;
-                break;
-            case Transition.BEHAVIOR_LINEAR:
-                retValue = TransitionBehaviour.LINEAR;
-                break;
-            case Transition.BEHAVIOR_MIDDLE_SLOW:
-                retValue = TransitionBehaviour.SLOW_MIDDLE;
-                break;
-            case Transition.BEHAVIOR_MIDDLE_FAST:
-                retValue = TransitionBehaviour.FAST_MIDDLE;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the transition slide direction used in JAVA layer
-     * to transition slide direction used in native layer
-     *
-     * @param slideDirection The transition slide direction
-     * in JAVA layer
-     *
-     * @return The transition slide direction in native layer
-     */
-    int getSlideSettingsDirection(int slideDirection) {
-        int retValue = -1;
-        switch (slideDirection) {
-            case TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN:
-                retValue = SlideDirection.RIGHT_OUT_LEFT_IN;
-                break;
-            case TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN:
-                retValue = SlideDirection.LEFT_OUT_RIGTH_IN;
-                break;
-            case TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN:
-                retValue = SlideDirection.TOP_OUT_BOTTOM_IN;
-                break;
-            case TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN:
-                retValue = SlideDirection.BOTTOM_OUT_TOP_IN;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Maps the effect color type used in JAVA layer
-     * to effect color type used in native layer
-     *
-     * @param effect The EffectColor reference
-     *
-     * @return The color effect value from native layer
-     */
-    private int getEffectColorType(EffectColor effect) {
-        int retValue = -1;
-        switch (effect.getType()) {
-            case EffectColor.TYPE_COLOR:
-                if (effect.getColor() == EffectColor.GREEN) {
-                    retValue = VideoEffect.GREEN;
-                } else if (effect.getColor() == EffectColor.PINK) {
-                    retValue = VideoEffect.PINK;
-                } else if (effect.getColor() == EffectColor.GRAY) {
-                    retValue = VideoEffect.BLACK_AND_WHITE;
-                } else {
-                    retValue = VideoEffect.COLORRGB16;
-                }
-                break;
-            case EffectColor.TYPE_GRADIENT:
-                retValue = VideoEffect.GRADIENT;
-                break;
-            case EffectColor.TYPE_SEPIA:
-                retValue = VideoEffect.SEPIA;
-                break;
-            case EffectColor.TYPE_NEGATIVE:
-                retValue = VideoEffect.NEGATIVE;
-                break;
-            case EffectColor.TYPE_FIFTIES:
-                retValue = VideoEffect.FIFTIES;
-                break;
-
-            default:
-                retValue = -1;
-        }
-        return retValue;
-    }
-
-    /**
-     * Calculates video resolution for output clip
-     * based on clip's height and aspect ratio of storyboard
-     *
-     * @param aspectRatio The aspect ratio of story board
-     * @param height The height of clip
-     *
-     * @return The video resolution
-     */
-    private int findVideoResolution(int aspectRatio, int height) {
-        final Pair<Integer, Integer>[] resolutions;
-        final Pair<Integer, Integer> maxResolution;
-        int retValue = VideoFrameSize.SIZE_UNDEFINED;
-        switch (aspectRatio) {
-            case MediaProperties.ASPECT_RATIO_3_2:
-                if (height == MediaProperties.HEIGHT_480)
-                    retValue = VideoFrameSize.NTSC;
-                else if (height == MediaProperties.HEIGHT_720)
-                    retValue = VideoFrameSize.W720p;
-                break;
-            case MediaProperties.ASPECT_RATIO_16_9:
-                if (height == MediaProperties.HEIGHT_480)
-                    retValue = VideoFrameSize.WVGA16x9;
-                else if (height == MediaProperties.HEIGHT_720)
-                    retValue = VideoFrameSize.V720p;
-                else if (height == MediaProperties.HEIGHT_1080)
-                    retValue = VideoFrameSize.V1080p;
-                break;
-            case MediaProperties.ASPECT_RATIO_4_3:
-                if (height == MediaProperties.HEIGHT_480)
-                    retValue = VideoFrameSize.VGA;
-                else if (height == MediaProperties.HEIGHT_720)
-                    retValue = VideoFrameSize.S720p;
-                break;
-            case MediaProperties.ASPECT_RATIO_5_3:
-                if (height == MediaProperties.HEIGHT_480)
-                    retValue = VideoFrameSize.WVGA;
-                break;
-            case MediaProperties.ASPECT_RATIO_11_9:
-                if (height == MediaProperties.HEIGHT_144)
-                    retValue = VideoFrameSize.QCIF;
-                else if (height == MediaProperties.HEIGHT_288)
-                    retValue = VideoFrameSize.CIF;
-                break;
-        }
-        if (retValue == VideoFrameSize.SIZE_UNDEFINED) {
-            resolutions = MediaProperties.getSupportedResolutions(mVideoEditor.getAspectRatio());
-            // Get the highest resolution
-            maxResolution = resolutions[resolutions.length - 1];
-            retValue = findVideoResolution(mVideoEditor.getAspectRatio(), maxResolution.second);
-        }
-
-        return retValue;
-    }
-
-    /**
-     *  Calculate a reasonable bitrate for generating intermediate clips.
-     */
-    private int findVideoBitrate(int videoFrameSize) {
-        switch (videoFrameSize) {
-            case VideoFrameSize.SQCIF:
-            case VideoFrameSize.QQVGA:
-            case VideoFrameSize.QCIF:
-                return Bitrate.BR_128_KBPS;
-            case VideoFrameSize.QVGA:
-            case VideoFrameSize.CIF:
-                return Bitrate.BR_384_KBPS;
-            case VideoFrameSize.VGA:
-            case VideoFrameSize.WVGA:
-            case VideoFrameSize.NTSC:
-            case VideoFrameSize.nHD:
-            case VideoFrameSize.WVGA16x9:
-                return Bitrate.BR_2_MBPS;
-            case VideoFrameSize.V720p:
-            case VideoFrameSize.W720p:
-            case VideoFrameSize.S720p:
-                return Bitrate.BR_5_MBPS;
-            case VideoFrameSize.V1080p:
-            default:
-                return Bitrate.BR_8_MBPS;
-        }
-    }
-
-    /**
-     * This method is responsible for exporting a movie
-     *
-     * @param filePath The output file path
-     * @param projectDir The output project directory
-     * @param height The height of clip
-     * @param bitrate The bitrate at which the movie should be exported
-     * @param mediaItemsList The media items list
-     * @param mediaTransitionList The transitions list
-     * @param mediaBGMList The background track list
-     * @param listener The ExportProgressListener
-     *
-     */
-    void export(String filePath, String projectDir, int height, int bitrate,
-            List<MediaItem> mediaItemsList, List<Transition> mediaTransitionList,
-            List<AudioTrack> mediaBGMList, ExportProgressListener listener) {
-
-        int outBitrate = 0;
-        mExportFilename = filePath;
-        previewStoryBoard(mediaItemsList, mediaTransitionList, mediaBGMList,null);
-        mExportProgressListener = listener;
-        int outVideoProfile = 0;
-        int outVideoLevel = 0;
-
-        /** Check the platform specific maximum export resolution */
-        VideoEditorProfile veProfile = VideoEditorProfile.get();
-        if (veProfile == null) {
-            throw new RuntimeException("Can't get the video editor profile");
-        }
-        final int maxOutputHeight = veProfile.maxOutputVideoFrameHeight;
-        final int maxOutputWidth = veProfile.maxOutputVideoFrameWidth;
-        if (height > maxOutputHeight) {
-            throw new IllegalArgumentException(
-                    "Unsupported export resolution. Supported maximum width:" +
-                    maxOutputWidth + " height:" + maxOutputHeight +
-                    " current height:" + height);
-        }
-        outVideoProfile = VideoEditorProfile.getExportProfile(mExportVideoCodec);
-        outVideoLevel = VideoEditorProfile.getExportLevel(mExportVideoCodec);
-
-        mProgressToApp = 0;
-
-        switch (bitrate) {
-            case MediaProperties.BITRATE_28K:
-                outBitrate = Bitrate.BR_32_KBPS;
-                break;
-            case MediaProperties.BITRATE_40K:
-                outBitrate = Bitrate.BR_48_KBPS;
-                break;
-            case MediaProperties.BITRATE_64K:
-                outBitrate = Bitrate.BR_64_KBPS;
-                break;
-            case MediaProperties.BITRATE_96K:
-                outBitrate = Bitrate.BR_96_KBPS;
-                break;
-            case MediaProperties.BITRATE_128K:
-                outBitrate = Bitrate.BR_128_KBPS;
-                break;
-            case MediaProperties.BITRATE_192K:
-                outBitrate = Bitrate.BR_192_KBPS;
-                break;
-            case MediaProperties.BITRATE_256K:
-                outBitrate = Bitrate.BR_256_KBPS;
-                break;
-            case MediaProperties.BITRATE_384K:
-                outBitrate = Bitrate.BR_384_KBPS;
-                break;
-            case MediaProperties.BITRATE_512K:
-                outBitrate = Bitrate.BR_512_KBPS;
-                break;
-            case MediaProperties.BITRATE_800K:
-                outBitrate = Bitrate.BR_800_KBPS;
-                break;
-            case MediaProperties.BITRATE_2M:
-                outBitrate = Bitrate.BR_2_MBPS;
-                break;
-            case MediaProperties.BITRATE_5M:
-                outBitrate = Bitrate.BR_5_MBPS;
-                break;
-            case MediaProperties.BITRATE_8M:
-                outBitrate = Bitrate.BR_8_MBPS;
-                break;
-
-            default:
-                throw new IllegalArgumentException("Argument Bitrate incorrect");
-        }
-        mPreviewEditSettings.videoFrameRate = VideoFrameRate.FR_30_FPS;
-        mPreviewEditSettings.outputFile = mOutputFilename = filePath;
-
-        int aspectRatio = mVideoEditor.getAspectRatio();
-        mPreviewEditSettings.videoFrameSize = findVideoResolution(aspectRatio, height);
-        mPreviewEditSettings.videoFormat = mExportVideoCodec;
-        mPreviewEditSettings.audioFormat = mExportAudioCodec;
-        mPreviewEditSettings.videoProfile = outVideoProfile;
-        mPreviewEditSettings.videoLevel = outVideoLevel;
-        mPreviewEditSettings.audioSamplingFreq = AudioSamplingFrequency.FREQ_32000;
-        mPreviewEditSettings.maxFileSize = 0;
-        mPreviewEditSettings.audioChannels = 2;
-        mPreviewEditSettings.videoBitrate = outBitrate;
-        mPreviewEditSettings.audioBitrate = Bitrate.BR_96_KBPS;
-
-        mPreviewEditSettings.transitionSettingsArray = new TransitionSettings[mTotalClips - 1];
-        for (int index = 0; index < mTotalClips - 1; index++) {
-            mPreviewEditSettings.transitionSettingsArray[index] = new TransitionSettings();
-            mPreviewEditSettings.transitionSettingsArray[index].videoTransitionType =
-                VideoTransition.NONE;
-            mPreviewEditSettings.transitionSettingsArray[index].audioTransitionType =
-                AudioTransition.NONE;
-        }
-
-        for (int clipCnt = 0; clipCnt < mPreviewEditSettings.clipSettingsArray.length; clipCnt++) {
-            if (mPreviewEditSettings.clipSettingsArray[clipCnt].fileType == FileType.JPG) {
-                mPreviewEditSettings.clipSettingsArray[clipCnt].clipPath =
-                mPreviewEditSettings.clipSettingsArray[clipCnt].clipOriginalPath;
-            }
-        }
-        nativePopulateSettings(mPreviewEditSettings, mClipProperties, mAudioSettings);
-
-        int err = 0;
-        try {
-            mProcessingState  = PROCESSING_EXPORT;
-            mProcessingObject = null;
-            err = generateClip(mPreviewEditSettings);
-            mProcessingState  = PROCESSING_NONE;
-        } catch (IllegalArgumentException ex) {
-            Log.e(TAG, "IllegalArgument for generateClip");
-            throw ex;
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "IllegalStateExceptiont for generateClip");
-            throw ex;
-        } catch (RuntimeException ex) {
-            Log.e(TAG, "RuntimeException for generateClip");
-            throw ex;
-        }
-
-        if (err != 0) {
-            Log.e(TAG, "RuntimeException for generateClip");
-            throw new RuntimeException("generateClip failed with error=" + err);
-        }
-
-        mExportProgressListener = null;
-    }
-
-    /**
-     * This methods takes care of stopping the Export process
-     *
-     * @param The input file name for which export has to be stopped
-     */
-    void stop(String filename) {
-        try {
-            stopEncoding();
-            new File(mExportFilename).delete();
-        } catch (IllegalStateException ex) {
-            Log.e(TAG, "Illegal state exception in unload settings");
-            throw ex;
-        } catch (RuntimeException ex) {
-            Log.e(TAG, "Runtime exception in unload settings");
-            throw ex;
-        }
-    }
-
-    /**
-     * This method extracts a frame from the input file
-     * and returns the frame as a bitmap. See getPixelsList() for more information.
-     */
-    Bitmap getPixels(String filename, int width, int height, long timeMs,
-            int videoRotation) {
-        final Bitmap result[] = new Bitmap[1];
-        getPixelsList(filename, width, height, timeMs, timeMs, 1, new int[] {0},
-                new MediaItem.GetThumbnailListCallback() {
-            public void onThumbnail(Bitmap bitmap, int index) {
-                result[0] = bitmap;
-            }
-        }, videoRotation);
-        return result[0];
-    }
-
-    /**
-     * This method extracts a list of frame from the
-     * input file and returns the frame in bitmap array
-     *
-     * @param filename The input file name
-     * @param width The width of the output frame, before rotation
-     * @param height The height of the output frame, before rotation
-     * @param startMs The starting time in ms
-     * @param endMs The end time in ms
-     * @param thumbnailCount The number of frames to be extracted
-     * @param indices The indices of thumbnails wanted
-     * @param callback The callback used to pass back the bitmaps
-     * @param videoRotation The rotation degree need to be done for the bitmap
-     *
-     * @return The frames as bitmaps in bitmap array
-     **/
-    void getPixelsList(String filename, final int width, final int height,
-            long startMs, long endMs, int thumbnailCount, int[] indices,
-            final MediaItem.GetThumbnailListCallback callback,
-            final int videoRotation) {
-
-        // The decoder needs output width and height as even
-        final int decWidth = (width + 1) & 0xFFFFFFFE;
-        final int decHeight = (height + 1) & 0xFFFFFFFE;
-        final int thumbnailSize = decWidth * decHeight;
-
-        // We convert the decoder output (in int[]) to a bitmap by first
-        // copy it into an IntBuffer, then use Bitmap.copyPixelsFromBuffer to
-        // copy it to the bitmap.
-        final int[] decArray = new int[thumbnailSize];
-        final IntBuffer decBuffer = IntBuffer.allocate(thumbnailSize);
-
-        // If we need to resize and/or rotate the decoder output, we need a
-        // temporary bitmap to hold the decoded output.
-        final boolean needToMassage =
-                (decWidth != width || decHeight != height || videoRotation != 0);
-        final Bitmap tmpBitmap = needToMassage
-                ? Bitmap.createBitmap(decWidth, decHeight, Bitmap.Config.ARGB_8888)
-                : null;
-
-        // The final output bitmap width/height may swap because of rotation.
-        final boolean needToSwapWH = (videoRotation == 90 || videoRotation == 270);
-        final int outWidth = needToSwapWH ? height : width;
-        final int outHeight = needToSwapWH ? width : height;
-
-        nativeGetPixelsList(filename, decArray, decWidth, decHeight,
-                thumbnailCount, startMs, endMs, indices,
-                new NativeGetPixelsListCallback() {
-            public void onThumbnail(int index) {
-                // This is the bitmap we will output to the client
-                Bitmap outBitmap = Bitmap.createBitmap(
-                        outWidth, outHeight, Bitmap.Config.ARGB_8888);
-
-                // Copy int[] to IntBuffer
-                decBuffer.rewind();
-                decBuffer.put(decArray, 0, thumbnailSize);
-                decBuffer.rewind();
-
-                if (!needToMassage) {
-                    // We can directly read the decoded result to output bitmap
-                    outBitmap.copyPixelsFromBuffer(decBuffer);
-                } else {
-                    // Copy the decoded result to an intermediate bitmap first
-                    tmpBitmap.copyPixelsFromBuffer(decBuffer);
-
-                    // Create a canvas to resize/rotate the bitmap
-                    // First scale the decoded bitmap to (0,0)-(1,1), rotate it
-                    // with (0.5, 0.5) as center, then scale it to
-                    // (outWidth, outHeight).
-                    final Canvas canvas = new Canvas(outBitmap);
-                    Matrix m = new Matrix();
-                    float sx = 1f / decWidth;
-                    float sy = 1f / decHeight;
-                    m.postScale(sx, sy);
-                    m.postRotate(videoRotation, 0.5f, 0.5f);
-                    m.postScale(outWidth, outHeight);
-                    canvas.drawBitmap(tmpBitmap, m, sResizePaint);
-                }
-                callback.onThumbnail(outBitmap, index);
-            }
-        });
-
-        if (tmpBitmap != null) {
-            tmpBitmap.recycle();
-        }
-    }
-
-    interface NativeGetPixelsListCallback {
-        public void onThumbnail(int index);
-    }
-
-    /**
-     * This method generates the audio graph
-     *
-     * @param uniqueId The unique id
-     * @param inFileName The inputFile
-     * @param OutAudiGraphFileName output filename
-     * @param frameDuration The each frame duration
-     * @param audioChannels The number of audio channels
-     * @param samplesCount Total number of samples count
-     * @param listener ExtractAudioWaveformProgressListener reference
-     * @param isVideo The flag to indicate if the file is video file or not
-     *
-     **/
-    void generateAudioGraph(String uniqueId, String inFileName, String OutAudiGraphFileName,
-            int frameDuration, int audioChannels, int samplesCount,
-            ExtractAudioWaveformProgressListener listener, boolean isVideo) {
-        String tempPCMFileName;
-
-        mExtractAudioWaveformProgressListener = listener;
-
-        /**
-         * In case of Video, first call will generate the PCM file to make the
-         * audio graph
-         */
-        if (isVideo) {
-            tempPCMFileName = String.format(mProjectPath + "/" + uniqueId + ".pcm");
-        } else {
-            tempPCMFileName = mAudioTrackPCMFilePath;
-        }
-
-        /**
-         * For Video item, generate the PCM
-         */
-        if (isVideo) {
-            nativeGenerateRawAudio(inFileName, tempPCMFileName);
-        }
-
-        nativeGenerateAudioGraph(tempPCMFileName, OutAudiGraphFileName, frameDuration,
-                audioChannels, samplesCount);
-
-        /**
-         * Once the audio graph file is generated, delete the pcm file
-         */
-        if (isVideo) {
-            new File(tempPCMFileName).delete();
-        }
-    }
-
-    void clearPreviewSurface(Surface surface) {
-        nativeClearSurface(surface);
-    }
-
-    /**
-     * Grab the semaphore which arbitrates access to the editor
-     *
-     * @throws InterruptedException
-     */
-    private void lock() throws InterruptedException {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbing semaphore", new Throwable());
-        }
-        mLock.acquire();
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbed semaphore");
-        }
-    }
-
-    /**
-     * Release the semaphore which arbitrates access to the editor
-     */
-    private void unlock() {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "unlock: releasing semaphore");
-        }
-        mLock.release();
-    }
-
-    /**     Native Methods        */
-    native Properties getMediaProperties(String file) throws IllegalArgumentException,
-            IllegalStateException, RuntimeException, Exception;
-
-    /**
-     * Get the version of ManualEdit.
-     *
-     * @return version of ManualEdit
-     * @throws RuntimeException if an error occurred
-     * @see Version
-     */
-    private static native Version getVersion() throws RuntimeException;
-
-    /**
-     * Returns the video thumbnail in an array of integers. Output format is
-     * ARGB8888.
-     *
-     * @param pixelArray the array that receives the pixel values
-     * @param width width of the video thumbnail
-     * @param height height of the video thumbnail
-     * @param timeMS desired time of the thumbnail in ms
-     * @return actual time in ms of the thumbnail generated
-     * @throws IllegalStateException if the class has not been initialized
-     * @throws IllegalArgumentException if the pixelArray is not available or
-     *             one of the dimensions is negative or zero or the time is
-     *             negative
-     * @throws RuntimeException on runtime errors in native code
-     */
-    private native int nativeGetPixels(String fileName, int[] pixelArray, int width, int height,
-            long timeMS);
-
-    private native int nativeGetPixelsList(String fileName, int[] pixelArray,
-            int width, int height, int nosofTN, long startTimeMs,
-            long endTimeMs, int[] indices, NativeGetPixelsListCallback callback);
-
-    /**
-     * Releases the JNI and cleans up the core native module.. Should be called
-     * only after init( )
-     *
-     * @throws IllegalStateException if the method could not be called
-     */
-    private native void release() throws IllegalStateException, RuntimeException;
-
-    /*
-     * Clear the preview surface
-     */
-    private native void nativeClearSurface(Surface surface);
-
-    /**
-     * Stops the encoding. This method should only be called after encoding has
-     * started using method <code> startEncoding</code>
-     *
-     * @throws IllegalStateException if the method could not be called
-     */
-    private native void stopEncoding() throws IllegalStateException, RuntimeException;
-
-
-    private native void _init(String tempPath, String libraryPath)
-            throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
-    private native void nativeStartPreview(Surface mSurface, long fromMs, long toMs,
-            int callbackAfterFrameCount, boolean loop) throws IllegalArgumentException,
-            IllegalStateException, RuntimeException;
-
-    private native void nativePopulateSettings(EditSettings editSettings,
-            PreviewClipProperties mProperties, AudioSettings mAudioSettings)
-    throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
-    private native int nativeRenderPreviewFrame(Surface mSurface, long timeMs,
-                                                 int surfaceWidth, int surfaceHeight)
-                                                 throws IllegalArgumentException,
-                                                 IllegalStateException, RuntimeException;
-
-    private native int nativeRenderMediaItemPreviewFrame(Surface mSurface, String filepath,
-            int framewidth, int frameheight, int surfacewidth, int surfaceheight, long timeMs)
-    throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
-    private native int nativeStopPreview();
-
-    private native int nativeGenerateAudioGraph(String pcmFilePath, String outGraphPath,
-            int frameDuration, int channels, int sampleCount);
-
-    private native int nativeGenerateRawAudio(String InFileName, String PCMFileName);
-
-    private native int nativeGenerateClip(EditSettings editSettings)
-    throws IllegalArgumentException, IllegalStateException, RuntimeException;
-
-}
diff --git a/media/java/android/media/videoeditor/MediaImageItem.java b/media/java/android/media/videoeditor/MediaImageItem.java
deleted file mode 100644
index 590b4ae..0000000
--- a/media/java/android/media/videoeditor/MediaImageItem.java
+++ /dev/null
@@ -1,1021 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import java.util.ArrayList;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EditSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.FileType;
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-import android.util.Log;
-import android.util.Pair;
-
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-import java.lang.Math;
-import java.util.List;
-
-/**
- * This class represents an image item on the storyboard. Note that images are
- * scaled down to the maximum supported resolution by preserving the native
- * aspect ratio. To learn the scaled image dimensions use
- * {@link #getScaledWidth()} and {@link #getScaledHeight()} respectively.
- *
- * {@hide}
- */
-public class MediaImageItem extends MediaItem {
-    /**
-     *  Logging
-     */
-    private static final String TAG = "MediaImageItem";
-
-    /**
-     *  The resize paint
-     */
-    private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
-    /**
-     *  Instance variables
-     */
-    private final int mWidth;
-    private final int mHeight;
-    private final int mAspectRatio;
-    private long mDurationMs;
-    private int mScaledWidth, mScaledHeight;
-    private String mScaledFilename;
-    private final VideoEditorImpl mVideoEditor;
-    private String mDecodedFilename;
-    private int mGeneratedClipHeight;
-    private int mGeneratedClipWidth;
-    private String mFileName;
-
-    private final MediaArtistNativeHelper mMANativeHelper;
-
-    /**
-     * This class cannot be instantiated by using the default constructor
-     */
-    @SuppressWarnings("unused")
-    private MediaImageItem() throws IOException {
-        this(null, null, null, 0, RENDERING_MODE_BLACK_BORDER);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param mediaItemId The media item id
-     * @param filename The image file name
-     * @param durationMs The duration of the image on the storyboard
-     * @param renderingMode The rendering mode
-     *
-     * @throws IOException
-     */
-    public MediaImageItem(VideoEditor editor, String mediaItemId, String filename, long durationMs,
-        int renderingMode) throws IOException {
-
-        super(editor, mediaItemId, filename, renderingMode);
-
-        mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
-        mVideoEditor = ((VideoEditorImpl)editor);
-        try {
-            final Properties properties = mMANativeHelper.getMediaProperties(filename);
-
-            switch (mMANativeHelper.getFileType(properties.fileType)) {
-                case MediaProperties.FILE_JPEG:
-                case MediaProperties.FILE_PNG: {
-                    break;
-                }
-
-                default: {
-                    throw new IllegalArgumentException("Unsupported Input File Type");
-                }
-            }
-        } catch (Exception e) {
-            throw new IllegalArgumentException("Unsupported file or file not found: " + filename);
-        }
-        mFileName = filename;
-        /**
-         *  Determine the dimensions of the image
-         */
-        final BitmapFactory.Options dbo = new BitmapFactory.Options();
-        dbo.inJustDecodeBounds = true;
-        BitmapFactory.decodeFile(filename, dbo);
-
-        mWidth = dbo.outWidth;
-        mHeight = dbo.outHeight;
-        mDurationMs = durationMs;
-        mDecodedFilename = String.format(mMANativeHelper.getProjectPath() +
-                "/" + "decoded" + getId()+ ".rgb");
-
-        try {
-            mAspectRatio = mMANativeHelper.getAspectRatio(mWidth, mHeight);
-        } catch(IllegalArgumentException e) {
-            throw new IllegalArgumentException ("Null width and height");
-        }
-
-        mGeneratedClipHeight = 0;
-        mGeneratedClipWidth = 0;
-
-        /**
-         *  Images are stored in memory scaled to the maximum resolution to
-         *  save memory.
-         */
-        final Pair<Integer, Integer>[] resolutions =
-            MediaProperties.getSupportedResolutions(mAspectRatio);
-
-        /**
-         *  Get the highest resolution
-         */
-        final Pair<Integer, Integer> maxResolution = resolutions[resolutions.length - 1];
-
-        final Bitmap imageBitmap;
-
-        if (mWidth > maxResolution.first || mHeight > maxResolution.second) {
-            /**
-             *  We need to scale the image
-             */
-            imageBitmap = scaleImage(filename, maxResolution.first,
-                                                         maxResolution.second);
-            mScaledFilename = String.format(mMANativeHelper.getProjectPath() +
-                    "/" + "scaled" + getId()+ ".JPG");
-            if (!((new File(mScaledFilename)).exists())) {
-                super.mRegenerateClip = true;
-                final FileOutputStream f1 = new FileOutputStream(mScaledFilename);
-                imageBitmap.compress(Bitmap.CompressFormat.JPEG, 50,f1);
-                f1.close();
-            }
-            mScaledWidth =  (imageBitmap.getWidth() >> 1) << 1;
-            mScaledHeight = (imageBitmap.getHeight() >> 1) << 1;
-        } else {
-            mScaledFilename = filename;
-            mScaledWidth =  (mWidth >> 1) << 1;
-            mScaledHeight = (mHeight >> 1) << 1;
-            imageBitmap = BitmapFactory.decodeFile(mScaledFilename);
-        }
-        int newWidth = mScaledWidth;
-        int newHeight = mScaledHeight;
-        if (!((new File(mDecodedFilename)).exists())) {
-            final FileOutputStream fl = new FileOutputStream(mDecodedFilename);
-            final DataOutputStream dos = new DataOutputStream(fl);
-            final int [] framingBuffer = new int[newWidth];
-            final ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
-            IntBuffer intBuffer;
-            final byte[] array = byteBuffer.array();
-            int tmp = 0;
-            while (tmp < newHeight) {
-                imageBitmap.getPixels(framingBuffer, 0, mScaledWidth, 0,
-                                                        tmp, newWidth, 1);
-                intBuffer = byteBuffer.asIntBuffer();
-                intBuffer.put(framingBuffer, 0, newWidth);
-                dos.write(array);
-                tmp += 1;
-            }
-            fl.close();
-        }
-        imageBitmap.recycle();
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getFileType() {
-        if (mFilename.endsWith(".jpg") || mFilename.endsWith(".jpeg")
-                || mFilename.endsWith(".JPG") || mFilename.endsWith(".JPEG")) {
-            return MediaProperties.FILE_JPEG;
-        } else if (mFilename.endsWith(".png") || mFilename.endsWith(".PNG")) {
-            return MediaProperties.FILE_PNG;
-        } else {
-            return MediaProperties.FILE_UNSUPPORTED;
-        }
-    }
-
-    /**
-     * @return The scaled image file name
-     */
-    String getScaledImageFileName() {
-        return mScaledFilename;
-    }
-
-    /**
-     * @return The generated Kenburns clip height.
-     */
-    int getGeneratedClipHeight() {
-        return mGeneratedClipHeight;
-    }
-
-    /**
-     * @return The generated Kenburns clip width.
-     */
-    int getGeneratedClipWidth() {
-        return mGeneratedClipWidth;
-    }
-
-    /**
-     * @return The file name of image which is decoded and stored
-     * in RGB format
-     */
-    String getDecodedImageFileName() {
-        return mDecodedFilename;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getWidth() {
-        return mWidth;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getHeight() {
-        return mHeight;
-    }
-
-    /**
-     * @return The scaled width of the image.
-     */
-    public int getScaledWidth() {
-        return mScaledWidth;
-    }
-
-    /**
-     * @return The scaled height of the image.
-     */
-    public int getScaledHeight() {
-        return mScaledHeight;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getAspectRatio() {
-        return mAspectRatio;
-    }
-
-    /**
-     * This method will adjust the duration of bounding transitions, effects
-     * and overlays if the current duration of the transactions become greater
-     * than the maximum allowable duration.
-     *
-     * @param durationMs The duration of the image in the storyboard timeline
-     */
-    public void setDuration(long durationMs) {
-        if (durationMs == mDurationMs) {
-            return;
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        /**
-         * Invalidate the end transitions if necessary.
-         * This invalidation is necessary for the case in which an effect or
-         * an overlay is overlapping with the end transition
-         * (before the duration is changed) and it no longer overlaps with the
-         * transition after the duration is increased.
-         *
-         * The beginning transition does not need to be invalidated at this time
-         * because an effect or an overlay overlaps with the beginning
-         * transition, the begin transition is unaffected by a media item
-         * duration change.
-         */
-        invalidateEndTransition();
-
-        mDurationMs = durationMs;
-
-        adjustTransitions();
-        final List<Overlay> adjustedOverlays = adjustOverlays();
-        final List<Effect> adjustedEffects = adjustEffects();
-
-        /**
-         * Invalidate the beginning and end transitions after adjustments.
-         * This invalidation is necessary for the case in which an effect or
-         * an overlay was not overlapping with the beginning or end transitions
-         * before the setDuration reduces the duration of the media item and
-         * causes an overlap of the beginning and/or end transition with the
-         * effect.
-         */
-        invalidateBeginTransition(adjustedEffects, adjustedOverlays);
-        invalidateEndTransition();
-        if (getGeneratedImageClip() != null) {
-            /*
-             *  Delete the file
-             */
-            new File(getGeneratedImageClip()).delete();
-            /*
-             *  Invalidate the filename
-             */
-            setGeneratedImageClip(null);
-            super.setRegenerateClip(true);
-        }
-        mVideoEditor.updateTimelineDuration();
-    }
-
-    /**
-     * Invalidate the begin transition if any effects and overlays overlap
-     * with the begin transition.
-     *
-     * @param effects List of effects to check for transition overlap
-     * @param overlays List of overlays to check for transition overlap
-     */
-    private void invalidateBeginTransition(List<Effect> effects, List<Overlay> overlays) {
-        if (mBeginTransition != null && mBeginTransition.isGenerated()) {
-            final long transitionDurationMs = mBeginTransition.getDuration();
-
-            /**
-             *  The begin transition must be invalidated if it overlaps with
-             *  an effect.
-             */
-            for (Effect effect : effects) {
-                /**
-                 *  Check if the effect overlaps with the begin transition
-                 */
-                if (effect.getStartTime() < transitionDurationMs) {
-                    mBeginTransition.invalidate();
-                    break;
-                }
-            }
-
-            if (mBeginTransition.isGenerated()) {
-                /**
-                 *  The end transition must be invalidated if it overlaps with
-                 *  an overlay.
-                 */
-                for (Overlay overlay : overlays) {
-                    /**
-                     *  Check if the overlay overlaps with the end transition
-                     */
-                    if (overlay.getStartTime() < transitionDurationMs) {
-                        mBeginTransition.invalidate();
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Invalidate the end transition if any effects and overlays overlap
-     * with the end transition.
-     */
-    private void invalidateEndTransition() {
-        if (mEndTransition != null && mEndTransition.isGenerated()) {
-            final long transitionDurationMs = mEndTransition.getDuration();
-
-            /**
-             *  The end transition must be invalidated if it overlaps with
-             *  an effect.
-             */
-            final List<Effect> effects = getAllEffects();
-            for (Effect effect : effects) {
-                /**
-                 *  Check if the effect overlaps with the end transition
-                 */
-                if (effect.getStartTime() + effect.getDuration() >
-                    mDurationMs - transitionDurationMs) {
-                    mEndTransition.invalidate();
-                    break;
-                }
-            }
-
-            if (mEndTransition.isGenerated()) {
-                /**
-                 *  The end transition must be invalidated if it overlaps with
-                 *  an overlay.
-                 */
-                final List<Overlay> overlays = getAllOverlays();
-                for (Overlay overlay : overlays) {
-                    /**
-                     *  Check if the overlay overlaps with the end transition
-                     */
-                    if (overlay.getStartTime() + overlay.getDuration() >
-                        mDurationMs - transitionDurationMs) {
-                        mEndTransition.invalidate();
-                        break;
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Adjust the start time and/or duration of effects.
-     *
-     * @return The list of effects which were adjusted
-     */
-    private List<Effect> adjustEffects() {
-        final List<Effect> adjustedEffects = new ArrayList<Effect>();
-        final List<Effect> effects = getAllEffects();
-        for (Effect effect : effects) {
-            /**
-             *  Adjust the start time if necessary
-             */
-            final long effectStartTimeMs;
-            if (effect.getStartTime() > getDuration()) {
-                effectStartTimeMs = 0;
-            } else {
-                effectStartTimeMs = effect.getStartTime();
-            }
-
-            /**
-             *  Adjust the duration if necessary
-             */
-            final long effectDurationMs;
-            if (effectStartTimeMs + effect.getDuration() > getDuration()) {
-                effectDurationMs = getDuration() - effectStartTimeMs;
-            } else {
-                effectDurationMs = effect.getDuration();
-            }
-
-            if (effectStartTimeMs != effect.getStartTime() ||
-                    effectDurationMs != effect.getDuration()) {
-                effect.setStartTimeAndDuration(effectStartTimeMs, effectDurationMs);
-                adjustedEffects.add(effect);
-            }
-        }
-
-        return adjustedEffects;
-    }
-
-    /**
-     * Adjust the start time and/or duration of overlays.
-     *
-     * @return The list of overlays which were adjusted
-     */
-    private List<Overlay> adjustOverlays() {
-        final List<Overlay> adjustedOverlays = new ArrayList<Overlay>();
-        final List<Overlay> overlays = getAllOverlays();
-        for (Overlay overlay : overlays) {
-            /**
-             *  Adjust the start time if necessary
-             */
-            final long overlayStartTimeMs;
-            if (overlay.getStartTime() > getDuration()) {
-                overlayStartTimeMs = 0;
-            } else {
-                overlayStartTimeMs = overlay.getStartTime();
-            }
-
-            /**
-             *  Adjust the duration if necessary
-             */
-            final long overlayDurationMs;
-            if (overlayStartTimeMs + overlay.getDuration() > getDuration()) {
-                overlayDurationMs = getDuration() - overlayStartTimeMs;
-            } else {
-                overlayDurationMs = overlay.getDuration();
-            }
-
-            if (overlayStartTimeMs != overlay.getStartTime() ||
-                    overlayDurationMs != overlay.getDuration()) {
-                overlay.setStartTimeAndDuration(overlayStartTimeMs, overlayDurationMs);
-                adjustedOverlays.add(overlay);
-            }
-        }
-
-        return adjustedOverlays;
-    }
-    /**
-     * This function get the proper width by given aspect ratio
-     * and height.
-     *
-     * @param aspectRatio  Given aspect ratio
-     * @param height  Given height
-     */
-    private int getWidthByAspectRatioAndHeight(int aspectRatio, int height) {
-        int width = 0;
-
-        switch (aspectRatio) {
-            case MediaProperties.ASPECT_RATIO_3_2:
-                if (height == MediaProperties.HEIGHT_480)
-                    width = 720;
-                else if (height == MediaProperties.HEIGHT_720)
-                    width = 1080;
-                break;
-
-            case MediaProperties.ASPECT_RATIO_16_9:
-                if (height == MediaProperties.HEIGHT_360)
-                    width = 640;
-                else if (height == MediaProperties.HEIGHT_480)
-                    width = 854;
-                else if (height == MediaProperties.HEIGHT_720)
-                    width = 1280;
-                else if (height == MediaProperties.HEIGHT_1080)
-                    width = 1920;
-                break;
-
-            case MediaProperties.ASPECT_RATIO_4_3:
-                if (height == MediaProperties.HEIGHT_480)
-                    width = 640;
-                if (height == MediaProperties.HEIGHT_720)
-                    width = 960;
-                break;
-
-            case MediaProperties.ASPECT_RATIO_5_3:
-                if (height == MediaProperties.HEIGHT_480)
-                    width = 800;
-                break;
-
-            case MediaProperties.ASPECT_RATIO_11_9:
-                if (height == MediaProperties.HEIGHT_144)
-                    width = 176;
-                break;
-
-            default : {
-                throw new IllegalArgumentException(
-                    "Illegal arguments for aspectRatio");
-            }
-        }
-
-        return width;
-    }
-
-    /**
-     * This function sets the Ken Burn effect generated clip
-     * name.
-     *
-     * @param generatedFilePath The name of the generated clip
-     */
-    @Override
-    void setGeneratedImageClip(String generatedFilePath) {
-        super.setGeneratedImageClip(generatedFilePath);
-
-        // set the Kenburns clip width and height
-        mGeneratedClipHeight = getScaledHeight();
-        mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
-                mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
-    }
-
-    /**
-     * @return The name of the image clip
-     * generated with ken burns effect.
-     */
-    @Override
-    String getGeneratedImageClip() {
-        return super.getGeneratedImageClip();
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public long getTimelineDuration() {
-        return mDurationMs;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public Bitmap getThumbnail(int width, int height, long timeMs) throws IOException {
-        if (getGeneratedImageClip() != null) {
-            return mMANativeHelper.getPixels(getGeneratedImageClip(),
-                width, height, timeMs, 0);
-        } else {
-            return scaleImage(mFilename, width, height);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public void getThumbnailList(int width, int height,
-                                 long startMs, long endMs,
-                                 int thumbnailCount,
-                                 int[] indices,
-                                 GetThumbnailListCallback callback)
-                                 throws IOException {
-        //KenBurns was not applied on this.
-        if (getGeneratedImageClip() == null) {
-            final Bitmap thumbnail = scaleImage(mFilename, width, height);
-            for (int i = 0; i < indices.length; i++) {
-                callback.onThumbnail(thumbnail, indices[i]);
-            }
-        } else {
-            if (startMs > endMs) {
-                throw new IllegalArgumentException("Start time is greater than end time");
-            }
-
-            if (endMs > mDurationMs) {
-                throw new IllegalArgumentException("End time is greater than file duration");
-            }
-
-            mMANativeHelper.getPixelsList(getGeneratedImageClip(), width,
-                height, startMs, endMs, thumbnailCount, indices, callback, 0);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void invalidateTransitions(long startTimeMs, long durationMs) {
-        /**
-         *  Check if the item overlaps with the beginning and end transitions
-         */
-        if (mBeginTransition != null) {
-            if (isOverlapping(startTimeMs, durationMs, 0, mBeginTransition.getDuration())) {
-                mBeginTransition.invalidate();
-            }
-        }
-
-        if (mEndTransition != null) {
-            final long transitionDurationMs = mEndTransition.getDuration();
-            if (isOverlapping(startTimeMs, durationMs,
-                    getDuration() - transitionDurationMs, transitionDurationMs)) {
-                mEndTransition.invalidate();
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs,
-            long newDurationMs) {
-        /**
-         *  Check if the item overlaps with the beginning and end transitions
-         */
-        if (mBeginTransition != null) {
-            final long transitionDurationMs = mBeginTransition.getDuration();
-            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs, 0,
-                    transitionDurationMs);
-            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs, 0,
-                    transitionDurationMs);
-            /**
-             * Invalidate transition if:
-             *
-             * 1. New item overlaps the transition, the old one did not
-             * 2. New item does not overlap the transition, the old one did
-             * 3. New and old item overlap the transition if begin or end
-             * time changed
-             */
-            if (newOverlap != oldOverlap) { // Overlap has changed
-                mBeginTransition.invalidate();
-            } else if (newOverlap) { // Both old and new overlap
-                if ((oldStartTimeMs != newStartTimeMs) ||
-                        !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
-                        newStartTimeMs + newDurationMs > transitionDurationMs)) {
-                    mBeginTransition.invalidate();
-                }
-            }
-        }
-
-        if (mEndTransition != null) {
-            final long transitionDurationMs = mEndTransition.getDuration();
-            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
-                    mDurationMs - transitionDurationMs, transitionDurationMs);
-            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
-                    mDurationMs - transitionDurationMs, transitionDurationMs);
-            /**
-             * Invalidate transition if:
-             *
-             * 1. New item overlaps the transition, the old one did not
-             * 2. New item does not overlap the transition, the old one did
-             * 3. New and old item overlap the transition if begin or end
-             * time changed
-             */
-            if (newOverlap != oldOverlap) { // Overlap has changed
-                mEndTransition.invalidate();
-            } else if (newOverlap) { // Both old and new overlap
-                if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
-                        ((oldStartTimeMs > mDurationMs - transitionDurationMs) ||
-                        newStartTimeMs > mDurationMs - transitionDurationMs)) {
-                    mEndTransition.invalidate();
-                }
-            }
-        }
-    }
-
-    /**
-     * This function invalidates the rgb image clip,ken burns effect clip,
-     * and scaled image clip
-     */
-    void invalidate() {
-        if (getGeneratedImageClip() != null) {
-            new File(getGeneratedImageClip()).delete();
-            setGeneratedImageClip(null);
-            setRegenerateClip(true);
-        }
-
-        if (mScaledFilename != null) {
-            if(mFileName != mScaledFilename) {
-                new File(mScaledFilename).delete();
-            }
-            mScaledFilename = null;
-        }
-
-        if (mDecodedFilename != null) {
-            new File(mDecodedFilename).delete();
-            mDecodedFilename = null;
-        }
-    }
-
-    /**
-     * @param KenBurnEffect object.
-     * @return an Object of {@link ClipSettings} with Ken Burn settings
-     * needed to generate the clip
-     */
-    private ClipSettings getKenBurns(EffectKenBurns effectKB) {
-        int PanZoomXa;
-        int PanZoomXb;
-        int width = 0, height = 0;
-        Rect start = new Rect();
-        Rect end = new Rect();
-        ClipSettings clipSettings = null;
-        clipSettings = new ClipSettings();
-        /**
-         *  image:
-        ---------------------------------------
-       |    Xa                                  |
-       | Ya ---------------                     |
-       |    |                |                  |
-       |    |                |                  |
-       |     ---------------    Xb       ratioB |
-       |        ratioA           -------        |
-       |                  Yb    |        |      |
-       |                        |        |      |
-       |                         -------        |
-        ---------------------------------------
-         */
-
-        effectKB.getKenBurnsSettings(start, end);
-        width = getWidth();
-        height = getHeight();
-        if ((start.left < 0) || (start.left > width) || (start.right < 0) || (start.right > width)
-                || (start.top < 0) || (start.top > height) || (start.bottom < 0)
-                || (start.bottom > height) || (end.left < 0) || (end.left > width)
-                || (end.right < 0) || (end.right > width) || (end.top < 0) || (end.top > height)
-                || (end.bottom < 0) || (end.bottom > height)) {
-            throw new IllegalArgumentException("Illegal arguments for KebBurns");
-        }
-
-        if (((width - (start.right - start.left) == 0) || (height - (start.bottom - start.top) == 0))
-                && ((width - (end.right - end.left) == 0) || (height - (end.bottom - end.top) == 0))) {
-            setRegenerateClip(false);
-            clipSettings.clipPath = getDecodedImageFileName();
-            clipSettings.fileType = FileType.JPG;
-            clipSettings.beginCutTime = 0;
-            clipSettings.endCutTime = (int)getTimelineDuration();
-            clipSettings.beginCutPercent = 0;
-            clipSettings.endCutPercent = 0;
-            clipSettings.panZoomEnabled = false;
-            clipSettings.panZoomPercentStart = 0;
-            clipSettings.panZoomTopLeftXStart = 0;
-            clipSettings.panZoomTopLeftYStart = 0;
-            clipSettings.panZoomPercentEnd = 0;
-            clipSettings.panZoomTopLeftXEnd = 0;
-            clipSettings.panZoomTopLeftYEnd = 0;
-            clipSettings.mediaRendering = mMANativeHelper
-            .getMediaItemRenderingMode(getRenderingMode());
-
-            clipSettings.rgbWidth = getScaledWidth();
-            clipSettings.rgbHeight = getScaledHeight();
-
-            return clipSettings;
-        }
-
-        PanZoomXa = (1000 * start.width()) / width;
-        PanZoomXb = (1000 * end.width()) / width;
-
-        clipSettings.clipPath = getDecodedImageFileName();
-        clipSettings.fileType = mMANativeHelper.getMediaItemFileType(getFileType());
-        clipSettings.beginCutTime = 0;
-        clipSettings.endCutTime = (int)getTimelineDuration();
-        clipSettings.beginCutPercent = 0;
-        clipSettings.endCutPercent = 0;
-        clipSettings.panZoomEnabled = true;
-        clipSettings.panZoomPercentStart = PanZoomXa;
-        clipSettings.panZoomTopLeftXStart = (start.left * 1000) / width;
-        clipSettings.panZoomTopLeftYStart = (start.top * 1000) / height;
-        clipSettings.panZoomPercentEnd = PanZoomXb;
-        clipSettings.panZoomTopLeftXEnd = (end.left * 1000) / width;
-        clipSettings.panZoomTopLeftYEnd = (end.top * 1000) / height;
-        clipSettings.mediaRendering
-            = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
-
-        clipSettings.rgbWidth = getScaledWidth();
-        clipSettings.rgbHeight = getScaledHeight();
-
-        return clipSettings;
-    }
-
-
-    /**
-     * @param KenBurnEffect object.
-     * @return an Object of {@link ClipSettings} with Ken Burns
-     * generated clip name
-     */
-    ClipSettings generateKenburnsClip(EffectKenBurns effectKB) {
-        EditSettings editSettings = new EditSettings();
-        editSettings.clipSettingsArray = new ClipSettings[1];
-        String output = null;
-        ClipSettings clipSettings = new ClipSettings();
-        initClipSettings(clipSettings);
-        editSettings.clipSettingsArray[0] = getKenBurns(effectKB);
-        if ((getGeneratedImageClip() == null) && (getRegenerateClip())) {
-            output = mMANativeHelper.generateKenBurnsClip(editSettings, this);
-            setGeneratedImageClip(output);
-            setRegenerateClip(false);
-            clipSettings.clipPath = output;
-            clipSettings.fileType = FileType.THREE_GPP;
-
-            mGeneratedClipHeight = getScaledHeight();
-            mGeneratedClipWidth = getWidthByAspectRatioAndHeight(
-                    mVideoEditor.getAspectRatio(), mGeneratedClipHeight);
-        } else {
-            if (getGeneratedImageClip() == null) {
-                clipSettings.clipPath = getDecodedImageFileName();
-                clipSettings.fileType = FileType.JPG;
-
-                clipSettings.rgbWidth = getScaledWidth();
-                clipSettings.rgbHeight = getScaledHeight();
-
-            } else {
-                clipSettings.clipPath = getGeneratedImageClip();
-                clipSettings.fileType = FileType.THREE_GPP;
-            }
-        }
-        clipSettings.mediaRendering = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
-        clipSettings.beginCutTime = 0;
-        clipSettings.endCutTime = (int)getTimelineDuration();
-
-        return clipSettings;
-    }
-
-    /**
-     * @return an Object of {@link ClipSettings} with Image Clip
-     * properties data populated.If the image has Ken Burns effect applied,
-     * then file path contains generated image clip name with Ken Burns effect
-     */
-    ClipSettings getImageClipProperties() {
-        ClipSettings clipSettings = new ClipSettings();
-        List<Effect> effects = null;
-        EffectKenBurns effectKB = null;
-        boolean effectKBPresent = false;
-
-        effects = getAllEffects();
-        for (Effect effect : effects) {
-            if (effect instanceof EffectKenBurns) {
-                effectKB = (EffectKenBurns)effect;
-                effectKBPresent = true;
-                break;
-            }
-        }
-
-        if (effectKBPresent) {
-            clipSettings = generateKenburnsClip(effectKB);
-        } else {
-            /**
-             * Init the clip settings object
-             */
-            initClipSettings(clipSettings);
-            clipSettings.clipPath = getDecodedImageFileName();
-            clipSettings.fileType = FileType.JPG;
-            clipSettings.beginCutTime = 0;
-            clipSettings.endCutTime = (int)getTimelineDuration();
-            clipSettings.mediaRendering = mMANativeHelper
-                .getMediaItemRenderingMode(getRenderingMode());
-            clipSettings.rgbWidth = getScaledWidth();
-            clipSettings.rgbHeight = getScaledHeight();
-
-        }
-        return clipSettings;
-    }
-
-    /**
-     * Resize a bitmap to the specified width and height
-     *
-     * @param filename The filename
-     * @param width The thumbnail width
-     * @param height The thumbnail height
-     *
-     * @return The resized bitmap
-     */
-    private Bitmap scaleImage(String filename, int width, int height)
-    throws IOException {
-        final BitmapFactory.Options dbo = new BitmapFactory.Options();
-        dbo.inJustDecodeBounds = true;
-        BitmapFactory.decodeFile(filename, dbo);
-
-        final int nativeWidth = dbo.outWidth;
-        final int nativeHeight = dbo.outHeight;
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "generateThumbnail: Input: " + nativeWidth + "x" + nativeHeight
-                    + ", resize to: " + width + "x" + height);
-        }
-
-        final Bitmap srcBitmap;
-        float bitmapWidth, bitmapHeight;
-        if (nativeWidth > width || nativeHeight > height) {
-            float dx = ((float)nativeWidth) / ((float)width);
-            float dy = ((float)nativeHeight) / ((float)height);
-
-            if (dx > dy) {
-                bitmapWidth = width;
-
-                if (((float)nativeHeight / dx) < (float)height) {
-                    bitmapHeight = (float)Math.ceil(nativeHeight / dx);
-                } else { // value equals the requested height
-                    bitmapHeight = (float)Math.floor(nativeHeight / dx);
-                }
-
-            } else {
-                if (((float)nativeWidth / dy) > (float)width) {
-                    bitmapWidth = (float)Math.floor(nativeWidth / dy);
-                } else { // value equals the requested width
-                    bitmapWidth = (float)Math.ceil(nativeWidth / dy);
-                }
-
-                bitmapHeight = height;
-            }
-
-            /**
-             *  Create the bitmap from file
-             */
-            int sampleSize = (int) Math.ceil(Math.max(
-                    (float) nativeWidth / bitmapWidth,
-                    (float) nativeHeight / bitmapHeight));
-            sampleSize = nextPowerOf2(sampleSize);
-            final BitmapFactory.Options options = new BitmapFactory.Options();
-            options.inSampleSize = sampleSize;
-            srcBitmap = BitmapFactory.decodeFile(filename, options);
-        } else {
-            bitmapWidth = width;
-            bitmapHeight = height;
-            srcBitmap = BitmapFactory.decodeFile(filename);
-
-        }
-
-        if (srcBitmap == null) {
-            Log.e(TAG, "generateThumbnail: Cannot decode image bytes");
-            throw new IOException("Cannot decode file: " + mFilename);
-        }
-
-        /**
-         *  Create the canvas bitmap
-         */
-        final Bitmap bitmap = Bitmap.createBitmap((int)bitmapWidth,
-                                                  (int)bitmapHeight,
-                                                  Bitmap.Config.ARGB_8888);
-        final Canvas canvas = new Canvas(bitmap);
-        canvas.drawBitmap(srcBitmap, new Rect(0, 0, srcBitmap.getWidth(),
-                                              srcBitmap.getHeight()),
-                                              new Rect(0, 0, (int)bitmapWidth,
-                                              (int)bitmapHeight), sResizePaint);
-        canvas.setBitmap(null);
-        /**
-         *  Release the source bitmap
-         */
-        srcBitmap.recycle();
-        return bitmap;
-    }
-
-    public static int nextPowerOf2(int n) {
-        n -= 1;
-        n |= n >>> 16;
-        n |= n >>> 8;
-        n |= n >>> 4;
-        n |= n >>> 2;
-        n |= n >>> 1;
-        return n + 1;
-    }
-}
diff --git a/media/java/android/media/videoeditor/MediaItem.java b/media/java/android/media/videoeditor/MediaItem.java
deleted file mode 100644
index 4e9ea75..0000000
--- a/media/java/android/media/videoeditor/MediaItem.java
+++ /dev/null
@@ -1,814 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
-
-import java.io.DataOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.FileType;
-import android.media.videoeditor.MediaArtistNativeHelper.MediaRendering;
-
-/**
- * This abstract class describes the base class for any MediaItem. Objects are
- * defined with a file path as a source data.
- * {@hide}
- */
-public abstract class MediaItem {
-    /**
-     *  A constant which can be used to specify the end of the file (instead of
-     *  providing the actual duration of the media item).
-     */
-    public final static int END_OF_FILE = -1;
-
-    /**
-     *  Rendering modes
-     */
-    /**
-     * When using the RENDERING_MODE_BLACK_BORDER rendering mode video frames
-     * are resized by preserving the aspect ratio until the movie matches one of
-     * the dimensions of the output movie. The areas outside the resized video
-     * clip are rendered black.
-     */
-    public static final int RENDERING_MODE_BLACK_BORDER = 0;
-
-    /**
-     * When using the RENDERING_MODE_STRETCH rendering mode video frames are
-     * stretched horizontally or vertically to match the current aspect ratio of
-     * the video editor.
-     */
-    public static final int RENDERING_MODE_STRETCH = 1;
-
-    /**
-     * When using the RENDERING_MODE_CROPPING rendering mode video frames are
-     * scaled horizontally or vertically by preserving the original aspect ratio
-     * of the media item.
-     */
-    public static final int RENDERING_MODE_CROPPING = 2;
-
-    /**
-     *  The unique id of the MediaItem
-     */
-    private final String mUniqueId;
-
-    /**
-     *  The name of the file associated with the MediaItem
-     */
-    protected final String mFilename;
-
-    /**
-     *  List of effects
-     */
-    private final List<Effect> mEffects;
-
-    /**
-     *  List of overlays
-     */
-    private final List<Overlay> mOverlays;
-
-    /**
-     *  The rendering mode
-     */
-    private int mRenderingMode;
-
-    private final MediaArtistNativeHelper mMANativeHelper;
-
-    private final String mProjectPath;
-
-    /**
-     *  Beginning and end transitions
-     */
-    protected Transition mBeginTransition;
-
-    protected Transition mEndTransition;
-
-    protected String mGeneratedImageClip;
-
-    protected boolean mRegenerateClip;
-
-    private boolean mBlankFrameGenerated = false;
-
-    private String mBlankFrameFilename = null;
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param mediaItemId The MediaItem id
-     * @param filename name of the media file.
-     * @param renderingMode The rendering mode
-     * @throws IOException if file is not found
-     * @throws IllegalArgumentException if a capability such as file format is
-     *             not supported the exception object contains the unsupported
-     *             capability
-     */
-    protected MediaItem(VideoEditor editor, String mediaItemId, String filename,
-                        int renderingMode) throws IOException {
-        if (filename == null) {
-            throw new IllegalArgumentException("MediaItem : filename is null");
-        }
-        File file = new File(filename);
-        if (!file.exists()) {
-            throw new IOException(filename + " not found ! ");
-        }
-
-        /*Compare file_size with 2GB*/
-        if (VideoEditor.MAX_SUPPORTED_FILE_SIZE <= file.length()) {
-            throw new IllegalArgumentException("File size is more than 2GB");
-        }
-        mUniqueId = mediaItemId;
-        mFilename = filename;
-        mRenderingMode = renderingMode;
-        mEffects = new ArrayList<Effect>();
-        mOverlays = new ArrayList<Overlay>();
-        mBeginTransition = null;
-        mEndTransition = null;
-        mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
-        mProjectPath = editor.getPath();
-        mRegenerateClip = false;
-        mGeneratedImageClip = null;
-    }
-
-    /**
-     * @return The id of the media item
-     */
-    public String getId() {
-        return mUniqueId;
-    }
-
-    /**
-     * @return The media source file name
-     */
-    public String getFilename() {
-        return mFilename;
-    }
-
-    /**
-     * If aspect ratio of the MediaItem is different from the aspect ratio of
-     * the editor then this API controls the rendering mode.
-     *
-     * @param renderingMode rendering mode. It is one of:
-     *            {@link #RENDERING_MODE_BLACK_BORDER},
-     *            {@link #RENDERING_MODE_STRETCH}
-     */
-    public void setRenderingMode(int renderingMode) {
-        switch (renderingMode) {
-            case RENDERING_MODE_BLACK_BORDER:
-            case RENDERING_MODE_STRETCH:
-            case RENDERING_MODE_CROPPING:
-                break;
-
-            default:
-                throw new IllegalArgumentException("Invalid Rendering Mode");
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        mRenderingMode = renderingMode;
-        if (mBeginTransition != null) {
-            mBeginTransition.invalidate();
-        }
-
-        if (mEndTransition != null) {
-            mEndTransition.invalidate();
-        }
-
-        for (Overlay overlay : mOverlays) {
-            ((OverlayFrame)overlay).invalidateGeneratedFiles();
-        }
-    }
-
-    /**
-     * @return The rendering mode
-     */
-    public int getRenderingMode() {
-        return mRenderingMode;
-    }
-
-    /**
-     * @param transition The beginning transition
-     */
-    void setBeginTransition(Transition transition) {
-        mBeginTransition = transition;
-    }
-
-    /**
-     * @return The begin transition
-     */
-    public Transition getBeginTransition() {
-        return mBeginTransition;
-    }
-
-    /**
-     * @param transition The end transition
-     */
-    void setEndTransition(Transition transition) {
-        mEndTransition = transition;
-    }
-
-    /**
-     * @return The end transition
-     */
-    public Transition getEndTransition() {
-        return mEndTransition;
-    }
-
-    /**
-     * @return The timeline duration. This is the actual duration in the
-     *         timeline (trimmed duration)
-     */
-    public abstract long getTimelineDuration();
-
-    /**
-     * @return The is the full duration of the media item (not trimmed)
-     */
-    public abstract long getDuration();
-
-    /**
-     * @return The source file type
-     */
-    public abstract int getFileType();
-
-    /**
-     * @return Get the native width of the media item
-     */
-    public abstract int getWidth();
-
-    /**
-     * @return Get the native height of the media item
-     */
-    public abstract int getHeight();
-
-    /**
-     * Get aspect ratio of the source media item.
-     *
-     * @return the aspect ratio as described in MediaProperties.
-     *         MediaProperties.ASPECT_RATIO_UNDEFINED if aspect ratio is not
-     *         supported as in MediaProperties
-     */
-    public abstract int getAspectRatio();
-
-    /**
-     * Add the specified effect to this media item.
-     *
-     * Note that certain types of effects cannot be applied to video and to
-     * image media items. For example in certain implementation a Ken Burns
-     * implementation cannot be applied to video media item.
-     *
-     * This method invalidates transition video clips if the
-     * effect overlaps with the beginning and/or the end transition.
-     *
-     * @param effect The effect to apply
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if the effect start and/or duration are
-     *      invalid or if the effect cannot be applied to this type of media
-     *      item or if the effect id is not unique across all the Effects
-     *      added.
-     */
-    public void addEffect(Effect effect) {
-
-        if (effect == null) {
-            throw new IllegalArgumentException("NULL effect cannot be applied");
-        }
-
-        if (effect.getMediaItem() != this) {
-            throw new IllegalArgumentException("Media item mismatch");
-        }
-
-        if (mEffects.contains(effect)) {
-            throw new IllegalArgumentException("Effect already exists: " + effect.getId());
-        }
-
-        if (effect.getStartTime() + effect.getDuration() > getDuration()) {
-            throw new IllegalArgumentException(
-            "Effect start time + effect duration > media clip duration");
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        mEffects.add(effect);
-
-        invalidateTransitions(effect.getStartTime(), effect.getDuration());
-
-        if (effect instanceof EffectKenBurns) {
-            mRegenerateClip = true;
-        }
-    }
-
-    /**
-     * Remove the effect with the specified id.
-     *
-     * This method invalidates a transition video clip if the effect overlaps
-     * with a transition.
-     *
-     * @param effectId The id of the effect to be removed
-     *
-     * @return The effect that was removed
-     * @throws IllegalStateException if a preview or an export is in progress
-     */
-    public Effect removeEffect(String effectId) {
-        for (Effect effect : mEffects) {
-            if (effect.getId().equals(effectId)) {
-                mMANativeHelper.setGeneratePreview(true);
-
-                mEffects.remove(effect);
-
-                invalidateTransitions(effect.getStartTime(), effect.getDuration());
-                if (effect instanceof EffectKenBurns) {
-                    if (mGeneratedImageClip != null) {
-                        /**
-                         *  Delete the file
-                         */
-                        new File(mGeneratedImageClip).delete();
-                        /**
-                         *  Invalidate the filename
-                         */
-                        mGeneratedImageClip = null;
-                    }
-                    mRegenerateClip = false;
-                }
-                return effect;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Set the filepath of the generated image clip when the effect is added.
-     *
-     * @param The filepath of the generated image clip.
-     */
-    void setGeneratedImageClip(String generatedFilePath) {
-        mGeneratedImageClip = generatedFilePath;
-    }
-
-    /**
-     * Get the filepath of the generated image clip when the effect is added.
-     *
-     * @return The filepath of the generated image clip (null if it does not
-     *         exist)
-     */
-    String getGeneratedImageClip() {
-        return mGeneratedImageClip;
-    }
-
-    /**
-     * Find the effect with the specified id
-     *
-     * @param effectId The effect id
-     * @return The effect with the specified id (null if it does not exist)
-     */
-    public Effect getEffect(String effectId) {
-        for (Effect effect : mEffects) {
-            if (effect.getId().equals(effectId)) {
-                return effect;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Get the list of effects.
-     *
-     * @return the effects list. If no effects exist an empty list will be
-     *         returned.
-     */
-    public List<Effect> getAllEffects() {
-        return mEffects;
-    }
-
-    /**
-     * Add an overlay to the storyboard. This method invalidates a transition
-     * video clip if the overlay overlaps with a transition.
-     *
-     * @param overlay The overlay to add
-     * @throws IllegalStateException if a preview or an export is in progress or
-     *             if the overlay id is not unique across all the overlays added
-     *             or if the bitmap is not specified or if the dimensions of the
-     *             bitmap do not match the dimensions of the media item
-     * @throws FileNotFoundException, IOException if overlay could not be saved
-     *             to project path
-     */
-    public void addOverlay(Overlay overlay) throws FileNotFoundException, IOException {
-        if (overlay == null) {
-            throw new IllegalArgumentException("NULL Overlay cannot be applied");
-        }
-
-        if (overlay.getMediaItem() != this) {
-            throw new IllegalArgumentException("Media item mismatch");
-        }
-
-        if (mOverlays.contains(overlay)) {
-            throw new IllegalArgumentException("Overlay already exists: " + overlay.getId());
-        }
-
-        if (overlay.getStartTime() + overlay.getDuration() > getDuration()) {
-            throw new IllegalArgumentException(
-            "Overlay start time + overlay duration > media clip duration");
-        }
-
-        if (overlay instanceof OverlayFrame) {
-            final OverlayFrame frame = (OverlayFrame)overlay;
-            final Bitmap bitmap = frame.getBitmap();
-            if (bitmap == null) {
-                throw new IllegalArgumentException("Overlay bitmap not specified");
-            }
-
-            final int scaledWidth, scaledHeight;
-            if (this instanceof MediaVideoItem) {
-                scaledWidth = getWidth();
-                scaledHeight = getHeight();
-            } else {
-                scaledWidth = ((MediaImageItem)this).getScaledWidth();
-                scaledHeight = ((MediaImageItem)this).getScaledHeight();
-            }
-
-            /**
-             * The dimensions of the overlay bitmap must be the same as the
-             * media item dimensions
-             */
-            if (bitmap.getWidth() != scaledWidth || bitmap.getHeight() != scaledHeight) {
-                throw new IllegalArgumentException(
-                "Bitmap dimensions must match media item dimensions");
-            }
-
-            mMANativeHelper.setGeneratePreview(true);
-            ((OverlayFrame)overlay).save(mProjectPath);
-
-            mOverlays.add(overlay);
-            invalidateTransitions(overlay.getStartTime(), overlay.getDuration());
-
-        } else {
-            throw new IllegalArgumentException("Overlay not supported");
-        }
-    }
-
-    /**
-     * @param flag The flag to indicate if regeneration of clip is true or
-     *            false.
-     */
-    void setRegenerateClip(boolean flag) {
-        mRegenerateClip = flag;
-    }
-
-    /**
-     * @return flag The flag to indicate if regeneration of clip is true or
-     *         false.
-     */
-    boolean getRegenerateClip() {
-        return mRegenerateClip;
-    }
-
-    /**
-     * Remove the overlay with the specified id.
-     *
-     * This method invalidates a transition video clip if the overlay overlaps
-     * with a transition.
-     *
-     * @param overlayId The id of the overlay to be removed
-     *
-     * @return The overlay that was removed
-     * @throws IllegalStateException if a preview or an export is in progress
-     */
-    public Overlay removeOverlay(String overlayId) {
-        for (Overlay overlay : mOverlays) {
-            if (overlay.getId().equals(overlayId)) {
-                mMANativeHelper.setGeneratePreview(true);
-
-                mOverlays.remove(overlay);
-                if (overlay instanceof OverlayFrame) {
-                    ((OverlayFrame)overlay).invalidate();
-                }
-                invalidateTransitions(overlay.getStartTime(), overlay.getDuration());
-                return overlay;
-            }
-        }
-        return null;
-    }
-
-    /**
-     * Find the overlay with the specified id
-     *
-     * @param overlayId The overlay id
-     *
-     * @return The overlay with the specified id (null if it does not exist)
-     */
-    public Overlay getOverlay(String overlayId) {
-        for (Overlay overlay : mOverlays) {
-            if (overlay.getId().equals(overlayId)) {
-                return overlay;
-            }
-        }
-
-        return null;
-    }
-
-    /**
-     * Get the list of overlays associated with this media item
-     *
-     * Note that if any overlay source files are not accessible anymore,
-     * this method will still provide the full list of overlays.
-     *
-     * @return The list of overlays. If no overlays exist an empty list will
-     *         be returned.
-     */
-    public List<Overlay> getAllOverlays() {
-        return mOverlays;
-    }
-
-    /**
-     * Create a thumbnail at specified time in a video stream in Bitmap format
-     *
-     * @param width width of the thumbnail in pixels
-     * @param height height of the thumbnail in pixels
-     * @param timeMs The time in the source video file at which the thumbnail is
-     *            requested (even if trimmed).
-     *
-     * @return The thumbnail as a Bitmap.
-     *
-     * @throws IOException if a file error occurs
-     * @throws IllegalArgumentException if time is out of video duration
-     */
-    public abstract Bitmap getThumbnail(int width, int height, long timeMs)
-                                        throws IOException;
-
-    /**
-     * Get the array of Bitmap thumbnails between start and end.
-     *
-     * @param width width of the thumbnail in pixels
-     * @param height height of the thumbnail in pixels
-     * @param startMs The start of time range in milliseconds
-     * @param endMs The end of the time range in milliseconds
-     * @param thumbnailCount The thumbnail count
-     * @param indices The indices of the thumbnails wanted
-     * @param callback The callback used to pass back the bitmaps
-     *
-     * @throws IOException if a file error occurs
-     */
-    public abstract void getThumbnailList(int width, int height,
-                                          long startMs, long endMs,
-                                          int thumbnailCount,
-                                          int[] indices,
-                                          GetThumbnailListCallback callback)
-                                          throws IOException;
-
-    public interface GetThumbnailListCallback {
-        public void onThumbnail(Bitmap bitmap, int index);
-    }
-
-    // This is for compatibility, only used in tests.
-    public Bitmap[] getThumbnailList(int width, int height,
-                                     long startMs, long endMs,
-                                     int thumbnailCount)
-                                     throws IOException {
-        final Bitmap[] bitmaps = new Bitmap[thumbnailCount];
-        int[] indices = new int[thumbnailCount];
-        for (int i = 0; i < thumbnailCount; i++) {
-            indices[i] = i;
-        }
-        getThumbnailList(width, height, startMs, endMs,
-                thumbnailCount, indices, new GetThumbnailListCallback() {
-            public void onThumbnail(Bitmap bitmap, int index) {
-                bitmaps[index] = bitmap;
-            }
-        });
-
-        return bitmaps;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (!(object instanceof MediaItem)) {
-            return false;
-        }
-        return mUniqueId.equals(((MediaItem)object).mUniqueId);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return mUniqueId.hashCode();
-    }
-
-    /**
-     * Invalidate the start and end transitions if necessary
-     *
-     * @param startTimeMs The start time of the effect or overlay
-     * @param durationMs The duration of the effect or overlay
-     */
-    abstract void invalidateTransitions(long startTimeMs, long durationMs);
-
-    /**
-     * Invalidate the start and end transitions if necessary. This method is
-     * typically called when the start time and/or duration of an overlay or
-     * effect is changing.
-     *
-     * @param oldStartTimeMs The old start time of the effect or overlay
-     * @param oldDurationMs The old duration of the effect or overlay
-     * @param newStartTimeMs The new start time of the effect or overlay
-     * @param newDurationMs The new duration of the effect or overlay
-     */
-    abstract void invalidateTransitions(long oldStartTimeMs, long oldDurationMs,
-            long newStartTimeMs, long newDurationMs);
-
-    /**
-     * Check if two items overlap in time
-     *
-     * @param startTimeMs1 Item 1 start time
-     * @param durationMs1 Item 1 duration
-     * @param startTimeMs2 Item 2 start time
-     * @param durationMs2 Item 2 end time
-     * @return true if the two items overlap
-     */
-    protected boolean isOverlapping(long startTimeMs1, long durationMs1,
-                                    long startTimeMs2, long durationMs2) {
-        if (startTimeMs1 + durationMs1 <= startTimeMs2) {
-            return false;
-        } else if (startTimeMs1 >= startTimeMs2 + durationMs2) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
-     * Adjust the duration transitions.
-     */
-    protected void adjustTransitions() {
-        /**
-         *  Check if the duration of transitions need to be adjusted
-         */
-        if (mBeginTransition != null) {
-            final long maxDurationMs = mBeginTransition.getMaximumDuration();
-            if (mBeginTransition.getDuration() > maxDurationMs) {
-                mBeginTransition.setDuration(maxDurationMs);
-            }
-        }
-
-        if (mEndTransition != null) {
-            final long maxDurationMs = mEndTransition.getMaximumDuration();
-            if (mEndTransition.getDuration() > maxDurationMs) {
-                mEndTransition.setDuration(maxDurationMs);
-            }
-        }
-    }
-
-    /**
-     * @return MediaArtistNativeHleper context
-     */
-    MediaArtistNativeHelper getNativeContext() {
-        return mMANativeHelper;
-    }
-
-    /**
-     * Initialises ClipSettings fields to default value
-     *
-     * @param ClipSettings object
-     *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
-     */
-    void initClipSettings(ClipSettings clipSettings) {
-        clipSettings.clipPath = null;
-        clipSettings.clipDecodedPath = null;
-        clipSettings.clipOriginalPath = null;
-        clipSettings.fileType = 0;
-        clipSettings.endCutTime = 0;
-        clipSettings.beginCutTime = 0;
-        clipSettings.beginCutPercent = 0;
-        clipSettings.endCutPercent = 0;
-        clipSettings.panZoomEnabled = false;
-        clipSettings.panZoomPercentStart = 0;
-        clipSettings.panZoomTopLeftXStart = 0;
-        clipSettings.panZoomTopLeftYStart = 0;
-        clipSettings.panZoomPercentEnd = 0;
-        clipSettings.panZoomTopLeftXEnd = 0;
-        clipSettings.panZoomTopLeftYEnd = 0;
-        clipSettings.mediaRendering = 0;
-        clipSettings.rgbWidth = 0;
-        clipSettings.rgbHeight = 0;
-    }
-
-    /**
-     * @return ClipSettings object with populated data
-     *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
-     */
-    ClipSettings getClipSettings() {
-        MediaVideoItem mVI = null;
-        MediaImageItem mII = null;
-        ClipSettings clipSettings = new ClipSettings();
-        initClipSettings(clipSettings);
-        if (this instanceof MediaVideoItem) {
-            mVI = (MediaVideoItem)this;
-            clipSettings.clipPath = mVI.getFilename();
-            clipSettings.fileType = mMANativeHelper.getMediaItemFileType(mVI.
-                                                                 getFileType());
-            clipSettings.beginCutTime = (int)mVI.getBoundaryBeginTime();
-            clipSettings.endCutTime = (int)mVI.getBoundaryEndTime();
-            clipSettings.mediaRendering = mMANativeHelper.
-                                          getMediaItemRenderingMode(mVI
-                                          .getRenderingMode());
-        } else if (this instanceof MediaImageItem) {
-            mII = (MediaImageItem)this;
-            clipSettings = mII.getImageClipProperties();
-        }
-        return clipSettings;
-    }
-
-    /**
-     * Generates a black frame to be used for generating
-     * begin transition at first media item in storyboard
-     * or end transition at last media item in storyboard
-     *
-     * @param ClipSettings object
-     *{@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
-     */
-    void generateBlankFrame(ClipSettings clipSettings) {
-        if (!mBlankFrameGenerated) {
-            int mWidth = 64;
-            int mHeight = 64;
-            mBlankFrameFilename = String.format(mProjectPath + "/" + "ghost.rgb");
-            FileOutputStream fl = null;
-            try {
-                 fl = new FileOutputStream(mBlankFrameFilename);
-            } catch (IOException e) {
-                /* catch IO exception */
-            }
-            final DataOutputStream dos = new DataOutputStream(fl);
-
-            final int [] framingBuffer = new int[mWidth];
-
-            ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
-            IntBuffer intBuffer;
-
-            byte[] array = byteBuffer.array();
-            int tmp = 0;
-            while(tmp < mHeight) {
-                intBuffer = byteBuffer.asIntBuffer();
-                intBuffer.put(framingBuffer,0,mWidth);
-                try {
-                    dos.write(array);
-                } catch (IOException e) {
-                    /* catch file write error */
-                }
-                tmp += 1;
-            }
-
-            try {
-                fl.close();
-            } catch (IOException e) {
-                /* file close error */
-            }
-            mBlankFrameGenerated = true;
-        }
-
-        clipSettings.clipPath = mBlankFrameFilename;
-        clipSettings.fileType = FileType.JPG;
-        clipSettings.beginCutTime = 0;
-        clipSettings.endCutTime = 0;
-        clipSettings.mediaRendering = MediaRendering.RESIZING;
-
-        clipSettings.rgbWidth = 64;
-        clipSettings.rgbHeight = 64;
-    }
-
-    /**
-     * Invalidates the blank frame generated
-     */
-    void invalidateBlankFrame() {
-        if (mBlankFrameFilename != null) {
-            if (new File(mBlankFrameFilename).exists()) {
-                new File(mBlankFrameFilename).delete();
-                mBlankFrameFilename = null;
-            }
-        }
-    }
-
-}
diff --git a/media/java/android/media/videoeditor/MediaProperties.java b/media/java/android/media/videoeditor/MediaProperties.java
deleted file mode 100644
index cf518a5..0000000
--- a/media/java/android/media/videoeditor/MediaProperties.java
+++ /dev/null
@@ -1,445 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-import android.media.videoeditor.VideoEditorProfile;
-import android.util.Pair;
-import java.lang.System;
-/**
- * This class defines all properties of a media file such as supported height,
- * aspect ratio, bitrate for export function.
- * {@hide}
- */
-public class MediaProperties {
-    /**
-     *  Supported heights
-     */
-    public static final int HEIGHT_144 = 144;
-    public static final int HEIGHT_288 = 288;
-    public static final int HEIGHT_360 = 360;
-    public static final int HEIGHT_480 = 480;
-    public static final int HEIGHT_720 = 720;
-    public static final int HEIGHT_1080 = 1080;
-
-    /**
-     *  Supported aspect ratios
-     */
-    public static final int ASPECT_RATIO_UNDEFINED = 0;
-    public static final int ASPECT_RATIO_3_2 = 1;
-    public static final int ASPECT_RATIO_16_9 = 2;
-    public static final int ASPECT_RATIO_4_3 = 3;
-    public static final int ASPECT_RATIO_5_3 = 4;
-    public static final int ASPECT_RATIO_11_9 = 5;
-
-    /**
-     *  The array of supported aspect ratios
-     */
-    private static final int[] ASPECT_RATIOS = new int[] {
-        ASPECT_RATIO_3_2,
-        ASPECT_RATIO_16_9,
-        ASPECT_RATIO_4_3,
-        ASPECT_RATIO_5_3,
-        ASPECT_RATIO_11_9
-    };
-
-    /**
-     *  Supported resolutions for specific aspect ratios
-     */
-    @SuppressWarnings({"unchecked"})
-    private static final Pair<Integer, Integer>[] ASPECT_RATIO_3_2_RESOLUTIONS =
-        new Pair[] {
-        new Pair<Integer, Integer>(720, HEIGHT_480),
-        new Pair<Integer, Integer>(1080, HEIGHT_720)
-    };
-
-    @SuppressWarnings({"unchecked"})
-    private static final Pair<Integer, Integer>[] ASPECT_RATIO_4_3_RESOLUTIONS =
-        new Pair[] {
-        new Pair<Integer, Integer>(640, HEIGHT_480),
-        new Pair<Integer, Integer>(960, HEIGHT_720)
-    };
-
-    @SuppressWarnings({"unchecked"})
-    private static final Pair<Integer, Integer>[] ASPECT_RATIO_5_3_RESOLUTIONS =
-        new Pair[] {
-        new Pair<Integer, Integer>(800, HEIGHT_480)
-    };
-
-    @SuppressWarnings({"unchecked"})
-    private static final Pair<Integer, Integer>[] ASPECT_RATIO_11_9_RESOLUTIONS =
-        new Pair[] {
-        new Pair<Integer, Integer>(176, HEIGHT_144),
-        new Pair<Integer, Integer>(352, HEIGHT_288)
-    };
-
-    @SuppressWarnings({"unchecked"})
-    private static final Pair<Integer, Integer>[] ASPECT_RATIO_16_9_RESOLUTIONS =
-        new Pair[] {
-        new Pair<Integer, Integer>(848, HEIGHT_480),
-        new Pair<Integer, Integer>(1280, HEIGHT_720),
-        new Pair<Integer, Integer>(1920, HEIGHT_1080),
-    };
-
-    /**
-     *  Bitrate values (in bits per second)
-     */
-    public static final int BITRATE_28K = 28000;
-    public static final int BITRATE_40K = 40000;
-    public static final int BITRATE_64K = 64000;
-    public static final int BITRATE_96K = 96000;
-    public static final int BITRATE_128K = 128000;
-    public static final int BITRATE_192K = 192000;
-    public static final int BITRATE_256K = 256000;
-    public static final int BITRATE_384K = 384000;
-    public static final int BITRATE_512K = 512000;
-    public static final int BITRATE_800K = 800000;
-    public static final int BITRATE_2M = 2000000;
-    public static final int BITRATE_5M = 5000000;
-    public static final int BITRATE_8M = 8000000;
-
-    /**
-     *  The array of supported bitrates
-     */
-    private static final int[] SUPPORTED_BITRATES = new int[] {
-        BITRATE_28K,
-        BITRATE_40K,
-        BITRATE_64K,
-        BITRATE_96K,
-        BITRATE_128K,
-        BITRATE_192K,
-        BITRATE_256K,
-        BITRATE_384K,
-        BITRATE_512K,
-        BITRATE_800K,
-        BITRATE_2M,
-        BITRATE_5M,
-        BITRATE_8M
-    };
-
-    /**
-     *  Video codec types
-     */
-    public static final int VCODEC_H263 = 1;
-    public static final int VCODEC_H264 = 2;
-    public static final int VCODEC_MPEG4 = 3;
-
-    /**
-     *  The array of supported video codecs
-     */
-    private static final int[] SUPPORTED_VCODECS = new int[] {
-        VCODEC_H264,
-        VCODEC_H263,
-        VCODEC_MPEG4,
-    };
-
-    /**
-     *  The H264 profile, the values are same as the one in OMX_Video.h
-     */
-    public final class H264Profile {
-        public static final int H264ProfileBaseline = 0x01; /**< Baseline profile */
-        public static final int H264ProfileMain     = 0x02; /**< Main profile */
-        public static final int H264ProfileExtended = 0x04; /**< Extended profile */
-        public static final int H264ProfileHigh     = 0x08; /**< High profile */
-        public static final int H264ProfileHigh10   = 0x10; /**< High 10 profile */
-        public static final int H264ProfileHigh422  = 0x20; /**< High 4:2:2 profile */
-        public static final int H264ProfileHigh444  = 0x40; /**< High 4:4:4 profile */
-        public static final int H264ProfileUnknown  = 0x7FFFFFFF;
-   }
-    /**
-     *  The H264 level, the values are same as the one in OMX_Video.h
-     */
-    public final class H264Level {
-        public static final int H264Level1   = 0x01; /**< Level 1 */
-        public static final int H264Level1b  = 0x02; /**< Level 1b */
-        public static final int H264Level11  = 0x04; /**< Level 1.1 */
-        public static final int H264Level12  = 0x08; /**< Level 1.2 */
-        public static final int H264Level13  = 0x10; /**< Level 1.3 */
-        public static final int H264Level2   = 0x20; /**< Level 2 */
-        public static final int H264Level21  = 0x40; /**< Level 2.1 */
-        public static final int H264Level22  = 0x80; /**< Level 2.2 */
-        public static final int H264Level3   = 0x100; /**< Level 3 */
-        public static final int H264Level31  = 0x200; /**< Level 3.1 */
-        public static final int H264Level32  = 0x400; /**< Level 3.2 */
-        public static final int H264Level4   = 0x800; /**< Level 4 */
-        public static final int H264Level41  = 0x1000; /**< Level 4.1 */
-        public static final int H264Level42  = 0x2000; /**< Level 4.2 */
-        public static final int H264Level5   = 0x4000; /**< Level 5 */
-        public static final int H264Level51  = 0x8000; /**< Level 5.1 */
-        public static final int H264LevelUnknown = 0x7FFFFFFF;
-    }
-    /**
-     *  The H263 profile, the values are same as the one in OMX_Video.h
-     */
-    public final class H263Profile {
-        public static final int H263ProfileBaseline            = 0x01;
-        public static final int H263ProfileH320Coding          = 0x02;
-        public static final int H263ProfileBackwardCompatible  = 0x04;
-        public static final int H263ProfileISWV2               = 0x08;
-        public static final int H263ProfileISWV3               = 0x10;
-        public static final int H263ProfileHighCompression     = 0x20;
-        public static final int H263ProfileInternet            = 0x40;
-        public static final int H263ProfileInterlace           = 0x80;
-        public static final int H263ProfileHighLatency       = 0x100;
-        public static final int H263ProfileUnknown          = 0x7FFFFFFF;
-    }
-    /**
-     *  The H263 level, the values are same as the one in OMX_Video.h
-     */
-    public final class H263Level {
-        public static final int H263Level10  = 0x01;
-        public static final int H263Level20  = 0x02;
-        public static final int H263Level30  = 0x04;
-        public static final int H263Level40  = 0x08;
-        public static final int H263Level45  = 0x10;
-        public static final int H263Level50  = 0x20;
-        public static final int H263Level60  = 0x40;
-        public static final int H263Level70  = 0x80;
-        public static final int H263LevelUnknown = 0x7FFFFFFF;
-    }
-    /**
-     *  The mpeg4 profile, the values are same as the one in OMX_Video.h
-     */
-    public final class MPEG4Profile {
-        public static final int MPEG4ProfileSimple           = 0x01;
-        public static final int MPEG4ProfileSimpleScalable   = 0x02;
-        public static final int MPEG4ProfileCore             = 0x04;
-        public static final int MPEG4ProfileMain             = 0x08;
-        public static final int MPEG4ProfileNbit             = 0x10;
-        public static final int MPEG4ProfileScalableTexture  = 0x20;
-        public static final int MPEG4ProfileSimpleFace       = 0x40;
-        public static final int MPEG4ProfileSimpleFBA        = 0x80;
-        public static final int MPEG4ProfileBasicAnimated    = 0x100;
-        public static final int MPEG4ProfileHybrid           = 0x200;
-        public static final int MPEG4ProfileAdvancedRealTime = 0x400;
-        public static final int MPEG4ProfileCoreScalable     = 0x800;
-        public static final int MPEG4ProfileAdvancedCoding   = 0x1000;
-        public static final int MPEG4ProfileAdvancedCore     = 0x2000;
-        public static final int MPEG4ProfileAdvancedScalable = 0x4000;
-        public static final int MPEG4ProfileAdvancedSimple   = 0x8000;
-        public static final int MPEG4ProfileUnknown          = 0x7FFFFFFF;
-    }
-    /**
-     *  The mpeg4 level, the values are same as the one in OMX_Video.h
-     */
-    public final class MPEG4Level {
-        public static final int MPEG4Level0  = 0x01; /**< Level 0 */
-        public static final int MPEG4Level0b = 0x02; /**< Level 0b */
-        public static final int MPEG4Level1  = 0x04; /**< Level 1 */
-        public static final int MPEG4Level2  = 0x08; /**< Level 2 */
-        public static final int MPEG4Level3  = 0x10; /**< Level 3 */
-        public static final int MPEG4Level4  = 0x20; /**< Level 4 */
-        public static final int MPEG4Level4a = 0x40; /**< Level 4a */
-        public static final int MPEG4Level5  = 0x80; /**< Level 5 */
-        public static final int MPEG4LevelUnknown = 0x7FFFFFFF;
-    }
-    /**
-     *  Audio codec types
-     */
-    public static final int ACODEC_NO_AUDIO = 0;
-    public static final int ACODEC_AMRNB = 1;
-    public static final int ACODEC_AAC_LC = 2;
-    public static final int ACODEC_AAC_PLUS = 3;
-    public static final int ACODEC_ENHANCED_AAC_PLUS = 4;
-    public static final int ACODEC_MP3 = 5;
-    public static final int ACODEC_EVRC = 6;
-    // 7 value is used for PCM
-    public static final int ACODEC_AMRWB = 8;
-    public static final int ACODEC_OGG = 9;
-
-    /**
-     *  The array of supported audio codecs
-     */
-    private static final int[] SUPPORTED_ACODECS = new int[] {
-        ACODEC_AAC_LC,
-        ACODEC_AMRNB,
-        ACODEC_AMRWB
-    };
-
-    /**
-     *  Samples per frame for each audio codec
-     */
-    public static final int SAMPLES_PER_FRAME_AAC = 1024;
-    public static final int SAMPLES_PER_FRAME_MP3 = 1152;
-    public static final int SAMPLES_PER_FRAME_AMRNB = 160;
-    public static final int SAMPLES_PER_FRAME_AMRWB = 320;
-
-    public static final int DEFAULT_SAMPLING_FREQUENCY = 32000;
-    public static final int DEFAULT_CHANNEL_COUNT = 2;
-
-    /**
-     *  File format types
-     */
-    public static final int FILE_3GP = 0;
-    public static final int FILE_MP4 = 1;
-    public static final int FILE_AMR = 2;
-    public static final int FILE_MP3 = 3;
-    // 4 is for PCM
-    public static final int FILE_JPEG = 5;
-    // 6 is for BMP
-    // 7 is for GIF
-    public static final int FILE_PNG = 8;
-    // 9 is for ARGB8888
-    public static final int FILE_M4V = 10;
-    public static final int FILE_UNSUPPORTED = 255;
-
-    /**
-     * Undefined video codec profiles
-     */
-    public static final int UNDEFINED_VIDEO_PROFILE = 255;
-
-    /**
-     * The array of the supported file formats
-     */
-    private static final int[] SUPPORTED_VIDEO_FILE_FORMATS = new int[] {
-        FILE_3GP,
-        FILE_MP4,
-        FILE_M4V
-    };
-
-    /**
-     * The maximum count of audio tracks supported
-     */
-    public static final int AUDIO_MAX_TRACK_COUNT = 1;
-
-    /** The maximum volume supported (100 means that no amplification is
-     * supported, i.e. attenuation only)
-     */
-    public static final int AUDIO_MAX_VOLUME_PERCENT = 100;
-
-    /**
-     * This class cannot be instantiated
-     */
-    private MediaProperties() {
-    }
-
-    /**
-     * @return The array of supported aspect ratios
-     */
-    public static int[] getAllSupportedAspectRatios() {
-        return ASPECT_RATIOS;
-    }
-
-    /**
-     * Get the supported resolutions for the specified aspect ratio.
-     *
-     * @param aspectRatio The aspect ratio for which the resolutions are
-     *        requested
-     * @return The array of width and height pairs
-     */
-    public static Pair<Integer, Integer>[] getSupportedResolutions(int aspectRatio) {
-        final Pair<Integer, Integer>[] resolutions;
-        switch (aspectRatio) {
-            case ASPECT_RATIO_3_2: {
-                resolutions = ASPECT_RATIO_3_2_RESOLUTIONS;
-                break;
-            }
-
-            case ASPECT_RATIO_4_3: {
-                resolutions = ASPECT_RATIO_4_3_RESOLUTIONS;
-                break;
-            }
-
-            case ASPECT_RATIO_5_3: {
-                resolutions = ASPECT_RATIO_5_3_RESOLUTIONS;
-                break;
-            }
-
-            case ASPECT_RATIO_11_9: {
-                resolutions = ASPECT_RATIO_11_9_RESOLUTIONS;
-                break;
-            }
-
-            case ASPECT_RATIO_16_9: {
-                resolutions = ASPECT_RATIO_16_9_RESOLUTIONS;
-                break;
-            }
-
-            default: {
-                throw new IllegalArgumentException("Unknown aspect ratio: " + aspectRatio);
-            }
-        }
-
-        /** Check the platform specific maximum export resolution */
-        VideoEditorProfile veProfile = VideoEditorProfile.get();
-        if (veProfile == null) {
-            throw new RuntimeException("Can't get the video editor profile");
-        }
-        final int maxWidth = veProfile.maxOutputVideoFrameWidth;
-        final int maxHeight = veProfile.maxOutputVideoFrameHeight;
-        Pair<Integer, Integer>[] tmpResolutions = new Pair[resolutions.length];
-        int numSupportedResolution = 0;
-        int i = 0;
-
-        /** Get supported resolution list */
-        for (i = 0; i < resolutions.length; i++) {
-            if ((resolutions[i].first <= maxWidth) &&
-                (resolutions[i].second <= maxHeight)) {
-                tmpResolutions[numSupportedResolution] = resolutions[i];
-                numSupportedResolution++;
-            }
-        }
-        final Pair<Integer, Integer>[] supportedResolutions =
-            new Pair[numSupportedResolution];
-        System.arraycopy(tmpResolutions, 0,
-            supportedResolutions, 0, numSupportedResolution);
-
-        return supportedResolutions;
-    }
-
-    /**
-     * @return The array of supported video codecs
-     */
-    public static int[] getSupportedVideoCodecs() {
-        return SUPPORTED_VCODECS;
-    }
-
-    /**
-     * @return The array of supported audio codecs
-     */
-    public static int[] getSupportedAudioCodecs() {
-        return SUPPORTED_ACODECS;
-    }
-
-    /**
-     * @return The array of supported file formats
-     */
-    public static int[] getSupportedVideoFileFormat() {
-        return SUPPORTED_VIDEO_FILE_FORMATS;
-    }
-
-    /**
-     * @return The array of supported video bitrates
-     */
-    public static int[] getSupportedVideoBitrates() {
-        return SUPPORTED_BITRATES;
-    }
-
-    /**
-     * @return The maximum value for the audio volume
-     */
-    public static int getSupportedMaxVolume() {
-        return MediaProperties.AUDIO_MAX_VOLUME_PERCENT;
-    }
-
-    /**
-     * @return The maximum number of audio tracks supported
-     */
-    public static int getSupportedAudioTrackCount() {
-        return MediaProperties.AUDIO_MAX_TRACK_COUNT;
-    }
-}
diff --git a/media/java/android/media/videoeditor/MediaVideoItem.java b/media/java/android/media/videoeditor/MediaVideoItem.java
deleted file mode 100644
index bbcdf57..0000000
--- a/media/java/android/media/videoeditor/MediaVideoItem.java
+++ /dev/null
@@ -1,758 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.lang.ref.SoftReference;
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.Properties;
-import android.media.videoeditor.VideoEditorProfile;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-
-/**
- * This class represents a video clip item on the storyboard
- * {@hide}
- */
-public class MediaVideoItem extends MediaItem {
-
-    /**
-     *  Instance variables
-     */
-    private final int mWidth;
-    private final int mHeight;
-    private final int mAspectRatio;
-    private final int mFileType;
-    private final int mVideoType;
-    private final int mVideoProfile;
-    private final int mVideoLevel;
-    private final int mVideoBitrate;
-    private final long mDurationMs;
-    private final int mAudioBitrate;
-    private final int mFps;
-    private final int mAudioType;
-    private final int mAudioChannels;
-    private final int mAudioSamplingFrequency;
-    private long mBeginBoundaryTimeMs;
-    private long mEndBoundaryTimeMs;
-    private int mVolumePercentage;
-    private boolean mMuted;
-    private String mAudioWaveformFilename;
-    private MediaArtistNativeHelper mMANativeHelper;
-    private VideoEditorImpl mVideoEditor;
-    private final int mVideoRotationDegree;
-    /**
-     *  The audio waveform data
-     */
-    private SoftReference<WaveformData> mWaveformData;
-
-    /**
-     * An object of this type cannot be instantiated with a default constructor
-     */
-    @SuppressWarnings("unused")
-    private MediaVideoItem() throws IOException {
-        this(null, null, null, RENDERING_MODE_BLACK_BORDER);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param mediaItemId The MediaItem id
-     * @param filename The image file name
-     * @param renderingMode The rendering mode
-     *
-     * @throws IOException if the file cannot be opened for reading
-     */
-    public MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
-            int renderingMode) throws IOException {
-        this(editor, mediaItemId, filename, renderingMode, 0, END_OF_FILE, 100, false, null);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param editor The video editor reference
-     * @param mediaItemId The MediaItem id
-     * @param filename The image file name
-     * @param renderingMode The rendering mode
-     * @param beginMs Start time in milliseconds. Set to 0 to extract from the
-     *           beginning
-     * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
-     *           extract until the end
-     * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
-     *            means double, 0% means silent.
-     * @param muted true if the audio is muted
-     * @param audioWaveformFilename The name of the audio waveform file
-     *
-     * @throws IOException if the file cannot be opened for reading
-     */
-    MediaVideoItem(VideoEditor editor, String mediaItemId, String filename,
-            int renderingMode, long beginMs, long endMs, int volumePercent, boolean muted,
-            String audioWaveformFilename)  throws IOException {
-        super(editor, mediaItemId, filename, renderingMode);
-
-        if (editor instanceof VideoEditorImpl) {
-            mMANativeHelper = ((VideoEditorImpl)editor).getNativeContext();
-            mVideoEditor = ((VideoEditorImpl)editor);
-        }
-
-        final Properties properties;
-        try {
-             properties = mMANativeHelper.getMediaProperties(filename);
-        } catch ( Exception e) {
-            throw new IllegalArgumentException(e.getMessage() + " : " + filename);
-        }
-
-        /** Check the platform specific maximum import resolution */
-        VideoEditorProfile veProfile = VideoEditorProfile.get();
-        if (veProfile == null) {
-            throw new RuntimeException("Can't get the video editor profile");
-        }
-        final int maxInputWidth = veProfile.maxInputVideoFrameWidth;
-        final int maxInputHeight = veProfile.maxInputVideoFrameHeight;
-        if ((properties.width > maxInputWidth) ||
-            (properties.height > maxInputHeight)) {
-            throw new IllegalArgumentException(
-                "Unsupported import resolution. Supported maximum width:" +
-                maxInputWidth + " height:" + maxInputHeight +
-                ", current width:" + properties.width +
-                " height:" + properties.height);
-        }
-        /** Check the platform specific maximum video profile and level */
-        if (!properties.profileSupported) {
-            throw new IllegalArgumentException(
-                "Unsupported video profile " + properties.profile);
-        }
-        if (!properties.levelSupported) {
-            throw new IllegalArgumentException(
-                "Unsupported video level " + properties.level);
-        }
-        switch (mMANativeHelper.getFileType(properties.fileType)) {
-            case MediaProperties.FILE_3GP:
-            case MediaProperties.FILE_MP4:
-            case MediaProperties.FILE_M4V:
-                break;
-
-            default:
-                throw new IllegalArgumentException("Unsupported Input File Type");
-        }
-
-        switch (mMANativeHelper.getVideoCodecType(properties.videoFormat)) {
-            case MediaProperties.VCODEC_H263:
-            case MediaProperties.VCODEC_H264:
-            case MediaProperties.VCODEC_MPEG4:
-                break;
-
-            default:
-                throw new IllegalArgumentException("Unsupported Video Codec Format in Input File");
-        }
-
-        mWidth = properties.width;
-        mHeight = properties.height;
-        mAspectRatio = mMANativeHelper.getAspectRatio(properties.width,
-                properties.height);
-        mFileType = mMANativeHelper.getFileType(properties.fileType);
-        mVideoType = mMANativeHelper.getVideoCodecType(properties.videoFormat);
-        mVideoProfile = properties.profile;
-        mVideoLevel = properties.level;
-        mDurationMs = properties.videoDuration;
-        mVideoBitrate = properties.videoBitrate;
-        mAudioBitrate = properties.audioBitrate;
-        mFps = (int)properties.averageFrameRate;
-        mAudioType = mMANativeHelper.getAudioCodecType(properties.audioFormat);
-        mAudioChannels = properties.audioChannels;
-        mAudioSamplingFrequency =  properties.audioSamplingFrequency;
-        mBeginBoundaryTimeMs = beginMs;
-        mEndBoundaryTimeMs = endMs == END_OF_FILE ? mDurationMs : endMs;
-        mVolumePercentage = volumePercent;
-        mMuted = muted;
-        mAudioWaveformFilename = audioWaveformFilename;
-        if (audioWaveformFilename != null) {
-            mWaveformData = new SoftReference<WaveformData>(
-                        new WaveformData(audioWaveformFilename));
-        } else {
-            mWaveformData = null;
-        }
-        mVideoRotationDegree = properties.videoRotation;
-    }
-
-    /**
-     * Sets the start and end marks for trimming a video media item.
-     * This method will adjust the duration of bounding transitions, effects
-     * and overlays if the current duration of the transactions become greater
-     * than the maximum allowable duration.
-     *
-     * @param beginMs Start time in milliseconds. Set to 0 to extract from the
-     *           beginning
-     * @param endMs End time in milliseconds. Set to {@link #END_OF_FILE} to
-     *           extract until the end
-     *
-     * @throws IllegalArgumentException if the start time is greater or equal than
-     *           end time, the end time is beyond the file duration, the start time
-     *           is negative
-     */
-    public void setExtractBoundaries(long beginMs, long endMs) {
-        if (beginMs > mDurationMs) {
-            throw new IllegalArgumentException("setExtractBoundaries: Invalid start time");
-        }
-
-        if (endMs > mDurationMs) {
-            throw new IllegalArgumentException("setExtractBoundaries: Invalid end time");
-        }
-
-        if ((endMs != -1) && (beginMs >= endMs) ) {
-            throw new IllegalArgumentException("setExtractBoundaries: Start time is greater than end time");
-        }
-
-        if ((beginMs < 0) || ((endMs != -1) && (endMs < 0))) {
-            throw new IllegalArgumentException("setExtractBoundaries: Start time or end time is negative");
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        if (beginMs != mBeginBoundaryTimeMs) {
-            if (mBeginTransition != null) {
-                mBeginTransition.invalidate();
-            }
-        }
-
-        if (endMs != mEndBoundaryTimeMs) {
-            if (mEndTransition != null) {
-                mEndTransition.invalidate();
-            }
-        }
-
-        mBeginBoundaryTimeMs = beginMs;
-        mEndBoundaryTimeMs = endMs;
-        adjustTransitions();
-        mVideoEditor.updateTimelineDuration();
-        /**
-         *  Note that the start and duration of any effects and overlays are
-         *  not adjusted nor are they automatically removed if they fall
-         *  outside the new boundaries.
-         */
-    }
-
-    /**
-     * @return The boundary begin time
-     */
-    public long getBoundaryBeginTime() {
-        return mBeginBoundaryTimeMs;
-    }
-
-    /**
-     * @return The boundary end time
-     */
-    public long getBoundaryEndTime() {
-        return mEndBoundaryTimeMs;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public void addEffect(Effect effect) {
-        if (effect instanceof EffectKenBurns) {
-            throw new IllegalArgumentException("Ken Burns effects cannot be applied to MediaVideoItem");
-        }
-        super.addEffect(effect);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public Bitmap getThumbnail(int width, int height, long timeMs) {
-        if (timeMs > mDurationMs) {
-            throw new IllegalArgumentException("Time Exceeds duration");
-        }
-
-        if (timeMs < 0) {
-            throw new IllegalArgumentException("Invalid Time duration");
-        }
-
-        if ((width <= 0) || (height <= 0)) {
-            throw new IllegalArgumentException("Invalid Dimensions");
-        }
-
-        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
-            int temp = width;
-            width = height;
-            height = temp;
-        }
-
-        return mMANativeHelper.getPixels(
-                getFilename(), width, height, timeMs, mVideoRotationDegree);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public void getThumbnailList(int width, int height,
-                                 long startMs, long endMs,
-                                 int thumbnailCount,
-                                 int[] indices,
-                                 GetThumbnailListCallback callback)
-                                 throws IOException {
-        if (startMs > endMs) {
-            throw new IllegalArgumentException("Start time is greater than end time");
-        }
-
-        if (endMs > mDurationMs) {
-            throw new IllegalArgumentException("End time is greater than file duration");
-        }
-
-        if ((height <= 0) || (width <= 0)) {
-            throw new IllegalArgumentException("Invalid dimension");
-        }
-
-        if (mVideoRotationDegree == 90 || mVideoRotationDegree == 270) {
-            int temp = width;
-            width = height;
-            height = temp;
-        }
-
-        mMANativeHelper.getPixelsList(getFilename(), width, height,
-                startMs, endMs, thumbnailCount, indices, callback,
-                mVideoRotationDegree);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void invalidateTransitions(long startTimeMs, long durationMs) {
-        /**
-         *  Check if the item overlaps with the beginning and end transitions
-         */
-        if (mBeginTransition != null) {
-            if (isOverlapping(startTimeMs, durationMs,
-                    mBeginBoundaryTimeMs, mBeginTransition.getDuration())) {
-                mBeginTransition.invalidate();
-            }
-        }
-
-        if (mEndTransition != null) {
-            final long transitionDurationMs = mEndTransition.getDuration();
-            if (isOverlapping(startTimeMs, durationMs,
-                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs)) {
-                mEndTransition.invalidate();
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void invalidateTransitions(long oldStartTimeMs, long oldDurationMs, long newStartTimeMs,
-            long newDurationMs) {
-        /**
-         *  Check if the item overlaps with the beginning and end transitions
-         */
-        if (mBeginTransition != null) {
-            final long transitionDurationMs = mBeginTransition.getDuration();
-            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
-                    mBeginBoundaryTimeMs, transitionDurationMs);
-            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
-                    mBeginBoundaryTimeMs, transitionDurationMs);
-            /**
-             * Invalidate transition if:
-             *
-             * 1. New item overlaps the transition, the old one did not
-             * 2. New item does not overlap the transition, the old one did
-             * 3. New and old item overlap the transition if begin or end
-             * time changed
-             */
-            if (newOverlap != oldOverlap) { // Overlap has changed
-                mBeginTransition.invalidate();
-            } else if (newOverlap) { // Both old and new overlap
-                if ((oldStartTimeMs != newStartTimeMs) ||
-                        !(oldStartTimeMs + oldDurationMs > transitionDurationMs &&
-                        newStartTimeMs + newDurationMs > transitionDurationMs)) {
-                    mBeginTransition.invalidate();
-                }
-            }
-        }
-
-        if (mEndTransition != null) {
-            final long transitionDurationMs = mEndTransition.getDuration();
-            final boolean oldOverlap = isOverlapping(oldStartTimeMs, oldDurationMs,
-                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
-            final boolean newOverlap = isOverlapping(newStartTimeMs, newDurationMs,
-                    mEndBoundaryTimeMs - transitionDurationMs, transitionDurationMs);
-            /**
-             * Invalidate transition if:
-             *
-             * 1. New item overlaps the transition, the old one did not
-             * 2. New item does not overlap the transition, the old one did
-             * 3. New and old item overlap the transition if begin or end
-             * time changed
-             */
-            if (newOverlap != oldOverlap) { // Overlap has changed
-                mEndTransition.invalidate();
-            } else if (newOverlap) { // Both old and new overlap
-                if ((oldStartTimeMs + oldDurationMs != newStartTimeMs + newDurationMs) ||
-                        ((oldStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs) ||
-                        newStartTimeMs > mEndBoundaryTimeMs - transitionDurationMs)) {
-                    mEndTransition.invalidate();
-                }
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getAspectRatio() {
-        return mAspectRatio;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getFileType() {
-        return mFileType;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getWidth() {
-        if (mVideoRotationDegree == 90 ||
-             mVideoRotationDegree == 270) {
-            return mHeight;
-        } else {
-            return mWidth;
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int getHeight() {
-        if (mVideoRotationDegree == 90 ||
-             mVideoRotationDegree == 270) {
-            return mWidth;
-        } else {
-            return mHeight;
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public long getTimelineDuration() {
-        return mEndBoundaryTimeMs - mBeginBoundaryTimeMs;
-    }
-
-    /**
-     * Render a frame according to the playback (in the native aspect ratio) for
-     * the specified media item. All effects and overlays applied to the media
-     * item are ignored. The extract boundaries are also ignored. This method
-     * can be used to playback frames when implementing trimming functionality.
-     *
-     * @param surfaceHolder SurfaceHolder used by the application
-     * @param timeMs time corresponding to the frame to display (relative to the
-     *            the beginning of the media item).
-     * @return The accurate time stamp of the frame that is rendered .
-     * @throws IllegalStateException if a playback, preview or an export is
-     *             already in progress
-     * @throws IllegalArgumentException if time is negative or greater than the
-     *             media item duration
-     */
-    public long renderFrame(SurfaceHolder surfaceHolder, long timeMs) {
-        if (surfaceHolder == null) {
-            throw new IllegalArgumentException("Surface Holder is null");
-        }
-
-        if (timeMs > mDurationMs || timeMs < 0) {
-            throw new IllegalArgumentException("requested time not correct");
-        }
-
-        final Surface surface = surfaceHolder.getSurface();
-        if (surface == null) {
-            throw new RuntimeException("Surface could not be retrieved from Surface holder");
-        }
-
-        if (mFilename != null) {
-            return mMANativeHelper.renderMediaItemPreviewFrame(surface,
-                    mFilename,timeMs,mWidth,mHeight);
-        } else {
-            return 0;
-        }
-    }
-
-
-    /**
-     * This API allows to generate a file containing the sample volume levels of
-     * the Audio track of this media item. This function may take significant
-     * time and is blocking. The file can be retrieved using
-     * getAudioWaveformFilename().
-     *
-     * @param listener The progress listener
-     *
-     * @throws IOException if the output file cannot be created
-     * @throws IllegalArgumentException if the mediaItem does not have a valid
-     *             Audio track
-     */
-    public void extractAudioWaveform(ExtractAudioWaveformProgressListener listener)
-        throws IOException {
-        int frameDuration = 0;
-        int sampleCount = 0;
-        final String projectPath = mMANativeHelper.getProjectPath();
-        /**
-         *  Waveform file does not exist
-         */
-        if (mAudioWaveformFilename == null ) {
-            /**
-             * Since audioWaveformFilename will not be supplied,it is  generated
-             */
-            String mAudioWaveFileName = null;
-
-            mAudioWaveFileName =
-                String.format(projectPath + "/" + "audioWaveformFile-"+ getId() + ".dat");
-            /**
-             * Logic to get frame duration = (no. of frames per sample * 1000)/
-             * sampling frequency
-             */
-            if (mMANativeHelper.getAudioCodecType(mAudioType) ==
-                MediaProperties.ACODEC_AMRNB ) {
-                frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRNB*1000)/
-                MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRNB;
-            } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
-                MediaProperties.ACODEC_AMRWB ) {
-                frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AMRWB * 1000)/
-                MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                sampleCount = MediaProperties.SAMPLES_PER_FRAME_AMRWB;
-            } else if (mMANativeHelper.getAudioCodecType(mAudioType) ==
-                MediaProperties.ACODEC_AAC_LC ) {
-                frameDuration = (MediaProperties.SAMPLES_PER_FRAME_AAC * 1000)/
-                MediaProperties.DEFAULT_SAMPLING_FREQUENCY;
-                sampleCount = MediaProperties.SAMPLES_PER_FRAME_AAC;
-            }
-
-            mMANativeHelper.generateAudioGraph( getId(),
-                    mFilename,
-                    mAudioWaveFileName,
-                    frameDuration,
-                    MediaProperties.DEFAULT_CHANNEL_COUNT,
-                    sampleCount,
-                    listener,
-                    true);
-            /**
-             * Record the generated file name
-             */
-            mAudioWaveformFilename = mAudioWaveFileName;
-        }
-        mWaveformData =
-            new SoftReference<WaveformData>(new WaveformData(mAudioWaveformFilename));
-    }
-
-    /**
-     * Get the audio waveform file name if {@link #extractAudioWaveform()} was
-     * successful. The file format is as following:
-     * <ul>
-     *  <li>first 4 bytes provide the number of samples for each value, as big-endian signed</li>
-     *  <li>4 following bytes is the total number of values in the file, as big-endian signed</li>
-     *  <li>all values follow as bytes Name is unique.</li>
-     *</ul>
-     * @return the name of the file, null if the file has not been computed or
-     *         if there is no Audio track in the mediaItem
-     */
-    String getAudioWaveformFilename() {
-        return mAudioWaveformFilename;
-    }
-
-    /**
-     * Invalidate the AudioWaveform File
-     */
-    void invalidate() {
-        if (mAudioWaveformFilename != null) {
-            new File(mAudioWaveformFilename).delete();
-            mAudioWaveformFilename = null;
-        }
-    }
-
-    /**
-     * @return The waveform data
-     */
-    public WaveformData getWaveformData() throws IOException {
-        if (mWaveformData == null) {
-            return null;
-        }
-
-        WaveformData waveformData = mWaveformData.get();
-        if (waveformData != null) {
-            return waveformData;
-        } else if (mAudioWaveformFilename != null) {
-            try {
-                waveformData = new WaveformData(mAudioWaveformFilename);
-            } catch(IOException e) {
-                throw e;
-            }
-            mWaveformData = new SoftReference<WaveformData>(waveformData);
-            return waveformData;
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Set volume of the Audio track of this mediaItem
-     *
-     * @param volumePercent in %/. 100% means no change; 50% means half value, 200%
-     *            means double, 0% means silent.
-     * @throws UsupportedOperationException if volume value is not supported
-     */
-    public void setVolume(int volumePercent) {
-        if ((volumePercent <0) || (volumePercent >100)) {
-            throw new IllegalArgumentException("Invalid volume");
-        }
-
-        mVolumePercentage = volumePercent;
-    }
-
-    /**
-     * Get the volume value of the audio track as percentage. Call of this
-     * method before calling setVolume will always return 100%
-     *
-     * @return the volume in percentage
-     */
-    public int getVolume() {
-        return mVolumePercentage;
-    }
-
-    /**
-     * @param muted true to mute the media item
-     */
-    public void setMute(boolean muted) {
-        mMANativeHelper.setGeneratePreview(true);
-        mMuted = muted;
-        if (mBeginTransition != null) {
-            mBeginTransition.invalidate();
-        }
-        if (mEndTransition != null) {
-            mEndTransition.invalidate();
-        }
-    }
-
-    /**
-     * @return true if the media item is muted
-     */
-    public boolean isMuted() {
-        return mMuted;
-    }
-
-    /**
-     * @return The video type
-     */
-    public int getVideoType() {
-        return mVideoType;
-    }
-
-    /**
-     * @return The video profile
-     */
-    public int getVideoProfile() {
-        return mVideoProfile;
-    }
-
-    /**
-     * @return The video profile
-     */
-    public int getVideoLevel() {
-        return mVideoLevel;
-    }
-
-    /**
-     * @return The video bitrate
-     */
-    public int getVideoBitrate() {
-        return mVideoBitrate;
-    }
-
-    /**
-     * @return The audio bitrate
-     */
-    public int getAudioBitrate() {
-        return mAudioBitrate;
-    }
-
-    /**
-     * @return The number of frames per second
-     */
-    public int getFps() {
-        return mFps;
-    }
-
-    /**
-     * @return The audio codec
-     */
-    public int getAudioType() {
-        return mAudioType;
-    }
-
-    /**
-     * @return The number of audio channels
-     */
-    public int getAudioChannels() {
-        return mAudioChannels;
-    }
-
-    /**
-     * @return The audio sample frequency
-     */
-    public int getAudioSamplingFrequency() {
-        return mAudioSamplingFrequency;
-    }
-
-    /**
-     * @return The Video media item properties in ClipSettings class object
-     * {@link android.media.videoeditor.MediaArtistNativeHelper.ClipSettings}
-     */
-    ClipSettings getVideoClipProperties() {
-        ClipSettings clipSettings = new ClipSettings();
-        clipSettings.clipPath = getFilename();
-        clipSettings.fileType = mMANativeHelper.getMediaItemFileType(getFileType());
-        clipSettings.beginCutTime = (int)getBoundaryBeginTime();
-        clipSettings.endCutTime = (int)getBoundaryEndTime();
-        clipSettings.mediaRendering = mMANativeHelper.getMediaItemRenderingMode(getRenderingMode());
-        clipSettings.rotationDegree = mVideoRotationDegree;
-
-        return clipSettings;
-    }
-}
diff --git a/media/java/android/media/videoeditor/Overlay.java b/media/java/android/media/videoeditor/Overlay.java
deleted file mode 100644
index a070eb4..0000000
--- a/media/java/android/media/videoeditor/Overlay.java
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * This is the super class for all Overlay classes.
- * {@hide}
- */
-public abstract class Overlay {
-    /**
-     *  Instance variables
-     */
-    private final String mUniqueId;
-    /**
-     *  The overlay owner
-     */
-    private final MediaItem mMediaItem;
-    /**
-     *  user attributes
-     */
-    private final Map<String, String> mUserAttributes;
-
-    protected long mStartTimeMs;
-    protected long mDurationMs;
-
-    /**
-     * Default constructor
-     */
-    @SuppressWarnings("unused")
-    private Overlay() {
-        this(null, null, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param mediaItem The media item owner
-     * @param overlayId The overlay id
-     * @param startTimeMs The start time relative to the media item start time
-     * @param durationMs The duration
-     *
-     * @throws IllegalArgumentException if the file type is not PNG or the
-     *      startTimeMs and durationMs are incorrect.
-     */
-    public Overlay(MediaItem mediaItem, String overlayId, long startTimeMs,
-           long durationMs) {
-        if (mediaItem == null) {
-            throw new IllegalArgumentException("Media item cannot be null");
-        }
-
-        if ((startTimeMs<0) || (durationMs<0) ) {
-            throw new IllegalArgumentException("Invalid start time and/OR duration");
-        }
-
-        if (startTimeMs + durationMs > mediaItem.getDuration()) {
-            throw new IllegalArgumentException("Invalid start time and duration");
-        }
-
-        mMediaItem = mediaItem;
-        mUniqueId = overlayId;
-        mStartTimeMs = startTimeMs;
-        mDurationMs = durationMs;
-        mUserAttributes = new HashMap<String, String>();
-    }
-
-    /**
-     * Get the overlay ID.
-     *
-     * @return The of the overlay
-     */
-    public String getId() {
-        return mUniqueId;
-    }
-
-    /**
-     * Get the duration of overlay.
-     *
-     * @return The duration of the overlay effect
-     */
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /**
-     * If a preview or export is in progress, then this change is effective for
-     * next preview or export session.
-     *
-     * @param durationMs The duration in milliseconds
-     */
-    public void setDuration(long durationMs) {
-        if (durationMs < 0) {
-            throw new IllegalArgumentException("Invalid duration");
-        }
-
-        if (mStartTimeMs + durationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Duration is too large");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-
-        final long oldDurationMs = mDurationMs;
-        mDurationMs = durationMs;
-
-        mMediaItem.invalidateTransitions(mStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the start time of overlay.
-     *
-     * @return the start time of the overlay
-     */
-    public long getStartTime() {
-        return mStartTimeMs;
-    }
-
-    /**
-     * Set the start time for the overlay. If a preview or export is in
-     * progress, then this change is effective for next preview or export
-     * session.
-     *
-     * @param startTimeMs start time in milliseconds
-     */
-    public void setStartTime(long startTimeMs) {
-        if (startTimeMs + mDurationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Start time is too large");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-
-        final long oldStartTimeMs = mStartTimeMs;
-        mStartTimeMs = startTimeMs;
-
-        mMediaItem.invalidateTransitions(oldStartTimeMs, mDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Set the start time and duration
-     *
-     * @param startTimeMs start time in milliseconds
-     * @param durationMs The duration in milliseconds
-     */
-    public void setStartTimeAndDuration(long startTimeMs, long durationMs) {
-        if (startTimeMs + durationMs > mMediaItem.getDuration()) {
-            throw new IllegalArgumentException("Invalid start time or duration");
-        }
-
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-
-        final long oldStartTimeMs = mStartTimeMs;
-        final long oldDurationMs = mDurationMs;
-
-        mStartTimeMs = startTimeMs;
-        mDurationMs = durationMs;
-
-        mMediaItem.invalidateTransitions(oldStartTimeMs, oldDurationMs, mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the media item owner.
-     *
-     * @return The media item owner.
-     */
-    public MediaItem getMediaItem() {
-        return mMediaItem;
-    }
-
-    /**
-     * Set a user attribute
-     *
-     * @param name The attribute name
-     * @param value The attribute value
-     */
-    public void setUserAttribute(String name, String value) {
-        mUserAttributes.put(name, value);
-    }
-
-    /**
-     * Get the current user attributes set.
-     *
-     * @return The user attributes
-     */
-    public Map<String, String> getUserAttributes() {
-        return mUserAttributes;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (!(object instanceof Overlay)) {
-            return false;
-        }
-        return mUniqueId.equals(((Overlay)object).mUniqueId);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return mUniqueId.hashCode();
-    }
-}
diff --git a/media/java/android/media/videoeditor/OverlayFrame.java b/media/java/android/media/videoeditor/OverlayFrame.java
deleted file mode 100644
index d159df2..0000000
--- a/media/java/android/media/videoeditor/OverlayFrame.java
+++ /dev/null
@@ -1,465 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.DataOutputStream;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap.CompressFormat;
-import android.util.Pair;
-
-
-/**
- * This class is used to overlay an image on top of a media item.
- * {@hide}
- */
-public class OverlayFrame extends Overlay {
-    /**
-     *  Instance variables
-     */
-    private Bitmap mBitmap;
-    private String mFilename;
-    private String mBitmapFileName;
-
-    private int mOFWidth;
-    private int mOFHeight;
-
-    /**
-     * resized RGB Image dimensions
-     */
-    private int mResizedRGBWidth;
-    private int mResizedRGBHeight;
-
-    /**
-     *  The resize paint
-     */
-    private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private OverlayFrame() {
-        this(null, null, (String)null, 0, 0);
-    }
-
-    /**
-     * Constructor for an OverlayFrame
-     *
-     * @param mediaItem The media item owner
-     * @param overlayId The overlay id
-     * @param bitmap The bitmap to be used as an overlay. The size of the
-     *      bitmap must equal to the size of the media item to which it is
-     *      added. The bitmap is typically a decoded PNG file.
-     * @param startTimeMs The overlay start time in milliseconds
-     * @param durationMs The overlay duration in milliseconds
-     *
-     * @throws IllegalArgumentException if the file type is not PNG or the
-     *      startTimeMs and durationMs are incorrect.
-     */
-    public OverlayFrame(MediaItem mediaItem, String overlayId, Bitmap bitmap,
-                        long startTimeMs,long durationMs) {
-        super(mediaItem, overlayId, startTimeMs, durationMs);
-        mBitmap = bitmap;
-        mFilename = null;
-        mBitmapFileName = null;
-        mResizedRGBWidth = 0;
-        mResizedRGBHeight = 0;
-    }
-
-    /**
-     * Constructor for an OverlayFrame. This constructor can be used to
-     * restore the overlay after it was saved internally by the video editor.
-     *
-     * @param mediaItem The media item owner
-     * @param overlayId The overlay id
-     * @param filename The file name that contains the overlay.
-     * @param startTimeMs The overlay start time in milliseconds
-     * @param durationMs The overlay duration in milliseconds
-     *
-     * @throws IllegalArgumentException if the file type is not PNG or the
-     *      startTimeMs and durationMs are incorrect.
-     */
-    OverlayFrame(MediaItem mediaItem, String overlayId, String filename,
-                 long startTimeMs,long durationMs) {
-        super(mediaItem, overlayId, startTimeMs, durationMs);
-        mBitmapFileName = filename;
-        mBitmap = BitmapFactory.decodeFile(mBitmapFileName);
-        mFilename = null;
-        mResizedRGBWidth = 0;
-        mResizedRGBHeight = 0;
-    }
-
-    /**
-     * Get the overlay bitmap.
-     *
-     * @return Get the overlay bitmap
-     */
-    public Bitmap getBitmap() {
-        return mBitmap;
-    }
-
-    /**
-     * Get the overlay bitmap.
-     *
-     * @return Get the overlay bitmap as png file.
-     */
-    String getBitmapImageFileName() {
-        return mBitmapFileName;
-    }
-    /**
-     * Set the overlay bitmap.
-     *
-     * @param bitmap The overlay bitmap.
-     */
-    public void setBitmap(Bitmap bitmap) {
-        getMediaItem().getNativeContext().setGeneratePreview(true);
-
-        invalidate();
-
-        mBitmap = bitmap;
-        if (mFilename != null) {
-            /**
-             *  Delete the file
-             */
-            new File(mFilename).delete();
-            /**
-             *  Invalidate the filename
-             */
-            mFilename = null;
-        }
-
-        /**
-         *  Invalidate the transitions if necessary
-         */
-        getMediaItem().invalidateTransitions(mStartTimeMs, mDurationMs);
-    }
-
-    /**
-     * Get the file name of this overlay
-     */
-    String getFilename() {
-        return mFilename;
-    }
-
-    /*
-     * Set the file name of this overlay
-     */
-    void setFilename(String filename) {
-        mFilename = filename;
-    }
-    /**
-     * Save the overlay to the project folder
-     *
-     * @param path The path where the overlay will be saved
-     *
-     * @return The filename
-     * @throws FileNotFoundException if the bitmap cannot be saved
-     * @throws IOException if the bitmap file cannot be saved
-     */
-    String save(String path) throws FileNotFoundException, IOException {
-        if (mFilename != null) {
-            return mFilename;
-        }
-
-        // Create the compressed PNG file
-        mBitmapFileName = path + "/" + "Overlay" + getId() + ".png";
-        if (!(new File(mBitmapFileName).exists())) {
-            final FileOutputStream out = new FileOutputStream (mBitmapFileName);
-            mBitmap.compress(CompressFormat.PNG, 100, out);
-            out.flush();
-            out.close();
-        }
-
-        mOFWidth = mBitmap.getWidth();
-        mOFHeight = mBitmap.getHeight();
-
-        mFilename = path + "/" + "Overlay" + getId() + ".rgb";
-
-        /* resize and save rgb as per project aspect ratio */
-        MediaArtistNativeHelper nativeHelper = (super.getMediaItem()).getNativeContext();
-
-        /* get height and width for story board aspect ratio */
-        final Pair<Integer, Integer> maxResolution;
-        final Pair<Integer, Integer>[] resolutions;
-        resolutions = MediaProperties.getSupportedResolutions(nativeHelper.nativeHelperGetAspectRatio());
-
-        // Get the highest resolution
-        maxResolution = resolutions[resolutions.length - 1];
-
-        /* Generate the rgb file with rendering mode */
-        generateOverlayWithRenderingMode (super.getMediaItem(), this,
-                maxResolution.second /* max Height */ ,
-                maxResolution.first /* max Width */);
-
-        return mFilename;
-    }
-
-    /**
-     * Get the OverlayFrame Height
-     */
-     int getOverlayFrameHeight() {
-         return mOFHeight;
-     }
-
-     /**
-     * Get the OverlayFrame Width
-     */
-     int getOverlayFrameWidth() {
-         return mOFWidth;
-     }
-
-    /*
-     * Set the OverlayFrame Height
-     */
-     void setOverlayFrameHeight(int height) {
-         mOFHeight = height;
-     }
-
-    /*
-     * Set the OverlayFrame Width
-     */
-     void setOverlayFrameWidth(int width) {
-         mOFWidth = width;
-     }
-
-    /*
-     * Set the resized RGB widht and height
-     */
-     void setResizedRGBSize(int width, int height) {
-        mResizedRGBWidth = width;
-        mResizedRGBHeight = height;
-     }
-
-    /*
-     * Get the resized RGB Height
-     */
-     int getResizedRGBSizeHeight() {
-         return mResizedRGBHeight;
-     }
-
-    /*
-     * Get the resized RGB Width
-     */
-     int getResizedRGBSizeWidth() {
-         return mResizedRGBWidth;
-     }
-
-
-    /**
-     * Delete the overlay files
-     */
-    void invalidate() {
-        if (mBitmap != null) {
-            mBitmap.recycle();
-            mBitmap = null;
-        }
-
-        if (mFilename != null) {
-            new File(mFilename).delete();
-            mFilename = null;
-        }
-
-        if (mBitmapFileName != null) {
-            new File(mBitmapFileName).delete();
-            mBitmapFileName = null;
-        }
-    }
-
-     /**
-     * Delete the overlay related files
-     */
-    void invalidateGeneratedFiles() {
-        if (mFilename != null) {
-            new File(mFilename).delete();
-            mFilename = null;
-        }
-
-        if (mBitmapFileName != null) {
-            new File(mBitmapFileName).delete();
-            mBitmapFileName = null;
-        }
-    }
-
-    void generateOverlayWithRenderingMode (MediaItem mediaItemsList, OverlayFrame overlay, int height , int width)
-        throws FileNotFoundException, IOException {
-
-        final MediaItem t = mediaItemsList;
-
-        /* get the rendering mode */
-        int renderMode = t.getRenderingMode();
-
-        Bitmap overlayBitmap = ((OverlayFrame)overlay).getBitmap();
-
-        /*
-         * Check if the resize of Overlay is needed with rendering mode applied
-         * because of change in export dimensions
-         */
-        int resizedRGBFileHeight = ((OverlayFrame)overlay).getResizedRGBSizeHeight();
-        int resizedRGBFileWidth = ((OverlayFrame)overlay).getResizedRGBSizeWidth();
-
-        /* Get original bitmap width if it is not resized */
-        if(resizedRGBFileWidth == 0) {
-            resizedRGBFileWidth = overlayBitmap.getWidth();
-        }
-        /* Get original bitmap height if it is not resized */
-        if(resizedRGBFileHeight == 0) {
-            resizedRGBFileHeight = overlayBitmap.getHeight();
-        }
-
-        if (resizedRGBFileWidth != width || resizedRGBFileHeight != height
-            || (!(new File(((OverlayFrame)overlay).getFilename()).exists()))) {
-            /*
-             *  Create the canvas bitmap
-             */
-            final Bitmap destBitmap = Bitmap.createBitmap((int)width,
-                                                      (int)height,
-                                                      Bitmap.Config.ARGB_8888);
-            final Canvas overlayCanvas = new Canvas(destBitmap);
-            final Rect destRect;
-            final Rect srcRect;
-
-            switch (renderMode) {
-                case MediaItem.RENDERING_MODE_STRETCH: {
-                    destRect = new Rect(0, 0, overlayCanvas.getWidth(),
-                                             overlayCanvas.getHeight());
-                    srcRect = new Rect(0, 0, overlayBitmap.getWidth(),
-                                             overlayBitmap.getHeight());
-                    break;
-                }
-
-                case MediaItem.RENDERING_MODE_BLACK_BORDER: {
-                    int left, right, top, bottom;
-                    float aROverlayImage, aRCanvas;
-                    aROverlayImage = (float)(overlayBitmap.getWidth()) /
-                                     (float)(overlayBitmap.getHeight());
-
-                    aRCanvas = (float)(overlayCanvas.getWidth()) /
-                                     (float)(overlayCanvas.getHeight());
-
-                    if (aROverlayImage > aRCanvas) {
-                        int newHeight = ((overlayCanvas.getWidth() * overlayBitmap.getHeight())
-                                         / overlayBitmap.getWidth());
-                        left = 0;
-                        top  = (overlayCanvas.getHeight() - newHeight) / 2;
-                        right = overlayCanvas.getWidth();
-                        bottom = top + newHeight;
-                    } else {
-                        int newWidth = ((overlayCanvas.getHeight() * overlayBitmap.getWidth())
-                                            / overlayBitmap.getHeight());
-                        left = (overlayCanvas.getWidth() - newWidth) / 2;
-                        top  = 0;
-                        right = left + newWidth;
-                        bottom = overlayCanvas.getHeight();
-                    }
-
-                    destRect = new Rect(left, top, right, bottom);
-                    srcRect = new Rect(0, 0, overlayBitmap.getWidth(), overlayBitmap.getHeight());
-                    break;
-                }
-
-                case MediaItem.RENDERING_MODE_CROPPING: {
-                    // Calculate the source rect
-                    int left, right, top, bottom;
-                    float aROverlayImage, aRCanvas;
-                    aROverlayImage = (float)(overlayBitmap.getWidth()) /
-                                     (float)(overlayBitmap.getHeight());
-                    aRCanvas = (float)(overlayCanvas.getWidth()) /
-                                    (float)(overlayCanvas.getHeight());
-                    if (aROverlayImage < aRCanvas) {
-                        int newHeight = ((overlayBitmap.getWidth() * overlayCanvas.getHeight())
-                                   / overlayCanvas.getWidth());
-
-                        left = 0;
-                        top  = (overlayBitmap.getHeight() - newHeight) / 2;
-                        right = overlayBitmap.getWidth();
-                        bottom = top + newHeight;
-                    } else {
-                        int newWidth = ((overlayBitmap.getHeight() * overlayCanvas.getWidth())
-                                    / overlayCanvas.getHeight());
-                        left = (overlayBitmap.getWidth() - newWidth) / 2;
-                        top  = 0;
-                        right = left + newWidth;
-                        bottom = overlayBitmap.getHeight();
-                    }
-
-                    srcRect = new Rect(left, top, right, bottom);
-                    destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
-                    break;
-                }
-
-                default: {
-                    throw new IllegalStateException("Rendering mode: " + renderMode);
-                }
-            }
-
-            overlayCanvas.drawBitmap(overlayBitmap, srcRect, destRect, sResizePaint);
-            overlayCanvas.setBitmap(null);
-
-            /*
-             * Write to the dest file
-             */
-            String outFileName = ((OverlayFrame)overlay).getFilename();
-
-            /*
-             * Save the image to same rgb file
-             */
-            if (outFileName != null) {
-                new File(outFileName).delete();
-            }
-
-            final FileOutputStream fl = new FileOutputStream(outFileName);
-            final DataOutputStream dos = new DataOutputStream(fl);
-
-            /*
-             * Populate the rgb file with bitmap data
-             */
-            final int [] framingBuffer = new int[width];
-            ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
-            IntBuffer intBuffer;
-
-            byte[] array = byteBuffer.array();
-            int tmp = 0;
-            while(tmp < height) {
-                destBitmap.getPixels(framingBuffer,0,width,0,tmp,width,1);
-                intBuffer = byteBuffer.asIntBuffer();
-                intBuffer.put(framingBuffer,0,width);
-                dos.write(array);
-                tmp += 1;
-            }
-            fl.flush();
-            fl.close();
-
-            /*
-             * Set the resized RGB width and height
-             */
-            ((OverlayFrame)overlay).setResizedRGBSize(width, height);
-        }
-    }
-}
diff --git a/media/java/android/media/videoeditor/Transition.java b/media/java/android/media/videoeditor/Transition.java
deleted file mode 100644
index fa9d26d..0000000
--- a/media/java/android/media/videoeditor/Transition.java
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.media.videoeditor.MediaArtistNativeHelper.AlphaMagicSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.AudioTransition;
-import android.media.videoeditor.MediaArtistNativeHelper.ClipSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EditSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.EffectSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.SlideTransitionSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.TransitionSettings;
-import android.media.videoeditor.MediaArtistNativeHelper.VideoTransition;
-
-/**
- * This class is super class for all transitions. Transitions (with the
- * exception of TransitionAtStart and TransitioAtEnd) can only be inserted
- * between media items.
- *
- * Adding a transition between MediaItems makes the
- * duration of the storyboard shorter by the duration of the Transition itself.
- * As a result, if the duration of the transition is larger than the smaller
- * duration of the two MediaItems associated with the Transition, an exception
- * will be thrown.
- *
- * During a transition, the audio track are cross-fading
- * automatically. {@hide}
- */
-public abstract class Transition {
-    /**
-     *  The transition behavior
-     */
-    private static final int BEHAVIOR_MIN_VALUE = 0;
-
-    /** The transition starts slowly and speed up */
-    public static final int BEHAVIOR_SPEED_UP = 0;
-    /** The transition start fast and speed down */
-    public static final int BEHAVIOR_SPEED_DOWN = 1;
-    /** The transition speed is constant */
-    public static final int BEHAVIOR_LINEAR = 2;
-    /** The transition starts fast and ends fast with a slow middle */
-    public static final int BEHAVIOR_MIDDLE_SLOW = 3;
-    /** The transition starts slowly and ends slowly with a fast middle */
-    public static final int BEHAVIOR_MIDDLE_FAST = 4;
-
-    private static final int BEHAVIOR_MAX_VALUE = 4;
-
-    /**
-     *  The unique id of the transition
-     */
-    private final String mUniqueId;
-
-    /**
-     *  The transition is applied at the end of this media item
-     */
-    private final MediaItem mAfterMediaItem;
-    /**
-     *  The transition is applied at the beginning of this media item
-     */
-    private final MediaItem mBeforeMediaItem;
-
-    /**
-     *  The transition behavior
-     */
-    protected final int mBehavior;
-
-    /**
-     *  The transition duration
-     */
-    protected long mDurationMs;
-
-    /**
-     *  The transition filename
-     */
-    protected String mFilename;
-
-    protected MediaArtistNativeHelper mNativeHelper;
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private Transition() {
-        this(null, null, null, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param transitionId The transition id
-     * @param afterMediaItem The transition is applied to the end of this
-     *      media item
-     * @param beforeMediaItem The transition is applied to the beginning of
-     *      this media item
-     * @param durationMs The duration of the transition in milliseconds
-     * @param behavior The transition behavior
-     */
-    protected Transition(String transitionId, MediaItem afterMediaItem,
-                         MediaItem beforeMediaItem,long durationMs,
-                         int behavior) {
-        if (behavior < BEHAVIOR_MIN_VALUE || behavior > BEHAVIOR_MAX_VALUE) {
-            throw new IllegalArgumentException("Invalid behavior: " + behavior);
-        }
-        if ((afterMediaItem == null) && (beforeMediaItem == null)) {
-            throw new IllegalArgumentException("Null media items");
-        }
-        mUniqueId = transitionId;
-        mAfterMediaItem = afterMediaItem;
-        mBeforeMediaItem = beforeMediaItem;
-        mDurationMs = durationMs;
-        mBehavior = behavior;
-        mNativeHelper = null;
-        if (durationMs > getMaximumDuration()) {
-            throw new IllegalArgumentException("The duration is too large");
-        }
-        if (afterMediaItem != null) {
-            mNativeHelper = afterMediaItem.getNativeContext();
-        }else {
-            mNativeHelper = beforeMediaItem.getNativeContext();
-        }
-    }
-
-    /**
-     * Get the ID of the transition.
-     *
-     * @return The ID of the transition
-     */
-    public String getId() {
-        return mUniqueId;
-    }
-
-    /**
-     * Get the media item at the end of which the transition is applied.
-     *
-     * @return The media item at the end of which the transition is applied
-     */
-    public MediaItem getAfterMediaItem() {
-        return mAfterMediaItem;
-    }
-
-    /**
-     * Get the media item at the beginning of which the transition is applied.
-     *
-     * @return The media item at the beginning of which the transition is
-     *      applied
-     */
-    public MediaItem getBeforeMediaItem() {
-        return mBeforeMediaItem;
-    }
-
-    /**
-     * Set the duration of the transition.
-     *
-     * @param durationMs the duration of the transition in milliseconds
-     */
-    public void setDuration(long durationMs) {
-        if (durationMs > getMaximumDuration()) {
-            throw new IllegalArgumentException("The duration is too large");
-        }
-
-        mDurationMs = durationMs;
-        invalidate();
-        mNativeHelper.setGeneratePreview(true);
-    }
-
-    /**
-     * Get the duration of the transition.
-     *
-     * @return the duration of the transition in milliseconds
-     */
-    public long getDuration() {
-        return mDurationMs;
-    }
-
-    /**
-     * The duration of a transition cannot be greater than half of the minimum
-     * duration of the bounding media items.
-     *
-     * @return The maximum duration of this transition
-     */
-    public long getMaximumDuration() {
-        if (mAfterMediaItem == null) {
-            return mBeforeMediaItem.getTimelineDuration() / 2;
-        } else if (mBeforeMediaItem == null) {
-            return mAfterMediaItem.getTimelineDuration() / 2;
-        } else {
-            return (Math.min(mAfterMediaItem.getTimelineDuration(),
-                    mBeforeMediaItem.getTimelineDuration()) / 2);
-        }
-    }
-
-    /**
-     * Get the behavior of the transition.
-     *
-     * @return The behavior
-     */
-    public int getBehavior() {
-        return mBehavior;
-    }
-
-    /**
-     * Get the transition data.
-     *
-     * @return The transition data in TransitionSettings object
-     * {@link android.media.videoeditor.MediaArtistNativeHelper.TransitionSettings}
-     */
-    TransitionSettings getTransitionSettings() {
-        TransitionAlpha transitionAlpha = null;
-        TransitionSliding transitionSliding = null;
-        TransitionCrossfade transitionCrossfade = null;
-        TransitionFadeBlack transitionFadeBlack = null;
-        TransitionSettings transitionSetting = null;
-        transitionSetting = new TransitionSettings();
-        transitionSetting.duration = (int)getDuration();
-        if (this instanceof TransitionAlpha) {
-            transitionAlpha = (TransitionAlpha)this;
-            transitionSetting.videoTransitionType = VideoTransition.ALPHA_MAGIC;
-            transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
-            transitionSetting.transitionBehaviour = mNativeHelper
-            .getVideoTransitionBehaviour(transitionAlpha.getBehavior());
-            transitionSetting.alphaSettings = new AlphaMagicSettings();
-            transitionSetting.slideSettings = null;
-            transitionSetting.alphaSettings.file = transitionAlpha.getPNGMaskFilename();
-            transitionSetting.alphaSettings.blendingPercent = transitionAlpha.getBlendingPercent();
-            transitionSetting.alphaSettings.invertRotation = transitionAlpha.isInvert();
-            transitionSetting.alphaSettings.rgbWidth = transitionAlpha.getRGBFileWidth();
-            transitionSetting.alphaSettings.rgbHeight = transitionAlpha.getRGBFileHeight();
-
-        } else if (this instanceof TransitionSliding) {
-            transitionSliding = (TransitionSliding)this;
-            transitionSetting.videoTransitionType = VideoTransition.SLIDE_TRANSITION;
-            transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
-            transitionSetting.transitionBehaviour = mNativeHelper
-            .getVideoTransitionBehaviour(transitionSliding.getBehavior());
-            transitionSetting.alphaSettings = null;
-            transitionSetting.slideSettings = new SlideTransitionSettings();
-            transitionSetting.slideSettings.direction = mNativeHelper
-            .getSlideSettingsDirection(transitionSliding.getDirection());
-        } else if (this instanceof TransitionCrossfade) {
-            transitionCrossfade = (TransitionCrossfade)this;
-            transitionSetting.videoTransitionType = VideoTransition.CROSS_FADE;
-            transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
-            transitionSetting.transitionBehaviour = mNativeHelper
-            .getVideoTransitionBehaviour(transitionCrossfade.getBehavior());
-            transitionSetting.alphaSettings = null;
-            transitionSetting.slideSettings = null;
-        } else if (this instanceof TransitionFadeBlack) {
-            transitionFadeBlack = (TransitionFadeBlack)this;
-            transitionSetting.videoTransitionType = VideoTransition.FADE_BLACK;
-            transitionSetting.audioTransitionType = AudioTransition.CROSS_FADE;
-            transitionSetting.transitionBehaviour = mNativeHelper
-            .getVideoTransitionBehaviour(transitionFadeBlack.getBehavior());
-            transitionSetting.alphaSettings = null;
-            transitionSetting.slideSettings = null;
-        }
-
-        return transitionSetting;
-    }
-
-    /**
-     * Checks if the effect and overlay applied on a media item
-     * overlaps with the transition on media item.
-     *
-     * @param m The media item
-     * @param clipSettings The ClipSettings object
-     * @param clipNo The clip no.(out of the two media items
-     * associated with current transition)for which the effect
-     * clip should be generated
-     * @return List of effects that overlap with the transition
-     */
-
-    List<EffectSettings>  isEffectandOverlayOverlapping(MediaItem m, ClipSettings clipSettings,
-                                         int clipNo) {
-        List<Effect> effects;
-        List<Overlay> overlays;
-        List<EffectSettings> effectSettings = new ArrayList<EffectSettings>();
-        EffectSettings tmpEffectSettings;
-
-        overlays = m.getAllOverlays();
-        for (Overlay overlay : overlays) {
-            tmpEffectSettings = mNativeHelper.getOverlaySettings((OverlayFrame)overlay);
-            mNativeHelper.adjustEffectsStartTimeAndDuration(tmpEffectSettings,
-                    clipSettings.beginCutTime, clipSettings.endCutTime);
-            if (tmpEffectSettings.duration != 0) {
-                effectSettings.add(tmpEffectSettings);
-            }
-        }
-
-        effects = m.getAllEffects();
-        for (Effect effect : effects) {
-            if (effect instanceof EffectColor) {
-                tmpEffectSettings = mNativeHelper.getEffectSettings((EffectColor)effect);
-                mNativeHelper.adjustEffectsStartTimeAndDuration(tmpEffectSettings,
-                        clipSettings.beginCutTime, clipSettings.endCutTime);
-                if (tmpEffectSettings.duration != 0) {
-                    if (m instanceof MediaVideoItem) {
-                        tmpEffectSettings.fiftiesFrameRate = mNativeHelper
-                        .GetClosestVideoFrameRate(((MediaVideoItem)m).getFps());
-                    }
-                    effectSettings.add(tmpEffectSettings);
-                }
-            }
-        }
-
-         return effectSettings;
-    }
-
-    /**
-     * Generate the video clip for the specified transition. This method may
-     * block for a significant amount of time. Before the method completes
-     * execution it sets the mFilename to the name of the newly generated
-     * transition video clip file.
-     */
-    void generate() {
-        MediaItem m1 = this.getAfterMediaItem();
-        MediaItem m2 = this.getBeforeMediaItem();
-        ClipSettings clipSettings1 = new ClipSettings();
-        ClipSettings clipSettings2 = new ClipSettings();
-        TransitionSettings transitionSetting = null;
-        EditSettings editSettings = new EditSettings();
-        List<EffectSettings> effectSettings_clip1;
-        List<EffectSettings> effectSettings_clip2;
-
-        String output = null;
-
-        if (mNativeHelper == null) {
-            if (m1 != null)
-                mNativeHelper = m1.getNativeContext();
-            else if (m2 != null)
-                mNativeHelper = m2.getNativeContext();
-        }
-        transitionSetting = getTransitionSettings();
-        if (m1 != null && m2 != null) {
-            /* transition between media items */
-            clipSettings1 = m1.getClipSettings();
-            clipSettings2 = m2.getClipSettings();
-            clipSettings1.beginCutTime = (int)(clipSettings1.endCutTime -
-                                                              this.mDurationMs);
-            clipSettings2.endCutTime = (int)(clipSettings2.beginCutTime +
-                                                              this.mDurationMs);
-            /*
-             * Check how many effects and overlays overlap with transition and
-             * generate effect clip first if there is any overlap
-             */
-            effectSettings_clip1 = isEffectandOverlayOverlapping(m1, clipSettings1,1);
-            effectSettings_clip2 = isEffectandOverlayOverlapping(m2, clipSettings2,2);
-            for (int index = 0; index < effectSettings_clip2.size(); index++ ) {
-                effectSettings_clip2.get(index).startTime += this.mDurationMs;
-            }
-            editSettings.effectSettingsArray =
-                                              new EffectSettings[effectSettings_clip1.size()
-                                                 + effectSettings_clip2.size()];
-            int i=0,j=0;
-            while (i < effectSettings_clip1.size()) {
-                editSettings.effectSettingsArray[j] = effectSettings_clip1.get(i);
-                i++;
-                j++;
-            }
-            i=0;
-            while (i < effectSettings_clip2.size()) {
-                editSettings.effectSettingsArray[j] = effectSettings_clip2.get(i);
-                i++;
-                j++;
-            }
-        } else if (m1 == null && m2 != null) {
-            /* begin transition at first media item */
-            m2.generateBlankFrame(clipSettings1);
-            clipSettings2 = m2.getClipSettings();
-            clipSettings1.endCutTime = (int)(this.mDurationMs + 50);
-            clipSettings2.endCutTime = (int)(clipSettings2.beginCutTime +
-                                                              this.mDurationMs);
-            /*
-             * Check how many effects and overlays overlap with transition and
-             * generate effect clip first if there is any overlap
-             */
-            effectSettings_clip2 = isEffectandOverlayOverlapping(m2, clipSettings2,2);
-            for (int index = 0; index < effectSettings_clip2.size(); index++ ) {
-                effectSettings_clip2.get(index).startTime += this.mDurationMs;
-            }
-            editSettings.effectSettingsArray = new EffectSettings[effectSettings_clip2.size()];
-            int i=0, j=0;
-            while (i < effectSettings_clip2.size()) {
-                editSettings.effectSettingsArray[j] = effectSettings_clip2.get(i);
-                i++;
-                j++;
-            }
-        } else if (m1 != null && m2 == null) {
-            /* end transition at last media item */
-            clipSettings1 = m1.getClipSettings();
-            m1.generateBlankFrame(clipSettings2);
-            clipSettings1.beginCutTime = (int)(clipSettings1.endCutTime -
-                                                              this.mDurationMs);
-            clipSettings2.endCutTime = (int)(this.mDurationMs + 50);
-            /*
-             * Check how many effects and overlays overlap with transition and
-             * generate effect clip first if there is any overlap
-             */
-            effectSettings_clip1 = isEffectandOverlayOverlapping(m1, clipSettings1,1);
-            editSettings.effectSettingsArray = new EffectSettings[effectSettings_clip1.size()];
-            int i=0,j=0;
-            while (i < effectSettings_clip1.size()) {
-                editSettings.effectSettingsArray[j] = effectSettings_clip1.get(i);
-                i++;
-                j++;
-            }
-        }
-
-        editSettings.clipSettingsArray = new ClipSettings[2];
-        editSettings.clipSettingsArray[0] = clipSettings1;
-        editSettings.clipSettingsArray[1] = clipSettings2;
-        editSettings.backgroundMusicSettings = null;
-        editSettings.transitionSettingsArray = new TransitionSettings[1];
-        editSettings.transitionSettingsArray[0] = transitionSetting;
-        output = mNativeHelper.generateTransitionClip(editSettings, mUniqueId,
-                                                      m1, m2,this);
-        setFilename(output);
-    }
-
-
-    /**
-     * Set the transition filename.
-     */
-    void setFilename(String filename) {
-        mFilename = filename;
-    }
-
-    /**
-     * Get the transition filename.
-     */
-    String getFilename() {
-        return mFilename;
-    }
-
-    /**
-     * Remove any resources associated with this transition
-     */
-    void invalidate() {
-        if (mFilename != null) {
-            new File(mFilename).delete();
-            mFilename = null;
-        }
-    }
-
-    /**
-     * Check if the transition is generated.
-     *
-     * @return true if the transition is generated
-     */
-    boolean isGenerated() {
-        return (mFilename != null);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public boolean equals(Object object) {
-        if (!(object instanceof Transition)) {
-            return false;
-        }
-        return mUniqueId.equals(((Transition)object).mUniqueId);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public int hashCode() {
-        return mUniqueId.hashCode();
-    }
-}
diff --git a/media/java/android/media/videoeditor/TransitionAlpha.java b/media/java/android/media/videoeditor/TransitionAlpha.java
deleted file mode 100644
index 22788d4..0000000
--- a/media/java/android/media/videoeditor/TransitionAlpha.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import java.io.DataOutputStream;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.IntBuffer;
-
-/**
- * This class allows to render an "alpha blending" transition according to a
- * bitmap mask. The mask shows the shape of the transition all along the
- * duration of the transition: just before the transition, video 1 is fully
- * displayed. When the transition starts, as the time goes on, pixels of video 2
- * replace pixels of video 1 according to the gray scale pixel value of the
- * mask.
- * {@hide}
- */
-public class TransitionAlpha extends Transition {
-    /** This is the input JPEG file for the mask */
-    private final String mMaskFilename;
-
-    /**
-     * This is percentage (between 0 and 100) of blending between video 1 and
-     * video 2 if this value equals 0, then the mask is strictly applied if this
-     * value equals 100, then the mask is not at all applied (no transition
-     * effect)
-     */
-    private final int mBlendingPercent;
-
-    /**
-     * If true, this value inverts the direction of the mask: white pixels of
-     * the mask show video 2 pixels first black pixels of the mask show video 2
-     * pixels last.
-     */
-    private final boolean mIsInvert;
-
-
-    private int mWidth;
-    private int mHeight;
-    private String mRGBMaskFile;
-
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private TransitionAlpha() {
-        this(null, null, null, 0, 0, null, 0, false);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param transitionId The transition id
-     * @param afterMediaItem The transition is applied to the end of this media
-     *            item
-     * @param beforeMediaItem The transition is applied to the beginning of this
-     *            media item
-     * @param durationMs duration of the transition in milliseconds
-     * @param behavior behavior is one of the behavior defined in Transition
-     *            class
-     * @param maskFilename JPEG file name. The dimension of the image
-     *           corresponds to 720p (16:9 aspect ratio). Mask files are
-     *           shared between video editors and can be created in the
-     *           projects folder (the parent folder for all projects).
-     * @param blendingPercent The blending percent applied
-     * @param invert true to invert the direction of the alpha blending
-     * @throws IllegalArgumentException if behavior is not supported, or if
-     *             direction are not supported.
-     */
-    public TransitionAlpha(String transitionId, MediaItem afterMediaItem,
-            MediaItem beforeMediaItem, long durationMs, int behavior,
-            String maskFilename, int blendingPercent, boolean invert) {
-        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
-
-        /**
-         * Generate a RGB file for the supplied mask file
-         */
-        final BitmapFactory.Options dbo = new BitmapFactory.Options();
-        dbo.inJustDecodeBounds = true;
-        if (!new File(maskFilename).exists())
-            throw new IllegalArgumentException("File not Found " + maskFilename);
-        BitmapFactory.decodeFile(maskFilename, dbo);
-
-        mWidth = dbo.outWidth;
-        mHeight = dbo.outHeight;
-
-        mRGBMaskFile = String.format(mNativeHelper.getProjectPath() +
-                "/" + "mask" + transitionId+ ".rgb");
-
-
-        FileOutputStream fl = null;
-
-        try{
-             fl = new FileOutputStream(mRGBMaskFile);
-        } catch (IOException e) {
-            /* catch IO exception */
-        }
-        final DataOutputStream dos = new DataOutputStream(fl);
-
-        if (fl != null) {
-            /**
-             * Write to rgb file
-             */
-            Bitmap imageBitmap = BitmapFactory.decodeFile(maskFilename);
-            final int [] framingBuffer = new int[mWidth];
-            ByteBuffer byteBuffer = ByteBuffer.allocate(framingBuffer.length * 4);
-            IntBuffer intBuffer;
-
-            byte[] array = byteBuffer.array();
-            int tmp = 0;
-            while (tmp < mHeight) {
-                imageBitmap.getPixels(framingBuffer, 0, mWidth, 0, tmp,mWidth, 1);
-                intBuffer = byteBuffer.asIntBuffer();
-                intBuffer.put(framingBuffer,0,mWidth);
-                try {
-                    dos.write(array);
-                } catch (IOException e) {
-                    /* catch file write error */
-                }
-                tmp += 1;
-            }
-
-            imageBitmap.recycle();
-            try{
-                fl.close();
-            }catch (IOException e) {
-                /* file close error */
-            }
-        }
-
-        /**
-         * Capture the details
-         */
-        mMaskFilename = maskFilename;
-        mBlendingPercent = blendingPercent;
-        mIsInvert = invert;
-    }
-
-    public int getRGBFileWidth() {
-        return mWidth;
-    }
-
-    public int getRGBFileHeight() {
-        return mHeight;
-    }
-
-    public String getPNGMaskFilename() {
-        return mRGBMaskFile;
-    }
-
-    /**
-     * Get the blending percentage
-     *
-     * @return The blending percentage
-     */
-    public int getBlendingPercent() {
-        return mBlendingPercent;
-    }
-
-    /**
-     * Get the filename of the mask.
-     *
-     * @return The mask filename
-     */
-    public String getMaskFilename() {
-        return mMaskFilename;
-    }
-
-    /**
-     * Check if the alpha blending direction is inverted.
-     *
-     * @return true if the direction of the alpha blending is inverted
-     */
-    public boolean isInvert() {
-        return mIsInvert;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    public void generate() {
-        super.generate();
-    }
-}
diff --git a/media/java/android/media/videoeditor/TransitionCrossfade.java b/media/java/android/media/videoeditor/TransitionCrossfade.java
deleted file mode 100644
index 417c64e..0000000
--- a/media/java/android/media/videoeditor/TransitionCrossfade.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-
-/**
- * This class allows to render a crossfade (dissolve) effect transition between
- * two videos
- * {@hide}
- */
-public class TransitionCrossfade extends Transition {
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private TransitionCrossfade() {
-        this(null, null, null, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param transitionId The transition id
-     * @param afterMediaItem The transition is applied to the end of this
-     *      media item
-     * @param beforeMediaItem The transition is applied to the beginning of
-     *      this media item
-     * @param durationMs duration of the transition in milliseconds
-     * @param behavior behavior is one of the behavior defined in Transition
-     *      class
-     *
-     * @throws IllegalArgumentException if behavior is not supported.
-     */
-    public TransitionCrossfade(String transitionId, MediaItem afterMediaItem,
-            MediaItem beforeMediaItem, long durationMs, int behavior) {
-        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void generate() {
-        super.generate();
-    }
-}
diff --git a/media/java/android/media/videoeditor/TransitionFadeBlack.java b/media/java/android/media/videoeditor/TransitionFadeBlack.java
deleted file mode 100644
index da07cf0..0000000
--- a/media/java/android/media/videoeditor/TransitionFadeBlack.java
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-
-/**
- * This class is used to render a fade to black and fade from black transition
- * between two media items.
- * {@hide}
- */
-public class TransitionFadeBlack extends Transition {
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private TransitionFadeBlack() {
-        this(null, null, null, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param transitionId The transition id
-     * @param afterMediaItem The transition is applied to the end of this
-     *      media item
-     * @param beforeMediaItem The transition is applied to the beginning of
-     *      this media item
-     * @param durationMs duration of the transition
-     * @param behavior behavior is one of the behavior defined in Transition
-     *      class
-     *
-     * @throws IllegalArgumentException if behavior is not supported.
-     */
-    public TransitionFadeBlack(String transitionId, MediaItem afterMediaItem,
-            MediaItem beforeMediaItem, long durationMs, int behavior) {
-        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void generate() {
-        super.generate();
-    }
-}
diff --git a/media/java/android/media/videoeditor/TransitionSliding.java b/media/java/android/media/videoeditor/TransitionSliding.java
deleted file mode 100644
index 57610ab..0000000
--- a/media/java/android/media/videoeditor/TransitionSliding.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-/**
- * This class allows to create sliding transitions
- * {@hide}
- */
-public class TransitionSliding extends Transition {
-
-    /** Video 1 is pushed to the right while video 2 is coming from left */
-    public final static int DIRECTION_RIGHT_OUT_LEFT_IN = 0;
-    /** Video 1 is pushed to the left while video 2 is coming from right */
-    public static final int DIRECTION_LEFT_OUT_RIGHT_IN = 1;
-    /** Video 1 is pushed to the top while video 2 is coming from bottom */
-    public static final int DIRECTION_TOP_OUT_BOTTOM_IN = 2;
-    /** Video 1 is pushed to the bottom while video 2 is coming from top */
-    public static final int DIRECTION_BOTTOM_OUT_TOP_IN = 3;
-
-    // The sliding transitions
-    private final int mSlidingDirection;
-
-    /**
-     * An object of this type cannot be instantiated by using the default
-     * constructor
-     */
-    @SuppressWarnings("unused")
-    private TransitionSliding() {
-        this(null, null, null, 0, 0, 0);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param transitionId The transition id
-     * @param afterMediaItem The transition is applied to the end of this
-     *      media item
-     * @param beforeMediaItem The transition is applied to the beginning of
-     *      this media item
-     * @param durationMs duration of the transition in milliseconds
-     * @param behavior behavior is one of the behavior defined in Transition
-     *            class
-     * @param direction direction shall be one of the supported directions like
-     *            RIGHT_OUT_LEFT_IN
-     *
-     * @throws IllegalArgumentException if behavior is not supported.
-     */
-    public TransitionSliding(String transitionId, MediaItem afterMediaItem,
-            MediaItem beforeMediaItem, long durationMs, int behavior,
-            int direction) {
-        super(transitionId, afterMediaItem, beforeMediaItem, durationMs, behavior);
-        switch (direction) {
-            case DIRECTION_RIGHT_OUT_LEFT_IN:
-            case DIRECTION_LEFT_OUT_RIGHT_IN:
-            case DIRECTION_TOP_OUT_BOTTOM_IN:
-            case DIRECTION_BOTTOM_OUT_TOP_IN:
-                break;
-
-            default:
-                throw new IllegalArgumentException("Invalid direction");
-        }
-        mSlidingDirection = direction;
-    }
-
-    /**
-     * Get the sliding direction.
-     *
-     * @return The sliding direction
-     */
-    public int getDirection() {
-        return mSlidingDirection;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    @Override
-    void generate() {
-        super.generate();
-    }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditor.java b/media/java/android/media/videoeditor/VideoEditor.java
deleted file mode 100644
index 08d27d4..0000000
--- a/media/java/android/media/videoeditor/VideoEditor.java
+++ /dev/null
@@ -1,774 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.CancellationException;
-import android.graphics.Bitmap;
-import android.graphics.Color;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Rect;
-import android.view.SurfaceHolder;
-
-/**
- * This is the interface implemented by classes which provide video editing
- * functionality. The VideoEditor implementation class manages all input and
- * output files. Unless specifically mentioned, methods are blocking. A typical
- * editing session may consist of the following sequence of operations:
- *
- * <ul>
- *  <li>Add a set of MediaItems</li>
- *  <li>Apply a set of Transitions between MediaItems</li>
- *  <li>Add Effects and Overlays to media items</li>
- *  <li>Preview the movie at any time</li>
- *  <li>Save the VideoEditor implementation class internal state</li>
- *  <li>Release the VideoEditor implementation class instance by invoking
- * {@link #release()}
- * </ul>
- * The internal VideoEditor state consists of the following elements:
- * <ul>
- *  <li>Ordered & trimmed MediaItems</li>
- *  <li>Transition video clips</li>
- *  <li>Overlays</li>
- *  <li>Effects</li>
- *  <li>Audio waveform for the background audio and MediaItems</li>
- *  <li>Project thumbnail</li>
- *  <li>Last exported movie.</li>
- *  <li>Other project specific data such as the current aspect ratio.</li>
- * </ul>
- * {@hide}
- */
-public interface VideoEditor {
-    /**
-     *  The file name of the project thumbnail
-     */
-    public static final String THUMBNAIL_FILENAME = "thumbnail.jpg";
-
-    /**
-     *  Use this value instead of the specific end of the storyboard timeline
-     *  value.
-     */
-    public final static int DURATION_OF_STORYBOARD = -1;
-
-    /**
-     *  Maximum supported file size
-     */
-    public static final long MAX_SUPPORTED_FILE_SIZE = 2147483648L;
-
-    /**
-     * This listener interface is used by the VideoEditor to emit preview
-     * progress notifications. This callback should be invoked after the number
-     * of frames specified by
-     * {@link #startPreview(SurfaceHolder surfaceHolder, long fromMs,
-     *           int callbackAfterFrameCount, PreviewProgressListener listener)}
-     */
-    public interface PreviewProgressListener {
-        /**
-         * This method notifies the listener of the current time position while
-         * previewing a project.
-         *
-         * @param videoEditor The VideoEditor instance
-         * @param timeMs The current preview position (expressed in milliseconds
-         *        since the beginning of the storyboard timeline).
-         * @param overlayData The overlay data (null if the overlay data
-         *      is unchanged)
-         */
-        public void onProgress(VideoEditor videoEditor, long timeMs,
-                               OverlayData overlayData);
-        /**
-         * This method notifies the listener when the preview is started
-         * previewing a project.
-         *
-         * @param videoEditor The VideoEditor instance
-         */
-        public void onStart(VideoEditor videoEditor);
-
-        /**
-         * This method notifies the listener when the preview is stopped
-         * previewing a project.
-         *
-         * @param videoEditor The VideoEditor instance
-         */
-        public void onStop(VideoEditor videoEditor);
-
-        /**
-         * This method notifies the listener when error has occurred during
-         * previewing a project.
-         *
-         * @param videoEditor The VideoEditor instance
-         * @param error The error that has occurred
-         * FIXME: We should pass well-defined error code to the application;
-         * but for now, we just pass whatever error code reported by the native layer.
-         */
-        public void onError(VideoEditor videoEditor, int error);
-    }
-
-    /**
-     * This listener interface is used by the VideoEditor to emit export status
-     * notifications.
-     * {@link #export(String filename, ExportProgressListener listener,
-     *                int height, int bitrate)}
-     */
-    public interface ExportProgressListener {
-        /**
-         * This method notifies the listener of the progress status of a export
-         * operation.
-         *
-         * @param videoEditor The VideoEditor instance
-         * @param filename The name of the file which is in the process of being
-         *        exported.
-         * @param progress The progress in %. At the beginning of the export,
-         *        this value is set to 0; at the end, the value is set to 100.
-         */
-        public void onProgress(VideoEditor videoEditor, String filename,
-                              int progress);
-    }
-
-    public interface MediaProcessingProgressListener {
-        /**
-         *  Values used for the action parameter
-         */
-        public static final int ACTION_ENCODE = 1;
-        public static final int ACTION_DECODE = 2;
-
-        /**
-         * This method notifies the listener of the progress status of
-         * processing a media object such as a Transition, AudioTrack & Kenburns
-         * This method may be called maximum 100 times for one operation.
-         *
-         * @param object The object that is being processed such as a Transition
-         *               or AudioTrack
-         * @param action The type of processing being performed
-         * @param progress The progress in %. At the beginning of the operation,
-         *          this value is set to 0; at the end, the value is set to 100.
-         */
-        public void onProgress(Object item, int action, int progress);
-    }
-
-    /**
-     * The overlay data
-     */
-    public static final class OverlayData {
-        // Instance variables
-        private Bitmap mOverlayBitmap;
-        private int mRenderingMode;
-        private boolean mClear;
-        private static final Paint sResizePaint = new Paint(Paint.FILTER_BITMAP_FLAG);
-
-        /**
-         * Default constructor
-         */
-        public OverlayData() {
-            mOverlayBitmap = null;
-            mRenderingMode = MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS;
-            mClear = false;
-        }
-
-        /**
-         * Releases the bitmap
-         */
-        public void release() {
-            if (mOverlayBitmap != null) {
-                mOverlayBitmap.recycle();
-                mOverlayBitmap = null;
-            }
-        }
-
-        /**
-         * Check if the overlay needs to be rendered
-         *
-         * @return true if rendering is needed
-         */
-        public boolean needsRendering() {
-            return (mClear || mOverlayBitmap != null);
-        }
-
-        /**
-         * Store the overlay data
-         *
-         * @param overlayBitmap The overlay bitmap
-         * @param renderingMode The rendering mode
-         */
-        void set(Bitmap overlayBitmap, int renderingMode) {
-            mOverlayBitmap = overlayBitmap;
-            mRenderingMode = renderingMode;
-            mClear = false;
-        }
-
-        /**
-         * Clear the overlay
-         */
-        void setClear() {
-            mClear = true;
-        }
-
-        /**
-        * Render the overlay by either clearing it or by
-        * rendering the overlay bitmap with the specified
-        * rendering mode
-        *
-        * @param destBitmap The destination bitmap
-        */
-        public void renderOverlay(Bitmap destBitmap) {
-            if (mClear) {
-                destBitmap.eraseColor(Color.TRANSPARENT);
-            } else if (mOverlayBitmap != null) {
-                final Canvas overlayCanvas = new Canvas(destBitmap);
-                final Rect destRect;
-                final Rect srcRect;
-                switch (mRenderingMode) {
-                    case MediaArtistNativeHelper.MediaRendering.RESIZING: {
-                        destRect = new Rect(0, 0, overlayCanvas.getWidth(),
-                                                 overlayCanvas.getHeight());
-                        srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(),
-                                                 mOverlayBitmap.getHeight());
-                        break;
-                    }
-
-                    case MediaArtistNativeHelper.MediaRendering.BLACK_BORDERS: {
-                        int left, right, top, bottom;
-                        float aROverlayImage, aRCanvas;
-                        aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
-                                         (float)(mOverlayBitmap.getHeight());
-
-                        aRCanvas = (float)(overlayCanvas.getWidth()) /
-                                         (float)(overlayCanvas.getHeight());
-
-                        if (aROverlayImage > aRCanvas) {
-                            int newHeight = ((overlayCanvas.getWidth() * mOverlayBitmap.getHeight())
-                                             / mOverlayBitmap.getWidth());
-                            left = 0;
-                            top  = (overlayCanvas.getHeight() - newHeight) / 2;
-                            right = overlayCanvas.getWidth();
-                            bottom = top + newHeight;
-                        } else {
-                            int newWidth = ((overlayCanvas.getHeight() * mOverlayBitmap.getWidth())
-                                                / mOverlayBitmap.getHeight());
-                            left = (overlayCanvas.getWidth() - newWidth) / 2;
-                            top  = 0;
-                            right = left + newWidth;
-                            bottom = overlayCanvas.getHeight();
-                        }
-
-                        destRect = new Rect(left, top, right, bottom);
-                        srcRect = new Rect(0, 0, mOverlayBitmap.getWidth(), mOverlayBitmap.getHeight());
-                        break;
-                    }
-
-                    case MediaArtistNativeHelper.MediaRendering.CROPPING: {
-                        // Calculate the source rect
-                        int left, right, top, bottom;
-                        float aROverlayImage, aRCanvas;
-                        aROverlayImage = (float)(mOverlayBitmap.getWidth()) /
-                                         (float)(mOverlayBitmap.getHeight());
-                        aRCanvas = (float)(overlayCanvas.getWidth()) /
-                                        (float)(overlayCanvas.getHeight());
-                        if (aROverlayImage < aRCanvas) {
-                            int newHeight = ((mOverlayBitmap.getWidth() * overlayCanvas.getHeight())
-                                       / overlayCanvas.getWidth());
-
-                            left = 0;
-                            top  = (mOverlayBitmap.getHeight() - newHeight) / 2;
-                            right = mOverlayBitmap.getWidth();
-                            bottom = top + newHeight;
-                        } else {
-                            int newWidth = ((mOverlayBitmap.getHeight() * overlayCanvas.getWidth())
-                                        / overlayCanvas.getHeight());
-                            left = (mOverlayBitmap.getWidth() - newWidth) / 2;
-                            top  = 0;
-                            right = left + newWidth;
-                            bottom = mOverlayBitmap.getHeight();
-                        }
-
-                        srcRect = new Rect(left, top, right, bottom);
-                        destRect = new Rect(0, 0, overlayCanvas.getWidth(), overlayCanvas.getHeight());
-                        break;
-                    }
-
-                    default: {
-                        throw new IllegalStateException("Rendering mode: " + mRenderingMode);
-                    }
-                }
-
-                destBitmap.eraseColor(Color.TRANSPARENT);
-                overlayCanvas.drawBitmap(mOverlayBitmap, srcRect, destRect, sResizePaint);
-
-                mOverlayBitmap.recycle();
-            }
-        }
-    }
-
-    /**
-     * @return The path where the VideoEditor stores all files related to the
-     *         project
-     */
-    public String getPath();
-
-    /**
-     * This method releases all in-memory resources used by the VideoEditor
-     * instance. All pending operations such as preview, export and extract
-     * audio waveform must be canceled.
-     */
-    public void release();
-
-    /**
-     * Persist the current internal state of VideoEditor to the project path.
-     * The VideoEditor state may be restored by invoking the
-     * {@link VideoEditorFactory#load(String)} method. This method does not
-     * release the internal in-memory state of the VideoEditor. To release
-     * the in-memory state of the VideoEditor the {@link #release()} method
-     * must be invoked.
-     *
-     * Pending transition generations must be allowed to complete before the
-     * state is saved.
-     * Pending audio waveform generations must be allowed to complete.
-     * Pending export operations must be allowed to continue.
-     *
-     * @throws IOException if the internal state cannot be saved to project file
-     */
-    public void save() throws IOException;
-
-    /**
-     * Create the output movie based on all media items added and the applied
-     * storyboard items. This method can take a long time to execute and is
-     * blocking. The application will receive progress notifications via the
-     * ExportProgressListener. Specific implementations may not support multiple
-     * simultaneous export operations. Note that invoking methods which would
-     * change the contents of the output movie throw an IllegalStateException
-     * while an export operation is pending.
-     *
-     * The audio and video codecs are automatically selected by the underlying
-     * implementation.
-     *
-     * @param filename The output file name (including the full path)
-     * @param height The height of the output video file. The supported values
-     *        for height are described in the MediaProperties class, for
-     *        example: HEIGHT_480. The width will be automatically computed
-     *        according to the aspect ratio provided by
-     *        {@link #setAspectRatio(int)}
-     * @param bitrate The bitrate of the output video file. This is approximate
-     *        value for the output movie. Supported bitrate values are
-     *        described in the MediaProperties class for example: BITRATE_384K
-     * @param listener The listener for progress notifications. Use null if
-     *        export progress notifications are not needed.
-     *
-     * @throws IllegalArgumentException if height or bitrate are not supported
-     *        or if the audio or video codecs are not supported
-     * @throws IOException if output file cannot be created
-     * @throws IllegalStateException if a preview or an export is in progress or
-     *        if no MediaItem has been added
-     * @throws CancellationException if export is canceled by calling
-     *        {@link #cancelExport()}
-     * @throws UnsupportOperationException if multiple simultaneous export() are
-     *        not allowed
-     */
-    public void export(String filename, int height, int bitrate,
-                       ExportProgressListener listener)
-                       throws IOException;
-
-    /**
-     * Create the output movie based on all media items added and the applied
-     * storyboard items. This method can take a long time to execute and is
-     * blocking. The application will receive progress notifications via the
-     * ExportProgressListener. Specific implementations may not support multiple
-     * simultaneous export operations. Note that invoking methods which would
-     * change the contents of the output movie throw an IllegalStateException
-     * while an export operation is pending.
-     *
-     * @param filename The output file name (including the full path)
-     * @param height The height of the output video file. The supported values
-     *        for height are described in the MediaProperties class, for
-     *        example: HEIGHT_480. The width will be automatically computed
-     *        according to the aspect ratio provided by
-     *        {@link #setAspectRatio(int)}
-     * @param bitrate The bitrate of the output video file. This is approximate
-     *        value for the output movie. Supported bitrate values are
-     *        described in the MediaProperties class for example: BITRATE_384K
-     * @param audioCodec The audio codec to be used for the export. The audio
-     *        codec values are defined in the MediaProperties class (e.g.
-     *        ACODEC_AAC_LC). Note that not all audio codec types are
-     *        supported for export purposes.
-     * @param videoCodec The video codec to be used for the export. The video
-     *        codec values are defined in the MediaProperties class (e.g.
-     *        VCODEC_H264). Note that not all video codec types are
-     *        supported for export purposes.
-     * @param listener The listener for progress notifications. Use null if
-     *        export progress notifications are not needed.
-     *
-     * @throws IllegalArgumentException if height or bitrate are not supported
-     *        or if the audio or video codecs are not supported
-     * @throws IOException if output file cannot be created
-     * @throws IllegalStateException if a preview or an export is in progress or
-     *        if no MediaItem has been added
-     * @throws CancellationException if export is cancelled by calling
-     *        {@link #cancelExport()}
-     * @throws UnsupportOperationException if multiple simultaneous export() are
-     *        not allowed
-     */
-    public void export(String filename, int height, int bitrate, int audioCodec,
-                       int videoCodec, ExportProgressListener listener)
-                       throws IOException;
-
-    /**
-     * Cancel the running export operation. This method blocks until the export
-     * is cancelled and the exported file (if any) is deleted. If the export
-     * completed by the time this method is invoked, the export file will be
-     * deleted.
-     *
-     * @param filename The filename which identifies the export operation to be
-     *            canceled.
-     **/
-    public void cancelExport(String filename);
-
-    /**
-     * Add a media item at the end of the storyboard.
-     *
-     * @param mediaItem The media item object to add
-     *
-     * @throws IllegalStateException if a preview or an export is in progress or
-     *        if the media item id is not unique across all the media items
-     *        added.
-     */
-    public void addMediaItem(MediaItem mediaItem);
-
-    /**
-     * Insert a media item after the media item with the specified id.
-     *
-     * @param mediaItem The media item object to insert
-     * @param afterMediaItemId Insert the mediaItem after the media item
-     *        identified by this id. If this parameter is null, the media
-     *        item is inserted at the beginning of the timeline.
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if media item with the specified id does
-     *        not exist (null is a valid value) or if the media item id is
-     *        not unique across all the media items added.
-     */
-    public void insertMediaItem(MediaItem mediaItem, String afterMediaItemId);
-
-    /**
-     * Move a media item after the media item with the specified id.
-     *
-     * Note: The project thumbnail is regenerated if the media item is or
-     * becomes the first media item in the storyboard timeline.
-     *
-     * @param mediaItemId The id of the media item to move
-     * @param afterMediaItemId Move the media item identified by mediaItemId
-     *        after the media item identified by this parameter. If this
-     *        parameter is null, the media item is moved at the beginning of
-     *        the timeline.
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if one of media item ids is invalid
-     *        (null is a valid value)
-     */
-    public void moveMediaItem(String mediaItemId, String afterMediaItemId);
-
-    /**
-     * Remove the media item with the specified id. If there are transitions
-     * before or after this media item, then this/these transition(s) are
-     * removed from the storyboard. If the extraction of the audio waveform is
-     * in progress, the extraction is canceled and the file is deleted.
-     *
-     * Effects and overlays associated with the media item will also be removed.
-     *
-     * Note: The project thumbnail is regenerated if the media item which is
-     * removed is the first media item in the storyboard or if the media item is
-     * the only one in the storyboard. If the media item is the only one in the
-     * storyboard, the project thumbnail will be set to a black frame and the
-     * aspect ratio will revert to the default aspect ratio and this method is
-     * equivalent to removeAllMediaItems() in this case.
-     *
-     * @param mediaItemId The unique id of the media item to be removed
-     *
-     * @return The media item that was removed
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if media item with the specified id does
-     *        not exist
-     */
-    public MediaItem removeMediaItem(String mediaItemId);
-
-    /**
-     * Remove all media items in the storyboard. All effects, overlays and all
-     * transitions are also removed.
-     *
-     * Note: The project thumbnail will be set to a black frame and the aspect
-     * ratio will revert to the default aspect ratio.
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     */
-    public void removeAllMediaItems();
-
-    /**
-     * Get the list of media items in the order in which it they appear in the
-     * storyboard timeline.
-     *
-     * Note that if any media item source files are no longer
-     * accessible, this method will still provide the full list of media items.
-     *
-     * @return The list of media items. If no media item exist an empty list
-     *        will be returned.
-     */
-    public List<MediaItem> getAllMediaItems();
-
-    /**
-     * Find the media item with the specified id
-     *
-     * @param mediaItemId The media item id
-     *
-     * @return The media item with the specified id (null if it does not exist)
-     */
-    public MediaItem getMediaItem(String mediaItemId);
-
-    /**
-     * Add a transition between the media items specified by the transition.
-     * If a transition existed at the same position it is invalidated and then
-     * the transition is replaced. Note that the new transition video clip is
-     * not automatically generated by this method. The
-     * {@link Transition#generate()} method must be invoked to generate
-     * the transition video clip.
-     *
-     * Note that the TransitionAtEnd and TransitionAtStart are special kinds
-     * that can not be applied between two media items.
-     *
-     * A crossfade audio transition will be automatically applied regardless of
-     * the video transition.
-     *
-     * @param transition The transition to apply
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if the transition duration is larger
-     *        than the smallest duration of the two media item files or if
-     *        the two media items specified in the transition are not
-     *        adjacent
-     */
-    public void addTransition(Transition transition);
-
-    /**
-     * Remove the transition with the specified id.
-     *
-     * @param transitionId The id of the transition to be removed
-     *
-     * @return The transition that was removed
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if transition with the specified id does
-     *        not exist
-     */
-    public Transition removeTransition(String transitionId);
-
-    /**
-     * Get the list of transitions
-     *
-     * @return The list of transitions. If no transitions exist an empty list
-     *        will be returned.
-     */
-    public List<Transition> getAllTransitions();
-
-    /**
-     * Find the transition with the specified transition id.
-     *
-     * @param transitionId The transition id
-     *
-     * @return The transition
-     */
-    public Transition getTransition(String transitionId);
-
-    /**
-     * Add the specified AudioTrack to the storyboard. Note: Specific
-     * implementations may support a limited number of audio tracks (e.g. only
-     * one audio track)
-     *
-     * @param audioTrack The AudioTrack to add
-     *
-     * @throws UnsupportedOperationException if the implementation supports a
-     *        limited number of audio tracks.
-     * @throws IllegalArgumentException if media item is not unique across all
-     *        the audio tracks already added.
-     */
-    public void addAudioTrack(AudioTrack audioTrack);
-
-    /**
-     * Insert an audio track after the audio track with the specified id. Use
-     * addAudioTrack to add an audio track at the end of the storyboard
-     * timeline.
-     *
-     * @param audioTrack The audio track object to insert
-     * @param afterAudioTrackId Insert the audio track after the audio track
-     *        identified by this parameter. If this parameter is null the
-     *        audio track is added at the beginning of the timeline.
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if media item with the specified id does
-     *        not exist (null is a valid value). if media item is not unique
-     *        across all the audio tracks already added.
-     * @throws UnsupportedOperationException if the implementation supports a
-     *        limited number of audio tracks
-     */
-    public void insertAudioTrack(AudioTrack audioTrack, String afterAudioTrackId);
-
-    /**
-     * Move an AudioTrack after the AudioTrack with the specified id.
-     *
-     * @param audioTrackId The id of the AudioTrack to move
-     * @param afterAudioTrackId Move the AudioTrack identified by audioTrackId
-     *        after the AudioTrack identified by this parameter. If this
-     *        parameter is null the audio track is added at the beginning of
-     *        the timeline.
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if one of media item ids is invalid
-     *        (null is a valid value)
-     */
-    public void moveAudioTrack(String audioTrackId, String afterAudioTrackId);
-
-    /**
-     * Remove the audio track with the specified id. If the extraction of the
-     * audio waveform is in progress, the extraction is canceled and the file is
-     * deleted.
-     *
-     * @param audioTrackId The id of the audio track to be removed
-     *
-     * @return The audio track that was removed
-     * @throws IllegalStateException if a preview or an export is in progress
-     */
-    public AudioTrack removeAudioTrack(String audioTrackId);
-
-    /**
-     * Get the list of AudioTracks in order in which they appear in the
-     * storyboard.
-     *
-     * Note that if any AudioTrack source files are not accessible anymore,
-     * this method will still provide the full list of audio tracks.
-     *
-     * @return The list of AudioTracks. If no audio tracks exist an empty list
-     *        will be returned.
-     */
-    public List<AudioTrack> getAllAudioTracks();
-
-    /**
-     * Find the AudioTrack with the specified id
-     *
-     * @param audioTrackId The AudioTrack id
-     *
-     * @return The AudioTrack with the specified id (null if it does not exist)
-     */
-    public AudioTrack getAudioTrack(String audioTrackId);
-
-    /**
-     * Set the aspect ratio used in the preview and the export movie.
-     *
-     * The default aspect ratio is ASPECTRATIO_16_9 (16:9).
-     *
-     * @param aspectRatio to apply. If aspectRatio is the same as the current
-     *        aspect ratio, then this function just returns. The supported
-     *        aspect ratio are defined in the MediaProperties class for
-     *        example: ASPECTRATIO_16_9
-     *
-     * @throws IllegalStateException if a preview or an export is in progress
-     * @throws IllegalArgumentException if aspect ratio is not supported
-     */
-    public void setAspectRatio(int aspectRatio);
-
-    /**
-     * Get current aspect ratio.
-     *
-     * @return The aspect ratio as described in MediaProperties
-     */
-    public int getAspectRatio();
-
-    /**
-     * Get the preview (and output movie) duration.
-     *
-     * @return The duration of the preview (and output movie)
-     */
-    public long getDuration();
-
-    /**
-     * Render a frame according to the preview aspect ratio and activating all
-     * storyboard items relative to the specified time.
-     *
-     * @param surfaceHolder SurfaceHolder used by the application
-     * @param timeMs time corresponding to the frame to display
-     * @param overlayData The overlay data
-     *
-     * @return The accurate time stamp of the frame that is rendered.
-     *
-     * @throws IllegalStateException if a preview or an export is already in
-     *        progress
-     * @throws IllegalArgumentException if time is negative or beyond the
-     *        preview duration
-     */
-    public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
-            OverlayData overlayData);
-
-    /**
-     * This method must be called after any changes made to the storyboard
-     * and before startPreview is called. Note that this method may block for an
-     * extensive period of time.
-     */
-    public void generatePreview(MediaProcessingProgressListener listener);
-
-    /**
-     * Start the preview of all the storyboard items applied on all MediaItems
-     * This method does not block (does not wait for the preview to complete).
-     * The PreviewProgressListener allows to track the progress at the time
-     * interval determined by the callbackAfterFrameCount parameter. The
-     * SurfaceHolder has to be created and ready for use before calling this
-     * method. The method is a no-op if there are no MediaItems in the
-     * storyboard.
-     *
-     * @param surfaceHolder SurfaceHolder where the preview is rendered.
-     * @param fromMs The time (relative to the timeline) at which the preview
-     *        will start
-     * @param toMs The time (relative to the timeline) at which the preview will
-     *        stop. Use -1 to play to the end of the timeline
-     * @param loop true if the preview should be looped once it reaches the end
-     * @param callbackAfterFrameCount The listener interface should be invoked
-     *        after the number of frames specified by this parameter.
-     * @param listener The listener which will be notified of the preview
-     *        progress
-     *
-     * @throws IllegalArgumentException if fromMs is beyond the preview duration
-     * @throws IllegalStateException if a preview or an export is already in
-     *        progress
-     */
-    public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs,
-                             boolean loop,int callbackAfterFrameCount,
-                             PreviewProgressListener listener);
-
-    /**
-     * Stop the current preview. This method blocks until ongoing preview is
-     * stopped. Ignored if there is no preview running.
-     *
-     * @return The accurate current time when stop is effective expressed in
-     *        milliseconds
-     */
-    public long stopPreview();
-
-    /**
-     * Clears the preview surface
-     *
-     * @param surfaceHolder SurfaceHolder where the preview is rendered
-     * and needs to be cleared.
-     */
-    public void clearSurface(SurfaceHolder surfaceHolder);
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorFactory.java b/media/java/android/media/videoeditor/VideoEditorFactory.java
deleted file mode 100644
index 85c329f..0000000
--- a/media/java/android/media/videoeditor/VideoEditorFactory.java
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-
-/**
- * The VideoEditorFactory class must be used to instantiate VideoEditor objects
- * by creating a new project {@link #create(String)} or by loading an
- * existing project {@link #load(String)}.
- * {@hide}
- */
-public class VideoEditorFactory {
-    /**
-     * This is the factory method for creating a new VideoEditor instance.
-     *
-     * @param projectPath The path where all VideoEditor internal
-     *            files are stored. When a project is deleted the application is
-     *            responsible for deleting the path and its contents.
-     *
-     * @return The VideoEditor instance
-     *
-     * @throws IOException if path does not exist or if the path can
-     *             not be accessed in read/write mode
-     */
-    public static VideoEditor create(String projectPath) throws IOException {
-        /*
-         *  If the project path does not exist create it
-         */
-        final File dir = new File(projectPath);
-        if (!dir.exists()) {
-            if (!dir.mkdirs()) {
-                throw new FileNotFoundException("Cannot create project path: "
-                                                                 + projectPath);
-            } else {
-                /*
-                 * Create the file which hides the media files
-                 * from the media scanner
-                 */
-                if (!new File(dir, ".nomedia").createNewFile()) {
-                    throw new FileNotFoundException("Cannot create file .nomedia");
-                }
-            }
-        }
-
-        return new VideoEditorImpl(projectPath);
-    }
-
-    /**
-     * This is the factory method for instantiating a VideoEditor from the
-     * internal state previously saved with the
-     * {@link VideoEditor#save(String)} method.
-     *
-     * @param projectPath The path where all VideoEditor internal files
-     *            are stored. When a project is deleted the application is
-     *            responsible for deleting the path and its contents.
-     * @param generatePreview if set to true the
-     *      {@link MediaEditor#generatePreview(MediaProcessingProgressListener
-     *             listener)}
-     *      will be called internally to generate any needed transitions.
-     *
-     * @return The VideoEditor instance
-     *
-     * @throws IOException if path does not exist or if the path can
-     *             not be accessed in read/write mode or if one of the resource
-     *             media files cannot be retrieved
-     */
-    public static VideoEditor load(String projectPath, boolean generatePreview)
-        throws IOException {
-        final VideoEditor videoEditor = new VideoEditorImpl(projectPath);
-        if (generatePreview) {
-            videoEditor.generatePreview(null);
-        }
-        return videoEditor;
-    }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorImpl.java b/media/java/android/media/videoeditor/VideoEditorImpl.java
deleted file mode 100644
index 2446c2f..0000000
--- a/media/java/android/media/videoeditor/VideoEditorImpl.java
+++ /dev/null
@@ -1,1976 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.MediaMetadataRetriever;
-import android.util.Log;
-import android.util.Xml;
-import android.view.Surface;
-import android.view.SurfaceHolder;
-import android.os.Debug;
-import android.os.SystemProperties;
-import android.os.Environment;
-
-/**
- * The VideoEditor implementation {@hide}
- */
-public class VideoEditorImpl implements VideoEditor {
-    /*
-     *  Logging
-     */
-    private static final String TAG = "VideoEditorImpl";
-
-    /*
-     *  The project filename
-     */
-    private static final String PROJECT_FILENAME = "videoeditor.xml";
-
-    /*
-     *  XML tags
-     */
-    private static final String TAG_PROJECT = "project";
-    private static final String TAG_MEDIA_ITEMS = "media_items";
-    private static final String TAG_MEDIA_ITEM = "media_item";
-    private static final String TAG_TRANSITIONS = "transitions";
-    private static final String TAG_TRANSITION = "transition";
-    private static final String TAG_OVERLAYS = "overlays";
-    private static final String TAG_OVERLAY = "overlay";
-    private static final String TAG_OVERLAY_USER_ATTRIBUTES = "overlay_user_attributes";
-    private static final String TAG_EFFECTS = "effects";
-    private static final String TAG_EFFECT = "effect";
-    private static final String TAG_AUDIO_TRACKS = "audio_tracks";
-    private static final String TAG_AUDIO_TRACK = "audio_track";
-
-    private static final String ATTR_ID = "id";
-    private static final String ATTR_FILENAME = "filename";
-    private static final String ATTR_AUDIO_WAVEFORM_FILENAME = "waveform";
-    private static final String ATTR_RENDERING_MODE = "rendering_mode";
-    private static final String ATTR_ASPECT_RATIO = "aspect_ratio";
-    private static final String ATTR_REGENERATE_PCM = "regeneratePCMFlag";
-    private static final String ATTR_TYPE = "type";
-    private static final String ATTR_DURATION = "duration";
-    private static final String ATTR_START_TIME = "start_time";
-    private static final String ATTR_BEGIN_TIME = "begin_time";
-    private static final String ATTR_END_TIME = "end_time";
-    private static final String ATTR_VOLUME = "volume";
-    private static final String ATTR_BEHAVIOR = "behavior";
-    private static final String ATTR_DIRECTION = "direction";
-    private static final String ATTR_BLENDING = "blending";
-    private static final String ATTR_INVERT = "invert";
-    private static final String ATTR_MASK = "mask";
-    private static final String ATTR_BEFORE_MEDIA_ITEM_ID = "before_media_item";
-    private static final String ATTR_AFTER_MEDIA_ITEM_ID = "after_media_item";
-    private static final String ATTR_COLOR_EFFECT_TYPE = "color_type";
-    private static final String ATTR_COLOR_EFFECT_VALUE = "color_value";
-    private static final String ATTR_START_RECT_LEFT = "start_l";
-    private static final String ATTR_START_RECT_TOP = "start_t";
-    private static final String ATTR_START_RECT_RIGHT = "start_r";
-    private static final String ATTR_START_RECT_BOTTOM = "start_b";
-    private static final String ATTR_END_RECT_LEFT = "end_l";
-    private static final String ATTR_END_RECT_TOP = "end_t";
-    private static final String ATTR_END_RECT_RIGHT = "end_r";
-    private static final String ATTR_END_RECT_BOTTOM = "end_b";
-    private static final String ATTR_LOOP = "loop";
-    private static final String ATTR_MUTED = "muted";
-    private static final String ATTR_DUCK_ENABLED = "ducking_enabled";
-    private static final String ATTR_DUCK_THRESHOLD = "ducking_threshold";
-    private static final String ATTR_DUCKED_TRACK_VOLUME = "ducking_volume";
-    private static final String ATTR_GENERATED_IMAGE_CLIP = "generated_image_clip";
-    private static final String ATTR_IS_IMAGE_CLIP_GENERATED = "is_image_clip_generated";
-    private static final String ATTR_GENERATED_TRANSITION_CLIP = "generated_transition_clip";
-    private static final String ATTR_IS_TRANSITION_GENERATED = "is_transition_generated";
-    private static final String ATTR_OVERLAY_RGB_FILENAME = "overlay_rgb_filename";
-    private static final String ATTR_OVERLAY_FRAME_WIDTH = "overlay_frame_width";
-    private static final String ATTR_OVERLAY_FRAME_HEIGHT = "overlay_frame_height";
-    private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH = "resized_RGBframe_width";
-    private static final String ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT = "resized_RGBframe_height";
-    private static final int ENGINE_ACCESS_MAX_TIMEOUT_MS = 500;
-    /*
-     *  Instance variables
-     */
-    private final Semaphore mLock;
-    private final String mProjectPath;
-    private final List<MediaItem> mMediaItems = new ArrayList<MediaItem>();
-    private final List<AudioTrack> mAudioTracks = new ArrayList<AudioTrack>();
-    private final List<Transition> mTransitions = new ArrayList<Transition>();
-    private long mDurationMs;
-    private int mAspectRatio;
-
-    /*
-     * Private Object for calling native Methods via MediaArtistNativeHelper
-     */
-    private MediaArtistNativeHelper mMANativeHelper;
-    private boolean mPreviewInProgress = false;
-    private final boolean mMallocDebug;
-
-    /**
-     * Constructor
-     *
-     * @param projectPath - The path where the VideoEditor stores all files
-     *        related to the project
-     */
-    public VideoEditorImpl(String projectPath) throws IOException {
-        String s;
-        s = SystemProperties.get("libc.debug.malloc");
-        if (s.equals("1")) {
-            mMallocDebug = true;
-            try {
-                dumpHeap("HeapAtStart");
-            } catch (Exception ex) {
-                Log.e(TAG, "dumpHeap returned error in constructor");
-            }
-        } else {
-            mMallocDebug = false;
-        }
-        mLock = new Semaphore(1, true);
-        mMANativeHelper = new MediaArtistNativeHelper(projectPath, mLock, this);
-        mProjectPath = projectPath;
-        final File projectXml = new File(projectPath, PROJECT_FILENAME);
-        if (projectXml.exists()) {
-            try {
-                load();
-            } catch (Exception ex) {
-                ex.printStackTrace();
-                throw new IOException(ex.toString());
-            }
-        } else {
-            mAspectRatio = MediaProperties.ASPECT_RATIO_16_9;
-            mDurationMs = 0;
-        }
-    }
-
-    /*
-     * @return The MediaArtistNativeHelper object
-     */
-    MediaArtistNativeHelper getNativeContext() {
-        return mMANativeHelper;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void addAudioTrack(AudioTrack audioTrack) {
-        if (audioTrack == null) {
-            throw new IllegalArgumentException("Audio Track is null");
-        }
-
-        if (mAudioTracks.size() == 1) {
-            throw new IllegalArgumentException("No more tracks can be added");
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        /*
-         * Add the audio track to AudioTrack list
-         */
-        mAudioTracks.add(audioTrack);
-
-        /*
-         * Form the audio PCM file path
-         */
-        final String audioTrackPCMFilePath = String.format(mProjectPath + "/"
-                    + "AudioPcm" + audioTrack.getId() + ".pcm");
-
-        /*
-         * Create PCM only if not generated in previous session
-         */
-        if (new File(audioTrackPCMFilePath).exists()) {
-            mMANativeHelper.setAudioflag(false);
-        }
-
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void addMediaItem(MediaItem mediaItem) {
-        /*
-         * Validate Media Item
-         */
-        if (mediaItem == null) {
-            throw new IllegalArgumentException("Media item is null");
-        }
-        /*
-         * Add the Media item to MediaItem list
-         */
-        if (mMediaItems.contains(mediaItem)) {
-            throw new IllegalArgumentException("Media item already exists: " + mediaItem.getId());
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        /*
-         *  Invalidate the end transition if necessary
-         */
-        final int mediaItemsCount = mMediaItems.size();
-        if (mediaItemsCount > 0) {
-            removeTransitionAfter(mediaItemsCount - 1);
-        }
-
-        /*
-         *  Add the new media item
-         */
-        mMediaItems.add(mediaItem);
-
-        computeTimelineDuration();
-
-        /*
-         *  Generate project thumbnail only from first media Item on storyboard
-         */
-        if (mMediaItems.size() == 1) {
-            generateProjectThumbnail();
-        }
-    }
-
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void addTransition(Transition transition) {
-        if (transition == null) {
-            throw new IllegalArgumentException("Null Transition");
-        }
-
-        final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
-        final MediaItem afterMediaItem = transition.getAfterMediaItem();
-        /*
-         * Check if the MediaItems are in sequence
-         */
-        if (mMediaItems == null) {
-            throw new IllegalArgumentException("No media items are added");
-        }
-
-        if ((afterMediaItem != null) &&  (beforeMediaItem != null)) {
-            final int afterMediaItemIndex = mMediaItems.indexOf(afterMediaItem);
-            final int beforeMediaItemIndex = mMediaItems.indexOf(beforeMediaItem);
-
-            if ((afterMediaItemIndex == -1) || (beforeMediaItemIndex == -1)) {
-                throw new IllegalArgumentException
-                    ("Either of the mediaItem is not found in the list");
-            }
-
-            if (afterMediaItemIndex != (beforeMediaItemIndex - 1) ) {
-                throw new IllegalArgumentException("MediaItems are not in sequence");
-            }
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        mTransitions.add(transition);
-        /*
-         *  Cross reference the transitions
-         */
-        if (afterMediaItem != null) {
-            /*
-             *  If a transition already exists at the specified position then
-             *  invalidate it.
-             */
-            if (afterMediaItem.getEndTransition() != null) {
-                afterMediaItem.getEndTransition().invalidate();
-                mTransitions.remove(afterMediaItem.getEndTransition());
-            }
-            afterMediaItem.setEndTransition(transition);
-        }
-
-        if (beforeMediaItem != null) {
-            /*
-             *  If a transition already exists at the specified position then
-             *  invalidate it.
-             */
-            if (beforeMediaItem.getBeginTransition() != null) {
-                beforeMediaItem.getBeginTransition().invalidate();
-                mTransitions.remove(beforeMediaItem.getBeginTransition());
-            }
-            beforeMediaItem.setBeginTransition(transition);
-        }
-
-        computeTimelineDuration();
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void cancelExport(String filename) {
-        if (mMANativeHelper != null && filename != null) {
-            mMANativeHelper.stop(filename);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void export(String filename, int height, int bitrate,
-                       int audioCodec, int videoCodec,
-                       ExportProgressListener listener)
-                       throws IOException {
-        int audcodec = 0;
-        int vidcodec = 0;
-        if (filename == null) {
-            throw new IllegalArgumentException("export: filename is null");
-        }
-
-        final File tempPathFile = new File(filename);
-        if (tempPathFile == null) {
-            throw new IOException(filename + "can not be created");
-        }
-
-        if (mMediaItems.size() == 0) {
-            throw new IllegalStateException("No MediaItems added");
-        }
-
-        switch (height) {
-            case MediaProperties.HEIGHT_144:
-                break;
-            case MediaProperties.HEIGHT_288:
-                break;
-            case MediaProperties.HEIGHT_360:
-                break;
-            case MediaProperties.HEIGHT_480:
-                break;
-            case MediaProperties.HEIGHT_720:
-                break;
-            case MediaProperties.HEIGHT_1080:
-                break;
-
-            default: {
-                String message = "Unsupported height value " + height;
-                throw new IllegalArgumentException(message);
-            }
-        }
-
-        switch (bitrate) {
-            case MediaProperties.BITRATE_28K:
-                break;
-            case MediaProperties.BITRATE_40K:
-                break;
-            case MediaProperties.BITRATE_64K:
-                break;
-            case MediaProperties.BITRATE_96K:
-                break;
-            case MediaProperties.BITRATE_128K:
-                break;
-            case MediaProperties.BITRATE_192K:
-                break;
-            case MediaProperties.BITRATE_256K:
-                break;
-            case MediaProperties.BITRATE_384K:
-                break;
-            case MediaProperties.BITRATE_512K:
-                break;
-            case MediaProperties.BITRATE_800K:
-                break;
-            case MediaProperties.BITRATE_2M:
-                break;
-            case MediaProperties.BITRATE_5M:
-                break;
-            case MediaProperties.BITRATE_8M:
-                break;
-
-            default: {
-                final String message = "Unsupported bitrate value " + bitrate;
-                throw new IllegalArgumentException(message);
-            }
-        }
-        computeTimelineDuration();
-        final long audioBitrate = MediaArtistNativeHelper.Bitrate.BR_96_KBPS;
-        final long fileSize = (mDurationMs * (bitrate + audioBitrate)) / 8000;
-        if (MAX_SUPPORTED_FILE_SIZE <= fileSize) {
-            throw new IllegalStateException("Export Size is more than 2GB");
-        }
-        switch (audioCodec) {
-            case MediaProperties.ACODEC_AAC_LC:
-                audcodec = MediaArtistNativeHelper.AudioFormat.AAC;
-                break;
-            case MediaProperties.ACODEC_AMRNB:
-                audcodec = MediaArtistNativeHelper.AudioFormat.AMR_NB;
-                break;
-
-            default: {
-                String message = "Unsupported audio codec type " + audioCodec;
-                throw new IllegalArgumentException(message);
-            }
-        }
-
-        switch (videoCodec) {
-            case MediaProperties.VCODEC_H263:
-                vidcodec = MediaArtistNativeHelper.VideoFormat.H263;
-                break;
-            case MediaProperties.VCODEC_H264:
-                vidcodec = MediaArtistNativeHelper.VideoFormat.H264;
-                break;
-            case MediaProperties.VCODEC_MPEG4:
-                vidcodec = MediaArtistNativeHelper.VideoFormat.MPEG4;
-                break;
-
-            default: {
-                String message = "Unsupported video codec type " + videoCodec;
-                throw new IllegalArgumentException(message);
-            }
-        }
-
-        boolean semAcquireDone = false;
-        try {
-            lock();
-            semAcquireDone = true;
-
-            if (mMANativeHelper == null) {
-                throw new IllegalStateException("The video editor is not initialized");
-            }
-            mMANativeHelper.setAudioCodec(audcodec);
-            mMANativeHelper.setVideoCodec(vidcodec);
-            mMANativeHelper.export(filename, mProjectPath, height,bitrate,
-                               mMediaItems, mTransitions, mAudioTracks, listener);
-        } catch (InterruptedException  ex) {
-            Log.e(TAG, "Sem acquire NOT successful in export");
-        } finally {
-            if (semAcquireDone) {
-                unlock();
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void export(String filename, int height, int bitrate,
-                       ExportProgressListener listener)
-                       throws IOException {
-        int defaultAudiocodec = MediaArtistNativeHelper.AudioFormat.AAC;
-        int defaultVideocodec = MediaArtistNativeHelper.VideoFormat.H264;
-
-        export(filename, height, bitrate, defaultAudiocodec,
-                defaultVideocodec, listener);
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void generatePreview(MediaProcessingProgressListener listener) {
-        boolean semAcquireDone = false;
-        try {
-            lock();
-            semAcquireDone = true;
-
-            if (mMANativeHelper == null) {
-                throw new IllegalStateException("The video editor is not initialized");
-            }
-
-            if ((mMediaItems.size() > 0) || (mAudioTracks.size() > 0)) {
-                mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions, mAudioTracks,
-                        listener);
-            }
-        } catch (InterruptedException  ex) {
-            Log.e(TAG, "Sem acquire NOT successful in previewStoryBoard");
-        } finally {
-            if (semAcquireDone) {
-                unlock();
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public List<AudioTrack> getAllAudioTracks() {
-        return mAudioTracks;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public List<MediaItem> getAllMediaItems() {
-        return mMediaItems;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public List<Transition> getAllTransitions() {
-        return mTransitions;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public int getAspectRatio() {
-        return mAspectRatio;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public AudioTrack getAudioTrack(String audioTrackId) {
-        for (AudioTrack at : mAudioTracks) {
-            if (at.getId().equals(audioTrackId)) {
-                return at;
-            }
-        }
-        return null;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public long getDuration() {
-        /**
-         *  Since MediaImageItem can change duration we need to compute the
-         *  duration here
-         */
-        computeTimelineDuration();
-        return mDurationMs;
-    }
-
-    /*
-     * Force updates the timeline duration
-     */
-    void updateTimelineDuration() {
-        computeTimelineDuration();
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized MediaItem getMediaItem(String mediaItemId) {
-        for (MediaItem mediaItem : mMediaItems) {
-            if (mediaItem.getId().equals(mediaItemId)) {
-                return mediaItem;
-            }
-        }
-        return null;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public String getPath() {
-        return mProjectPath;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public Transition getTransition(String transitionId) {
-        for (Transition transition : mTransitions) {
-            if (transition.getId().equals(transitionId)) {
-                return transition;
-            }
-        }
-        return null;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void insertAudioTrack(AudioTrack audioTrack,
-                                              String afterAudioTrackId) {
-        if (mAudioTracks.size() == 1) {
-            throw new IllegalArgumentException("No more tracks can be added");
-        }
-
-        if (afterAudioTrackId == null) {
-            mMANativeHelper.setGeneratePreview(true);
-            mAudioTracks.add(0, audioTrack);
-        } else {
-            final int audioTrackCount = mAudioTracks.size();
-            for (int i = 0; i < audioTrackCount; i++) {
-                AudioTrack at = mAudioTracks.get(i);
-                if (at.getId().equals(afterAudioTrackId)) {
-                    mMANativeHelper.setGeneratePreview(true);
-                    mAudioTracks.add(i + 1, audioTrack);
-                    return;
-                }
-            }
-
-            throw new IllegalArgumentException("AudioTrack not found: " + afterAudioTrackId);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void insertMediaItem(MediaItem mediaItem, String afterMediaItemId) {
-        if (mMediaItems.contains(mediaItem)) {
-            throw new IllegalArgumentException("Media item already exists: " + mediaItem.getId());
-        }
-
-        if (afterMediaItemId == null) {
-            mMANativeHelper.setGeneratePreview(true);
-            if (mMediaItems.size() > 0) {
-                /**
-                 *  Invalidate the transition at the beginning of the timeline
-                 */
-                removeTransitionBefore(0);
-            }
-
-            mMediaItems.add(0, mediaItem);
-            computeTimelineDuration();
-            generateProjectThumbnail();
-        } else {
-            final int mediaItemCount = mMediaItems.size();
-            for (int i = 0; i < mediaItemCount; i++) {
-                final MediaItem mi = mMediaItems.get(i);
-                if (mi.getId().equals(afterMediaItemId)) {
-                    mMANativeHelper.setGeneratePreview(true);
-                    /**
-                     *  Invalidate the transition at this position
-                     */
-                    removeTransitionAfter(i);
-                    /**
-                     *  Insert the new media item
-                     */
-                    mMediaItems.add(i + 1, mediaItem);
-                    computeTimelineDuration();
-                    return;
-                }
-            }
-
-            throw new IllegalArgumentException("MediaItem not found: " + afterMediaItemId);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void moveAudioTrack(String audioTrackId, String afterAudioTrackId) {
-        throw new IllegalStateException("Not supported");
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void moveMediaItem(String mediaItemId, String afterMediaItemId) {
-        final MediaItem moveMediaItem = removeMediaItem(mediaItemId,true);
-        if (moveMediaItem == null) {
-            throw new IllegalArgumentException("Target MediaItem not found: " + mediaItemId);
-        }
-
-        if (afterMediaItemId == null) {
-            if (mMediaItems.size() > 0) {
-                mMANativeHelper.setGeneratePreview(true);
-
-                /**
-                 *  Invalidate adjacent transitions at the insertion point
-                 */
-                removeTransitionBefore(0);
-
-                /**
-                 *  Insert the media item at the new position
-                 */
-                mMediaItems.add(0, moveMediaItem);
-                computeTimelineDuration();
-
-                generateProjectThumbnail();
-            } else {
-                throw new IllegalStateException("Cannot move media item (it is the only item)");
-            }
-        } else {
-            final int mediaItemCount = mMediaItems.size();
-            for (int i = 0; i < mediaItemCount; i++) {
-                final MediaItem mi = mMediaItems.get(i);
-                if (mi.getId().equals(afterMediaItemId)) {
-                    mMANativeHelper.setGeneratePreview(true);
-                    /**
-                     *  Invalidate adjacent transitions at the insertion point
-                     */
-                    removeTransitionAfter(i);
-                    /**
-                     *  Insert the media item at the new position
-                     */
-                    mMediaItems.add(i + 1, moveMediaItem);
-                    computeTimelineDuration();
-                    return;
-                }
-            }
-
-            throw new IllegalArgumentException("MediaItem not found: " + afterMediaItemId);
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void release() {
-        stopPreview();
-
-        boolean semAcquireDone = false;
-        try {
-            lock();
-            semAcquireDone = true;
-
-            if (mMANativeHelper != null) {
-                mMediaItems.clear();
-                mAudioTracks.clear();
-                mTransitions.clear();
-                mMANativeHelper.releaseNativeHelper();
-                mMANativeHelper = null;
-            }
-        } catch (Exception  ex) {
-            Log.e(TAG, "Sem acquire NOT successful in export", ex);
-        } finally {
-            if (semAcquireDone) {
-                unlock();
-            }
-        }
-        if (mMallocDebug) {
-            try {
-                dumpHeap("HeapAtEnd");
-            } catch (Exception ex) {
-                Log.e(TAG, "dumpHeap returned error in release");
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized void removeAllMediaItems() {
-        mMANativeHelper.setGeneratePreview(true);
-
-        mMediaItems.clear();
-
-        /**
-         *  Invalidate all transitions
-         */
-        for (Transition transition : mTransitions) {
-            transition.invalidate();
-        }
-        mTransitions.clear();
-
-        mDurationMs = 0;
-        /**
-         * If a thumbnail already exists, then delete it
-         */
-        if ((new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).exists()) {
-            (new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).delete();
-        }
-
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized AudioTrack removeAudioTrack(String audioTrackId) {
-        final AudioTrack audioTrack = getAudioTrack(audioTrackId);
-        if (audioTrack != null) {
-            mMANativeHelper.setGeneratePreview(true);
-            mAudioTracks.remove(audioTrack);
-            audioTrack.invalidate();
-            mMANativeHelper.invalidatePcmFile();
-            mMANativeHelper.setAudioflag(true);
-        } else {
-            throw new IllegalArgumentException(" No more audio tracks");
-        }
-        return audioTrack;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized MediaItem removeMediaItem(String mediaItemId) {
-        final String firstItemString = mMediaItems.get(0).getId();
-        final MediaItem mediaItem = getMediaItem(mediaItemId);
-        if (mediaItem != null) {
-            mMANativeHelper.setGeneratePreview(true);
-            /**
-             *  Remove the media item
-             */
-            mMediaItems.remove(mediaItem);
-            if (mediaItem instanceof MediaImageItem) {
-                ((MediaImageItem)mediaItem).invalidate();
-            }
-            final List<Overlay> overlays = mediaItem.getAllOverlays();
-            if (overlays.size() > 0) {
-                for (Overlay overlay : overlays) {
-                    if (overlay instanceof OverlayFrame) {
-                        final OverlayFrame overlayFrame = (OverlayFrame)overlay;
-                        overlayFrame.invalidate();
-                    }
-                }
-            }
-
-            /**
-             *  Remove the adjacent transitions
-             */
-            removeAdjacentTransitions(mediaItem);
-            computeTimelineDuration();
-        }
-
-        /**
-         * If string equals first mediaItem, then
-         * generate Project thumbnail
-         */
-        if (firstItemString.equals(mediaItemId)) {
-            generateProjectThumbnail();
-        }
-
-        if (mediaItem instanceof MediaVideoItem) {
-            /**
-             * Delete the graph file
-             */
-            ((MediaVideoItem)mediaItem).invalidate();
-        }
-        return mediaItem;
-    }
-
-    private synchronized MediaItem removeMediaItem(String mediaItemId, boolean flag) {
-        final String firstItemString = mMediaItems.get(0).getId();
-
-        final MediaItem mediaItem = getMediaItem(mediaItemId);
-        if (mediaItem != null) {
-            mMANativeHelper.setGeneratePreview(true);
-            /**
-             *  Remove the media item
-             */
-            mMediaItems.remove(mediaItem);
-            /**
-             *  Remove the adjacent transitions
-             */
-            removeAdjacentTransitions(mediaItem);
-            computeTimelineDuration();
-        }
-
-        /**
-         * If string equals first mediaItem, then
-         * generate Project thumbail
-         */
-        if (firstItemString.equals(mediaItemId)) {
-            generateProjectThumbnail();
-        }
-        return mediaItem;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public synchronized Transition removeTransition(String transitionId) {
-        final Transition transition = getTransition(transitionId);
-        if (transition == null) {
-            throw new IllegalStateException("Transition not found: " + transitionId);
-        }
-
-        mMANativeHelper.setGeneratePreview(true);
-
-        /**
-         *  Remove the transition references
-         */
-        final MediaItem afterMediaItem = transition.getAfterMediaItem();
-        if (afterMediaItem != null) {
-            afterMediaItem.setEndTransition(null);
-        }
-
-        final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
-        if (beforeMediaItem != null) {
-            beforeMediaItem.setBeginTransition(null);
-        }
-
-        mTransitions.remove(transition);
-        transition.invalidate();
-        computeTimelineDuration();
-        return transition;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public long renderPreviewFrame(SurfaceHolder surfaceHolder, long timeMs,
-                                    OverlayData overlayData) {
-        if (surfaceHolder == null) {
-            throw new IllegalArgumentException("Surface Holder is null");
-        }
-
-        final Surface surface = surfaceHolder.getSurface();
-        if (surface == null) {
-            throw new IllegalArgumentException("Surface could not be retrieved from Surface holder");
-        }
-
-        if (surface.isValid() == false) {
-            throw new IllegalStateException("Surface is not valid");
-        }
-
-        if (timeMs < 0) {
-            throw new IllegalArgumentException("requested time not correct");
-        } else if (timeMs > mDurationMs) {
-            throw new IllegalArgumentException("requested time more than duration");
-        }
-        long result = 0;
-
-        boolean semAcquireDone = false;
-        try {
-            semAcquireDone = lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
-            if (semAcquireDone == false) {
-                throw new IllegalStateException("Timeout waiting for semaphore");
-            }
-
-            if (mMANativeHelper == null) {
-                throw new IllegalStateException("The video editor is not initialized");
-            }
-
-            if (mMediaItems.size() > 0) {
-                final Rect frame = surfaceHolder.getSurfaceFrame();
-                result = mMANativeHelper.renderPreviewFrame(surface,
-                        timeMs, frame.width(), frame.height(), overlayData);
-            } else {
-                result = 0;
-            }
-        } catch (InterruptedException ex) {
-            Log.w(TAG, "The thread was interrupted", new Throwable());
-            throw new IllegalStateException("The thread was interrupted");
-        } finally {
-            if (semAcquireDone) {
-                unlock();
-            }
-        }
-        return result;
-    }
-
-    /**
-     *  the project form XML
-     */
-    private void load() throws FileNotFoundException, XmlPullParserException, IOException {
-        final File file = new File(mProjectPath, PROJECT_FILENAME);
-        /**
-         *  Load the metadata
-         */
-        final FileInputStream fis = new FileInputStream(file);
-        try {
-            final List<String> ignoredMediaItems = new ArrayList<String>();
-
-            final XmlPullParser parser = Xml.newPullParser();
-            parser.setInput(fis, "UTF-8");
-            int eventType = parser.getEventType();
-            String name;
-            MediaItem currentMediaItem = null;
-            Overlay currentOverlay = null;
-            boolean regenerateProjectThumbnail = false;
-            while (eventType != XmlPullParser.END_DOCUMENT) {
-                switch (eventType) {
-                    case XmlPullParser.START_TAG: {
-                        name = parser.getName();
-                        if (TAG_PROJECT.equals(name)) {
-                            mAspectRatio = Integer.parseInt(parser.getAttributeValue("",
-                                   ATTR_ASPECT_RATIO));
-
-                            final boolean mRegenPCM =
-                                Boolean.parseBoolean(parser.getAttributeValue("",
-                                    ATTR_REGENERATE_PCM));
-                            mMANativeHelper.setAudioflag(mRegenPCM);
-                        } else if (TAG_MEDIA_ITEM.equals(name)) {
-                            final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
-                            try {
-                                currentMediaItem = parseMediaItem(parser);
-                                mMediaItems.add(currentMediaItem);
-                            } catch (Exception ex) {
-                                Log.w(TAG, "Cannot load media item: " + mediaItemId, ex);
-                                currentMediaItem = null;
-
-                                // First media item is invalid, mark for project thumbnail removal
-                                if (mMediaItems.size() == 0) {
-                                    regenerateProjectThumbnail = true;
-                                }
-                                // Ignore the media item
-                                ignoredMediaItems.add(mediaItemId);
-                            }
-                        } else if (TAG_TRANSITION.equals(name)) {
-                            try {
-                                final Transition transition = parseTransition(parser,
-                                        ignoredMediaItems);
-                                // The transition will be null if the bounding
-                                // media items are ignored
-                                if (transition != null) {
-                                    mTransitions.add(transition);
-                                }
-                            } catch (Exception ex) {
-                                Log.w(TAG, "Cannot load transition", ex);
-                            }
-                        } else if (TAG_OVERLAY.equals(name)) {
-                            if (currentMediaItem != null) {
-                                try {
-                                    currentOverlay = parseOverlay(parser, currentMediaItem);
-                                    currentMediaItem.addOverlay(currentOverlay);
-                                } catch (Exception ex) {
-                                    Log.w(TAG, "Cannot load overlay", ex);
-                                }
-                            }
-                        } else if (TAG_OVERLAY_USER_ATTRIBUTES.equals(name)) {
-                            if (currentOverlay != null) {
-                                final int attributesCount = parser.getAttributeCount();
-                                for (int i = 0; i < attributesCount; i++) {
-                                    currentOverlay.setUserAttribute(parser.getAttributeName(i),
-                                            parser.getAttributeValue(i));
-                                }
-                            }
-                        } else if (TAG_EFFECT.equals(name)) {
-                            if (currentMediaItem != null) {
-                                try {
-                                    final Effect effect = parseEffect(parser, currentMediaItem);
-                                    currentMediaItem.addEffect(effect);
-
-                                    if (effect instanceof EffectKenBurns) {
-                                        final boolean isImageClipGenerated =
-                                               Boolean.parseBoolean(parser.getAttributeValue("",
-                                                                  ATTR_IS_IMAGE_CLIP_GENERATED));
-                                        if(isImageClipGenerated) {
-                                            final String filename = parser.getAttributeValue("",
-                                                                  ATTR_GENERATED_IMAGE_CLIP);
-                                            if (new File(filename).exists() == true) {
-                                                ((MediaImageItem)currentMediaItem).
-                                                            setGeneratedImageClip(filename);
-                                                ((MediaImageItem)currentMediaItem).
-                                                             setRegenerateClip(false);
-                                             } else {
-                                               ((MediaImageItem)currentMediaItem).
-                                                             setGeneratedImageClip(null);
-                                               ((MediaImageItem)currentMediaItem).
-                                                             setRegenerateClip(true);
-                                             }
-                                        } else {
-                                            ((MediaImageItem)currentMediaItem).
-                                                             setGeneratedImageClip(null);
-                                            ((MediaImageItem)currentMediaItem).
-                                                            setRegenerateClip(true);
-                                        }
-                                    }
-                                } catch (Exception ex) {
-                                    Log.w(TAG, "Cannot load effect", ex);
-                                }
-                            }
-                        } else if (TAG_AUDIO_TRACK.equals(name)) {
-                            try {
-                                final AudioTrack audioTrack = parseAudioTrack(parser);
-                                addAudioTrack(audioTrack);
-                            } catch (Exception ex) {
-                                Log.w(TAG, "Cannot load audio track", ex);
-                            }
-                        }
-                        break;
-                    }
-
-                    case XmlPullParser.END_TAG: {
-                        name = parser.getName();
-                        if (TAG_MEDIA_ITEM.equals(name)) {
-                            currentMediaItem = null;
-                        } else if (TAG_OVERLAY.equals(name)) {
-                            currentOverlay = null;
-                        }
-                        break;
-                    }
-
-                    default: {
-                        break;
-                    }
-                }
-                eventType = parser.next();
-            }
-            computeTimelineDuration();
-            // Regenerate project thumbnail
-            if (regenerateProjectThumbnail) {
-                generateProjectThumbnail();
-                regenerateProjectThumbnail = false;
-            }
-        } finally {
-            if (fis != null) {
-                fis.close();
-            }
-        }
-    }
-
-    /**
-     * Parse the media item
-     *
-     * @param parser The parser
-     * @return The media item
-     */
-    private MediaItem parseMediaItem(XmlPullParser parser) throws IOException {
-        final String mediaItemId = parser.getAttributeValue("", ATTR_ID);
-        final String type = parser.getAttributeValue("", ATTR_TYPE);
-        final String filename = parser.getAttributeValue("", ATTR_FILENAME);
-        final int renderingMode = Integer.parseInt(parser.getAttributeValue("",
-                ATTR_RENDERING_MODE));
-
-        final MediaItem currentMediaItem;
-        if (MediaImageItem.class.getSimpleName().equals(type)) {
-            final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
-            currentMediaItem = new MediaImageItem(this, mediaItemId, filename,
-                    durationMs, renderingMode);
-        } else if (MediaVideoItem.class.getSimpleName().equals(type)) {
-            final long beginMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-            final long endMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
-            final int volume = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
-            final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_MUTED));
-            final String audioWaveformFilename = parser.getAttributeValue("",
-                    ATTR_AUDIO_WAVEFORM_FILENAME);
-            currentMediaItem = new MediaVideoItem(this, mediaItemId, filename,
-                    renderingMode, beginMs, endMs, volume, muted, audioWaveformFilename);
-
-            final long beginTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-            final long endTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
-            ((MediaVideoItem)currentMediaItem).setExtractBoundaries(beginTimeMs, endTimeMs);
-
-            final int volumePercent = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
-            ((MediaVideoItem)currentMediaItem).setVolume(volumePercent);
-        } else {
-            throw new IllegalArgumentException("Unknown media item type: " + type);
-        }
-
-        return currentMediaItem;
-    }
-
-    /**
-     * Parse the transition
-     *
-     * @param parser The parser
-     * @param ignoredMediaItems The list of ignored media items
-     *
-     * @return The transition
-     */
-    private Transition parseTransition(XmlPullParser parser, List<String> ignoredMediaItems) {
-        final String transitionId = parser.getAttributeValue("", ATTR_ID);
-        final String type = parser.getAttributeValue("", ATTR_TYPE);
-        final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
-        final int behavior = Integer.parseInt(parser.getAttributeValue("", ATTR_BEHAVIOR));
-
-        final String beforeMediaItemId = parser.getAttributeValue("", ATTR_BEFORE_MEDIA_ITEM_ID);
-        final MediaItem beforeMediaItem;
-        if (beforeMediaItemId != null) {
-            if (ignoredMediaItems.contains(beforeMediaItemId)) {
-                // This transition is ignored
-                return null;
-            }
-
-            beforeMediaItem = getMediaItem(beforeMediaItemId);
-        } else {
-            beforeMediaItem = null;
-        }
-
-        final String afterMediaItemId = parser.getAttributeValue("", ATTR_AFTER_MEDIA_ITEM_ID);
-        final MediaItem afterMediaItem;
-        if (afterMediaItemId != null) {
-            if (ignoredMediaItems.contains(afterMediaItemId)) {
-                // This transition is ignored
-                return null;
-            }
-
-            afterMediaItem = getMediaItem(afterMediaItemId);
-        } else {
-            afterMediaItem = null;
-        }
-
-        final Transition transition;
-        if (TransitionAlpha.class.getSimpleName().equals(type)) {
-            final int blending = Integer.parseInt(parser.getAttributeValue("", ATTR_BLENDING));
-            final String maskFilename = parser.getAttributeValue("", ATTR_MASK);
-            final boolean invert = Boolean.getBoolean(parser.getAttributeValue("", ATTR_INVERT));
-            transition = new TransitionAlpha(transitionId, afterMediaItem, beforeMediaItem,
-                    durationMs, behavior, maskFilename, blending, invert);
-        } else if (TransitionCrossfade.class.getSimpleName().equals(type)) {
-            transition = new TransitionCrossfade(transitionId, afterMediaItem, beforeMediaItem,
-                    durationMs, behavior);
-        } else if (TransitionSliding.class.getSimpleName().equals(type)) {
-            final int direction = Integer.parseInt(parser.getAttributeValue("", ATTR_DIRECTION));
-            transition = new TransitionSliding(transitionId, afterMediaItem, beforeMediaItem,
-                    durationMs, behavior, direction);
-        } else if (TransitionFadeBlack.class.getSimpleName().equals(type)) {
-            transition = new TransitionFadeBlack(transitionId, afterMediaItem, beforeMediaItem,
-                    durationMs, behavior);
-        } else {
-            throw new IllegalArgumentException("Invalid transition type: " + type);
-        }
-
-        final boolean isTransitionGenerated = Boolean.parseBoolean(parser.getAttributeValue("",
-                                                 ATTR_IS_TRANSITION_GENERATED));
-        if (isTransitionGenerated == true) {
-            final String transitionFile = parser.getAttributeValue("",
-                                                ATTR_GENERATED_TRANSITION_CLIP);
-
-            if (new File(transitionFile).exists()) {
-                transition.setFilename(transitionFile);
-            } else {
-                transition.setFilename(null);
-            }
-        }
-
-        // Use the transition
-        if (beforeMediaItem != null) {
-            beforeMediaItem.setBeginTransition(transition);
-        }
-
-        if (afterMediaItem != null) {
-            afterMediaItem.setEndTransition(transition);
-        }
-
-        return transition;
-    }
-
-    /**
-     * Parse the overlay
-     *
-     * @param parser The parser
-     * @param mediaItem The media item owner
-     *
-     * @return The overlay
-     */
-    private Overlay parseOverlay(XmlPullParser parser, MediaItem mediaItem) {
-        final String overlayId = parser.getAttributeValue("", ATTR_ID);
-        final String type = parser.getAttributeValue("", ATTR_TYPE);
-        final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
-        final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-
-        final Overlay overlay;
-        if (OverlayFrame.class.getSimpleName().equals(type)) {
-            final String filename = parser.getAttributeValue("", ATTR_FILENAME);
-            overlay = new OverlayFrame(mediaItem, overlayId, filename, startTimeMs, durationMs);
-        } else {
-            throw new IllegalArgumentException("Invalid overlay type: " + type);
-        }
-
-        final String overlayRgbFileName = parser.getAttributeValue("", ATTR_OVERLAY_RGB_FILENAME);
-        if (overlayRgbFileName != null) {
-            ((OverlayFrame)overlay).setFilename(overlayRgbFileName);
-
-            final int overlayFrameWidth = Integer.parseInt(parser.getAttributeValue("",
-                                   ATTR_OVERLAY_FRAME_WIDTH));
-            final int overlayFrameHeight = Integer.parseInt(parser.getAttributeValue("",
-                                   ATTR_OVERLAY_FRAME_HEIGHT));
-
-            ((OverlayFrame)overlay).setOverlayFrameWidth(overlayFrameWidth);
-            ((OverlayFrame)overlay).setOverlayFrameHeight(overlayFrameHeight);
-
-            final int resizedRGBFrameWidth = Integer.parseInt(parser.getAttributeValue("",
-                                   ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH));
-            final int resizedRGBFrameHeight = Integer.parseInt(parser.getAttributeValue("",
-                                   ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT));
-
-            ((OverlayFrame)overlay).setResizedRGBSize(resizedRGBFrameWidth, resizedRGBFrameHeight);
-        }
-
-        return overlay;
-    }
-
-    /**
-     * Parse the effect
-     *
-     * @param parser The parser
-     * @param mediaItem The media item owner
-     *
-     * @return The effect
-     */
-    private Effect parseEffect(XmlPullParser parser, MediaItem mediaItem) {
-        final String effectId = parser.getAttributeValue("", ATTR_ID);
-        final String type = parser.getAttributeValue("", ATTR_TYPE);
-        final long durationMs = Long.parseLong(parser.getAttributeValue("", ATTR_DURATION));
-        final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-
-        final Effect effect;
-        if (EffectColor.class.getSimpleName().equals(type)) {
-            final int colorEffectType = Integer.parseInt(parser.getAttributeValue("",
-                                                       ATTR_COLOR_EFFECT_TYPE));
-            final int color;
-            if (colorEffectType == EffectColor.TYPE_COLOR
-                    || colorEffectType == EffectColor.TYPE_GRADIENT) {
-                color = Integer.parseInt(parser.getAttributeValue("", ATTR_COLOR_EFFECT_VALUE));
-            } else {
-                color = 0;
-            }
-            effect = new EffectColor(mediaItem, effectId, startTimeMs,
-                    durationMs, colorEffectType, color);
-        } else if (EffectKenBurns.class.getSimpleName().equals(type)) {
-            final Rect startRect = new Rect(
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_LEFT)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_TOP)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_RIGHT)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_START_RECT_BOTTOM)));
-            final Rect endRect = new Rect(
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_LEFT)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_TOP)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_RIGHT)),
-                    Integer.parseInt(parser.getAttributeValue("", ATTR_END_RECT_BOTTOM)));
-            effect = new EffectKenBurns(mediaItem, effectId, startRect, endRect,
-                                        startTimeMs, durationMs);
-        } else {
-            throw new IllegalArgumentException("Invalid effect type: " + type);
-        }
-
-        return effect;
-    }
-
-    /**
-     * Parse the audio track
-     *
-     * @param parser The parser
-     *
-     * @return The audio track
-     */
-    private AudioTrack parseAudioTrack(XmlPullParser parser) throws IOException {
-        final String audioTrackId = parser.getAttributeValue("", ATTR_ID);
-        final String filename = parser.getAttributeValue("", ATTR_FILENAME);
-        final long startTimeMs = Long.parseLong(parser.getAttributeValue("", ATTR_START_TIME));
-        final long beginMs = Long.parseLong(parser.getAttributeValue("", ATTR_BEGIN_TIME));
-        final long endMs = Long.parseLong(parser.getAttributeValue("", ATTR_END_TIME));
-        final int volume = Integer.parseInt(parser.getAttributeValue("", ATTR_VOLUME));
-        final boolean muted = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_MUTED));
-        final boolean loop = Boolean.parseBoolean(parser.getAttributeValue("", ATTR_LOOP));
-        final boolean duckingEnabled = Boolean.parseBoolean(
-                parser.getAttributeValue("", ATTR_DUCK_ENABLED));
-        final int duckThreshold = Integer.parseInt(
-                parser.getAttributeValue("", ATTR_DUCK_THRESHOLD));
-        final int duckedTrackVolume = Integer.parseInt(parser.getAttributeValue("",
-                                                     ATTR_DUCKED_TRACK_VOLUME));
-
-        final String waveformFilename = parser.getAttributeValue("", ATTR_AUDIO_WAVEFORM_FILENAME);
-        final AudioTrack audioTrack = new AudioTrack(this, audioTrackId,
-                                                     filename, startTimeMs,
-                                                     beginMs, endMs, loop,
-                                                     volume, muted,
-                                                     duckingEnabled,
-                                                     duckThreshold,
-                                                     duckedTrackVolume,
-                                                     waveformFilename);
-
-        return audioTrack;
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void save() throws IOException {
-        final XmlSerializer serializer = Xml.newSerializer();
-        final StringWriter writer = new StringWriter();
-        serializer.setOutput(writer);
-        serializer.startDocument("UTF-8", true);
-        serializer.startTag("", TAG_PROJECT);
-        serializer.attribute("",
-                             ATTR_ASPECT_RATIO, Integer.toString(mAspectRatio));
-
-        serializer.attribute("", ATTR_REGENERATE_PCM,
-                        Boolean.toString(mMANativeHelper.getAudioflag()));
-
-        serializer.startTag("", TAG_MEDIA_ITEMS);
-        for (MediaItem mediaItem : mMediaItems) {
-            serializer.startTag("", TAG_MEDIA_ITEM);
-            serializer.attribute("", ATTR_ID, mediaItem.getId());
-            serializer.attribute("", ATTR_TYPE,
-                                          mediaItem.getClass().getSimpleName());
-            serializer.attribute("", ATTR_FILENAME, mediaItem.getFilename());
-            serializer.attribute("", ATTR_RENDERING_MODE, Integer.toString(
-                    mediaItem.getRenderingMode()));
-            if (mediaItem instanceof MediaVideoItem) {
-                final MediaVideoItem mvi = (MediaVideoItem)mediaItem;
-                serializer
-                .attribute("", ATTR_BEGIN_TIME,
-                                     Long.toString(mvi.getBoundaryBeginTime()));
-                serializer.attribute("", ATTR_END_TIME,
-                                       Long.toString(mvi.getBoundaryEndTime()));
-                serializer.attribute("", ATTR_VOLUME,
-                                             Integer.toString(mvi.getVolume()));
-                serializer.attribute("", ATTR_MUTED,
-                                               Boolean.toString(mvi.isMuted()));
-                if (mvi.getAudioWaveformFilename() != null) {
-                    serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
-                            mvi.getAudioWaveformFilename());
-                }
-            } else if (mediaItem instanceof MediaImageItem) {
-                serializer.attribute("", ATTR_DURATION,
-                        Long.toString(mediaItem.getTimelineDuration()));
-            }
-
-            final List<Overlay> overlays = mediaItem.getAllOverlays();
-            if (overlays.size() > 0) {
-                serializer.startTag("", TAG_OVERLAYS);
-                for (Overlay overlay : overlays) {
-                    serializer.startTag("", TAG_OVERLAY);
-                    serializer.attribute("", ATTR_ID, overlay.getId());
-                    serializer.attribute("",
-                                 ATTR_TYPE, overlay.getClass().getSimpleName());
-                    serializer.attribute("", ATTR_BEGIN_TIME,
-                                         Long.toString(overlay.getStartTime()));
-                    serializer.attribute("", ATTR_DURATION,
-                                          Long.toString(overlay.getDuration()));
-                    if (overlay instanceof OverlayFrame) {
-                        final OverlayFrame overlayFrame = (OverlayFrame)overlay;
-                        overlayFrame.save(getPath());
-                        if (overlayFrame.getBitmapImageFileName() != null) {
-                            serializer.attribute("", ATTR_FILENAME,
-                                         overlayFrame.getBitmapImageFileName());
-                        }
-
-                        if (overlayFrame.getFilename() != null) {
-                            serializer.attribute("",
-                                                 ATTR_OVERLAY_RGB_FILENAME,
-                                                 overlayFrame.getFilename());
-                            serializer.attribute("", ATTR_OVERLAY_FRAME_WIDTH,
-                                                 Integer.toString(overlayFrame.getOverlayFrameWidth()));
-                            serializer.attribute("", ATTR_OVERLAY_FRAME_HEIGHT,
-                                                 Integer.toString(overlayFrame.getOverlayFrameHeight()));
-                            serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_WIDTH,
-                                                 Integer.toString(overlayFrame.getResizedRGBSizeWidth()));
-                            serializer.attribute("", ATTR_OVERLAY_RESIZED_RGB_FRAME_HEIGHT,
-                                                 Integer.toString(overlayFrame.getResizedRGBSizeHeight()));
-
-                        }
-
-                    }
-
-                    /**
-                     *  Save the user attributes
-                     */
-                    serializer.startTag("", TAG_OVERLAY_USER_ATTRIBUTES);
-                    final Map<String, String> userAttributes = overlay.getUserAttributes();
-                    for (String name : userAttributes.keySet()) {
-                        final String value = userAttributes.get(name);
-                        if (value != null) {
-                            serializer.attribute("", name, value);
-                        }
-                    }
-                    serializer.endTag("", TAG_OVERLAY_USER_ATTRIBUTES);
-
-                    serializer.endTag("", TAG_OVERLAY);
-                }
-                serializer.endTag("", TAG_OVERLAYS);
-            }
-
-            final List<Effect> effects = mediaItem.getAllEffects();
-            if (effects.size() > 0) {
-                serializer.startTag("", TAG_EFFECTS);
-                for (Effect effect : effects) {
-                    serializer.startTag("", TAG_EFFECT);
-                    serializer.attribute("", ATTR_ID, effect.getId());
-                    serializer.attribute("",
-                                  ATTR_TYPE, effect.getClass().getSimpleName());
-                    serializer.attribute("", ATTR_BEGIN_TIME,
-                            Long.toString(effect.getStartTime()));
-                    serializer.attribute("", ATTR_DURATION,
-                                           Long.toString(effect.getDuration()));
-                    if (effect instanceof EffectColor) {
-                        final EffectColor colorEffect = (EffectColor)effect;
-                        serializer.attribute("", ATTR_COLOR_EFFECT_TYPE,
-                                Integer.toString(colorEffect.getType()));
-                        if (colorEffect.getType() == EffectColor.TYPE_COLOR ||
-                                colorEffect.getType() == EffectColor.TYPE_GRADIENT) {
-                            serializer.attribute("", ATTR_COLOR_EFFECT_VALUE,
-                                    Integer.toString(colorEffect.getColor()));
-                        }
-                    } else if (effect instanceof EffectKenBurns) {
-                        final Rect startRect = ((EffectKenBurns)effect).getStartRect();
-                        serializer.attribute("", ATTR_START_RECT_LEFT,
-                                Integer.toString(startRect.left));
-                        serializer.attribute("", ATTR_START_RECT_TOP,
-                                Integer.toString(startRect.top));
-                        serializer.attribute("", ATTR_START_RECT_RIGHT,
-                                Integer.toString(startRect.right));
-                        serializer.attribute("", ATTR_START_RECT_BOTTOM,
-                                Integer.toString(startRect.bottom));
-
-                        final Rect endRect = ((EffectKenBurns)effect).getEndRect();
-                        serializer.attribute("", ATTR_END_RECT_LEFT,
-                                                Integer.toString(endRect.left));
-                        serializer.attribute("", ATTR_END_RECT_TOP,
-                                                 Integer.toString(endRect.top));
-                        serializer.attribute("", ATTR_END_RECT_RIGHT,
-                                               Integer.toString(endRect.right));
-                        serializer.attribute("", ATTR_END_RECT_BOTTOM,
-                                Integer.toString(endRect.bottom));
-                        final MediaItem mItem = effect.getMediaItem();
-                           if(((MediaImageItem)mItem).getGeneratedImageClip() != null) {
-                               serializer.attribute("", ATTR_IS_IMAGE_CLIP_GENERATED,
-                                       Boolean.toString(true));
-                               serializer.attribute("", ATTR_GENERATED_IMAGE_CLIP,
-                                     ((MediaImageItem)mItem).getGeneratedImageClip());
-                            } else {
-                                serializer.attribute("", ATTR_IS_IMAGE_CLIP_GENERATED,
-                                     Boolean.toString(false));
-                         }
-                    }
-
-                    serializer.endTag("", TAG_EFFECT);
-                }
-                serializer.endTag("", TAG_EFFECTS);
-            }
-
-            serializer.endTag("", TAG_MEDIA_ITEM);
-        }
-        serializer.endTag("", TAG_MEDIA_ITEMS);
-
-        serializer.startTag("", TAG_TRANSITIONS);
-
-        for (Transition transition : mTransitions) {
-            serializer.startTag("", TAG_TRANSITION);
-            serializer.attribute("", ATTR_ID, transition.getId());
-            serializer.attribute("", ATTR_TYPE, transition.getClass().getSimpleName());
-            serializer.attribute("", ATTR_DURATION, Long.toString(transition.getDuration()));
-            serializer.attribute("", ATTR_BEHAVIOR, Integer.toString(transition.getBehavior()));
-            serializer.attribute("", ATTR_IS_TRANSITION_GENERATED,
-                                    Boolean.toString(transition.isGenerated()));
-            if (transition.isGenerated() == true) {
-                serializer.attribute("", ATTR_GENERATED_TRANSITION_CLIP, transition.mFilename);
-            }
-            final MediaItem afterMediaItem = transition.getAfterMediaItem();
-            if (afterMediaItem != null) {
-                serializer.attribute("", ATTR_AFTER_MEDIA_ITEM_ID, afterMediaItem.getId());
-            }
-
-            final MediaItem beforeMediaItem = transition.getBeforeMediaItem();
-            if (beforeMediaItem != null) {
-                serializer.attribute("", ATTR_BEFORE_MEDIA_ITEM_ID, beforeMediaItem.getId());
-            }
-
-            if (transition instanceof TransitionSliding) {
-                serializer.attribute("", ATTR_DIRECTION,
-                        Integer.toString(((TransitionSliding)transition).getDirection()));
-            } else if (transition instanceof TransitionAlpha) {
-                TransitionAlpha ta = (TransitionAlpha)transition;
-                serializer.attribute("", ATTR_BLENDING,
-                                     Integer.toString(ta.getBlendingPercent()));
-                serializer.attribute("", ATTR_INVERT,
-                                               Boolean.toString(ta.isInvert()));
-                if (ta.getMaskFilename() != null) {
-                    serializer.attribute("", ATTR_MASK, ta.getMaskFilename());
-                }
-            }
-            serializer.endTag("", TAG_TRANSITION);
-        }
-        serializer.endTag("", TAG_TRANSITIONS);
-        serializer.startTag("", TAG_AUDIO_TRACKS);
-        for (AudioTrack at : mAudioTracks) {
-            serializer.startTag("", TAG_AUDIO_TRACK);
-            serializer.attribute("", ATTR_ID, at.getId());
-            serializer.attribute("", ATTR_FILENAME, at.getFilename());
-            serializer.attribute("", ATTR_START_TIME, Long.toString(at.getStartTime()));
-            serializer.attribute("", ATTR_BEGIN_TIME, Long.toString(at.getBoundaryBeginTime()));
-            serializer.attribute("", ATTR_END_TIME, Long.toString(at.getBoundaryEndTime()));
-            serializer.attribute("", ATTR_VOLUME, Integer.toString(at.getVolume()));
-            serializer.attribute("", ATTR_DUCK_ENABLED,
-                                       Boolean.toString(at.isDuckingEnabled()));
-            serializer.attribute("", ATTR_DUCKED_TRACK_VOLUME,
-                                   Integer.toString(at.getDuckedTrackVolume()));
-            serializer.attribute("", ATTR_DUCK_THRESHOLD,
-                                   Integer.toString(at.getDuckingThreshhold()));
-            serializer.attribute("", ATTR_MUTED, Boolean.toString(at.isMuted()));
-            serializer.attribute("", ATTR_LOOP, Boolean.toString(at.isLooping()));
-            if (at.getAudioWaveformFilename() != null) {
-                serializer.attribute("", ATTR_AUDIO_WAVEFORM_FILENAME,
-                        at.getAudioWaveformFilename());
-            }
-
-            serializer.endTag("", TAG_AUDIO_TRACK);
-        }
-        serializer.endTag("", TAG_AUDIO_TRACKS);
-
-        serializer.endTag("", TAG_PROJECT);
-        serializer.endDocument();
-
-        /**
-         *  Save the metadata XML file
-         */
-        final FileOutputStream out = new FileOutputStream(new File(getPath(),
-                                                          PROJECT_FILENAME));
-        out.write(writer.toString().getBytes());
-        out.flush();
-        out.close();
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void setAspectRatio(int aspectRatio) {
-        mAspectRatio = aspectRatio;
-        /**
-         *  Invalidate all transitions
-         */
-        mMANativeHelper.setGeneratePreview(true);
-
-        for (Transition transition : mTransitions) {
-            transition.invalidate();
-        }
-
-        final Iterator<MediaItem> it = mMediaItems.iterator();
-
-        while (it.hasNext()) {
-            final MediaItem t = it.next();
-            List<Overlay> overlayList = t.getAllOverlays();
-            for (Overlay overlay : overlayList) {
-
-                ((OverlayFrame)overlay).invalidateGeneratedFiles();
-            }
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public void startPreview(SurfaceHolder surfaceHolder, long fromMs, long toMs,
-                             boolean loop, int callbackAfterFrameCount,
-                             PreviewProgressListener listener) {
-
-        if (surfaceHolder == null) {
-            throw new IllegalArgumentException();
-        }
-
-        final Surface surface = surfaceHolder.getSurface();
-        if (surface == null) {
-            throw new IllegalArgumentException("Surface could not be retrieved from surface holder");
-        }
-
-        if (surface.isValid() == false) {
-            throw new IllegalStateException("Surface is not valid");
-        }
-
-        if (listener == null) {
-            throw new IllegalArgumentException();
-        }
-
-        if (fromMs >= mDurationMs) {
-            throw new IllegalArgumentException("Requested time not correct");
-        }
-
-        if (fromMs < 0) {
-            throw new IllegalArgumentException("Requested time not correct");
-        }
-
-        boolean semAcquireDone = false;
-        if (!mPreviewInProgress) {
-            try{
-                semAcquireDone = lock(ENGINE_ACCESS_MAX_TIMEOUT_MS);
-                if (semAcquireDone == false) {
-                    throw new IllegalStateException("Timeout waiting for semaphore");
-                }
-
-                if (mMANativeHelper == null) {
-                    throw new IllegalStateException("The video editor is not initialized");
-                }
-
-                if (mMediaItems.size() > 0) {
-                    mPreviewInProgress = true;
-                    mMANativeHelper.previewStoryBoard(mMediaItems, mTransitions,
-                                                      mAudioTracks, null);
-                    mMANativeHelper.doPreview(surface, fromMs, toMs, loop,
-                                     callbackAfterFrameCount, listener);
-                }
-                /**
-                 *  Release The lock on complete by calling stopPreview
-                 */
-            } catch (InterruptedException ex) {
-                Log.w(TAG, "The thread was interrupted", new Throwable());
-                throw new IllegalStateException("The thread was interrupted");
-            }
-         } else {
-            throw new IllegalStateException("Preview already in progress");
-        }
-    }
-
-    /*
-     * {@inheritDoc}
-     */
-    public long stopPreview() {
-        long result = 0;
-        if (mPreviewInProgress) {
-            try {
-                result = mMANativeHelper.stopPreview();
-                /**
-                 *  release on complete by calling stopPreview
-                 */
-                } finally {
-                    mPreviewInProgress = false;
-                    unlock();
-                }
-            return result;
-        }
-        else {
-            return 0;
-        }
-    }
-
-    /*
-     * Remove transitions associated with the specified media item
-     *
-     * @param mediaItem The media item
-     */
-    private void removeAdjacentTransitions(MediaItem mediaItem) {
-        final Transition beginTransition = mediaItem.getBeginTransition();
-        if (beginTransition != null) {
-            if (beginTransition.getAfterMediaItem() != null) {
-                beginTransition.getAfterMediaItem().setEndTransition(null);
-            }
-            beginTransition.invalidate();
-            mTransitions.remove(beginTransition);
-        }
-
-        final Transition endTransition = mediaItem.getEndTransition();
-        if (endTransition != null) {
-            if (endTransition.getBeforeMediaItem() != null) {
-                endTransition.getBeforeMediaItem().setBeginTransition(null);
-            }
-            endTransition.invalidate();
-            mTransitions.remove(endTransition);
-        }
-
-        mediaItem.setBeginTransition(null);
-        mediaItem.setEndTransition(null);
-    }
-
-    /**
-     * Remove the transition before this media item
-     *
-     * @param index The media item index
-     */
-    private void removeTransitionBefore(int index) {
-        final MediaItem mediaItem = mMediaItems.get(index);
-        final Iterator<Transition> it = mTransitions.iterator();
-        while (it.hasNext()) {
-            Transition t = it.next();
-            if (t.getBeforeMediaItem() == mediaItem) {
-                mMANativeHelper.setGeneratePreview(true);
-                it.remove();
-                t.invalidate();
-                mediaItem.setBeginTransition(null);
-                if (index > 0) {
-                    mMediaItems.get(index - 1).setEndTransition(null);
-                }
-                break;
-            }
-        }
-    }
-
-    /**
-     * Remove the transition after this media item
-     *
-     * @param mediaItem The media item
-     */
-    private void removeTransitionAfter(int index) {
-        final MediaItem mediaItem = mMediaItems.get(index);
-        final Iterator<Transition> it = mTransitions.iterator();
-        while (it.hasNext()) {
-            Transition t = it.next();
-            if (t.getAfterMediaItem() == mediaItem) {
-                mMANativeHelper.setGeneratePreview(true);
-                it.remove();
-                t.invalidate();
-                mediaItem.setEndTransition(null);
-                /**
-                 *  Invalidate the reference in the next media item
-                 */
-                if (index < mMediaItems.size() - 1) {
-                    mMediaItems.get(index + 1).setBeginTransition(null);
-                }
-                break;
-            }
-        }
-    }
-
-    /**
-     * Compute the duration
-     */
-    private void computeTimelineDuration() {
-        mDurationMs = 0;
-        final int mediaItemsCount = mMediaItems.size();
-        for (int i = 0; i < mediaItemsCount; i++) {
-            final MediaItem mediaItem = mMediaItems.get(i);
-            mDurationMs += mediaItem.getTimelineDuration();
-            if (mediaItem.getEndTransition() != null) {
-                if (i < mediaItemsCount - 1) {
-                    mDurationMs -= mediaItem.getEndTransition().getDuration();
-                }
-            }
-        }
-    }
-
-    /*
-     * Generate the project thumbnail
-     */
-    private void generateProjectThumbnail() {
-        /*
-         * If a thumbnail already exists, then delete it first
-         */
-        if ((new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).exists()) {
-            (new File(mProjectPath + "/" + THUMBNAIL_FILENAME)).delete();
-        }
-        /*
-         * Generate a new thumbnail for the project from first media Item
-         */
-        if (mMediaItems.size() > 0) {
-            MediaItem mI = mMediaItems.get(0);
-            /*
-             * Keep aspect ratio of the image
-             */
-            int height = 480;
-            int width = mI.getWidth() * height / mI.getHeight();
-
-            Bitmap projectBitmap = null;
-            String filename = mI.getFilename();
-            if (mI instanceof MediaVideoItem) {
-                MediaMetadataRetriever retriever = new MediaMetadataRetriever();
-                retriever.setDataSource(filename);
-                Bitmap bitmap = retriever.getFrameAtTime();
-                retriever.release();
-                retriever = null;
-                if (bitmap == null) {
-                    String msg = "Thumbnail extraction from " +
-                                    filename + " failed";
-                    throw new IllegalArgumentException(msg);
-                }
-                // Resize the thumbnail to the target size
-                projectBitmap =
-                    Bitmap.createScaledBitmap(bitmap, width, height, true);
-            } else {
-                try {
-                    projectBitmap = mI.getThumbnail(width, height, 500);
-                } catch (IllegalArgumentException e) {
-                    String msg = "Project thumbnail extraction from " +
-                                    filename + " failed";
-                    throw new IllegalArgumentException(msg);
-                } catch (IOException e) {
-                    String msg = "IO Error creating project thumbnail";
-                    throw new IllegalArgumentException(msg);
-                }
-            }
-
-            try {
-                FileOutputStream stream = new FileOutputStream(mProjectPath + "/"
-                                                          + THUMBNAIL_FILENAME);
-                projectBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream);
-                stream.flush();
-                stream.close();
-            } catch (IOException e) {
-                throw new IllegalArgumentException ("Error creating project thumbnail");
-            } finally {
-                projectBitmap.recycle();
-            }
-        }
-    }
-
-    /**
-     * Clears the preview surface
-     *
-     * @param surfaceHolder SurfaceHolder where the preview is rendered
-     * and needs to be cleared.
-     */
-    public void clearSurface(SurfaceHolder surfaceHolder) {
-        if (surfaceHolder == null) {
-            throw new IllegalArgumentException("Invalid surface holder");
-        }
-
-        final Surface surface = surfaceHolder.getSurface();
-        if (surface == null) {
-            throw new IllegalArgumentException("Surface could not be retrieved from surface holder");
-        }
-
-        if (surface.isValid() == false) {
-            throw new IllegalStateException("Surface is not valid");
-        }
-
-        if (mMANativeHelper != null) {
-            mMANativeHelper.clearPreviewSurface(surface);
-        } else {
-            Log.w(TAG, "Native helper was not ready!");
-        }
-    }
-
-    /**
-     * Grab the semaphore which arbitrates access to the editor
-     *
-     * @throws InterruptedException
-     */
-    private void lock() throws InterruptedException {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbing semaphore", new Throwable());
-        }
-        mLock.acquire();
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbed semaphore");
-        }
-    }
-
-    /**
-     * Tries to grab the semaphore with a specified time out which arbitrates access to the editor
-     *
-     * @param timeoutMs time out in ms.
-     *
-     * @return true if the semaphore is acquired, false otherwise
-     * @throws InterruptedException
-     */
-    private boolean lock(long timeoutMs) throws InterruptedException {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbing semaphore with timeout " + timeoutMs, new Throwable());
-        }
-
-        boolean acquireSem = mLock.tryAcquire(timeoutMs, TimeUnit.MILLISECONDS);
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "lock: grabbed semaphore status " + acquireSem);
-        }
-
-        return acquireSem;
-    }
-
-    /**
-     * Release the semaphore which arbitrates access to the editor
-     */
-    private void unlock() {
-        if (Log.isLoggable(TAG, Log.DEBUG)) {
-            Log.d(TAG, "unlock: releasing semaphore");
-        }
-        mLock.release();
-    }
-
-    /**
-     * Dumps the heap memory usage information to file
-     */
-    private static void dumpHeap (String filename) throws Exception {
-        /* Cleanup as much as possible before dump
-         */
-        System.gc();
-        System.runFinalization();
-        Thread.sleep(1000);
-        String state = Environment.getExternalStorageState();
-        if (Environment.MEDIA_MOUNTED.equals(state)) {
-            String extDir =
-             Environment.getExternalStorageDirectory().toString();
-
-            /* If dump file already exists, then delete it first
-            */
-            if ((new File(extDir + "/" + filename + ".dump")).exists()) {
-                (new File(extDir + "/" + filename + ".dump")).delete();
-            }
-            /* Dump native heap
-            */
-            FileOutputStream ost =
-             new FileOutputStream(extDir + "/" + filename + ".dump");
-            Debug.dumpNativeHeap(ost.getFD());
-            ost.close();
-        }
-    }
-}
diff --git a/media/java/android/media/videoeditor/VideoEditorProfile.java b/media/java/android/media/videoeditor/VideoEditorProfile.java
deleted file mode 100644
index 202a2df..0000000
--- a/media/java/android/media/videoeditor/VideoEditorProfile.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2011 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.media.videoeditor;
-
-/**
- * The VideoEditorProfile class is used to retrieve the
- * predefined videoeditor profile settings for videoeditor applications.
- * These settings are read-only.
- *
- * <p>The videoeditor profile specifies the following set of parameters:
- * <ul>
- * <li> max input video frame width
- * <li> max input video frame height
- * <li> max output video frame width
- * <li> max output video frame height
- * </ul>
- * {@hide}
- */
-public class VideoEditorProfile
-{
-    static {
-        System.loadLibrary("media_jni");
-        native_init();
-    }
-    /**
-     * The max input video frame width
-     */
-    public int maxInputVideoFrameWidth;
-
-    /**
-     * The max input video frame height
-     */
-    public int maxInputVideoFrameHeight;
-
-    /**
-     * The max ouput video frame width
-     */
-    public int maxOutputVideoFrameWidth;
-
-    /**
-     * The max ouput video frame height
-     */
-    public int maxOutputVideoFrameHeight;
-
-    /**
-     * Returns the videoeditor profile
-     */
-    public static VideoEditorProfile get() {
-        return native_get_videoeditor_profile();
-    }
-
-    /**
-     * Returns the supported profile by given video codec
-     */
-    public static int getExportProfile(int vidCodec) {
-        int profile = -1;
-
-        switch (vidCodec) {
-            case MediaProperties.VCODEC_H263:
-            case MediaProperties.VCODEC_H264:
-            case MediaProperties.VCODEC_MPEG4:
-                 profile = native_get_videoeditor_export_profile(vidCodec);
-                 break;
-            default :
-               throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
-        }
-
-        return profile;
-    }
-
-    /**
-     * Returns the supported level by given video codec
-     */
-    public static int getExportLevel(int vidCodec) {
-        int level = -1;
-
-        switch (vidCodec) {
-            case MediaProperties.VCODEC_H263:
-            case MediaProperties.VCODEC_H264:
-            case MediaProperties.VCODEC_MPEG4:
-                 level = native_get_videoeditor_export_level(vidCodec);
-                 break;
-            default :
-               throw new IllegalArgumentException("Unsupported video codec" + vidCodec);
-        }
-
-        return level;
-    }
-
-    // Private constructor called by JNI
-    private VideoEditorProfile(int inputWidth,
-                             int inputHeight,
-                             int outputWidth,
-                             int outputHeight) {
-
-        this.maxInputVideoFrameWidth = inputWidth;
-        this.maxInputVideoFrameHeight = inputHeight;
-        this.maxOutputVideoFrameWidth = outputWidth;
-        this.maxOutputVideoFrameHeight = outputHeight;
-    }
-
-    // Methods implemented by JNI
-    private static native final void native_init();
-    private static native final VideoEditorProfile
-        native_get_videoeditor_profile();
-    private static native final int native_get_videoeditor_export_profile(int codec);
-    private static native final int native_get_videoeditor_export_level(int level);
-
-}
diff --git a/media/java/android/media/videoeditor/WaveformData.java b/media/java/android/media/videoeditor/WaveformData.java
deleted file mode 100644
index 6c10e3c..0000000
--- a/media/java/android/media/videoeditor/WaveformData.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * Copyright (C) 2010 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.media.videoeditor;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
-/**
- * Class which describes the waveform data of an audio track. The gain values
- * represent the average gain for an audio frame. For audio codecs which do not
- * operate on a per frame bases (eg. ALAW, ULAW) a reasonable audio frame
- * duration will be assumed (eg. 50ms).
- * {@hide}
- */
-public class WaveformData {
-    /*
-     *  Instance variables
-     */
-    private final int mFrameDurationMs;
-    private final int mFramesCount;
-    private final short[] mGains;
-
-    /*
-     * This constructor shall not be used
-     */
-    @SuppressWarnings("unused")
-    private WaveformData() throws IOException {
-        mFrameDurationMs = 0;
-        mFramesCount = 0;
-        mGains = null;
-    }
-
-    /*
-     * Constructor
-     *
-     * @param audioWaveformFilename The name of the audio waveform file
-     *
-     * The file format is as following:
-     * <ul>
-     *  <li>first 4 bytes provide the number of samples for each value, as
-     *  big-endian signed</li>
-     *  <li>4 following bytes is the total number of values in the file, as
-     *  big-endian signed</li>
-     *  <li>then, all values follow as bytes</li>
-     * </ul>
-     *
-     * @throws IOException on failure of file input stream operations
-     * @throws IllegalArgumentException if audioWaveformFilename is null
-     */
-    WaveformData(String audioWaveformFilename) throws IOException {
-
-        if (audioWaveformFilename == null) {
-            throw new IllegalArgumentException("WaveformData : filename is null");
-        }
-
-        FileInputStream audioGraphFileReadHandle = null;
-
-        try {
-            final File audioGraphFileContext = new File(audioWaveformFilename);
-
-            audioGraphFileReadHandle = new FileInputStream(audioGraphFileContext);
-            /*
-             * Read frame duration
-             */
-            final byte tempFrameDuration[] = new byte[4];
-
-            audioGraphFileReadHandle.read(tempFrameDuration, 0, 4);
-
-            int tempFrameDurationMs = 0;
-            int tempFramesCounter = 0;
-            for (int i = 0; i < 4; i++) {
-                tempFrameDurationMs = (tempFrameDurationMs << 8);
-                tempFrameDurationMs = (tempFrameDurationMs | (tempFrameDuration[i] & 0xff));
-            }
-            mFrameDurationMs = tempFrameDurationMs;
-
-            /*
-             * Read count
-             */
-            final byte tempFramesCount[] = new byte[4];
-
-            audioGraphFileReadHandle.read(tempFramesCount, 0, 4);
-            for (int i = 0; i < 4; i++) {
-                tempFramesCounter = (tempFramesCounter << 8);
-                tempFramesCounter = (tempFramesCounter | (tempFramesCount[i] & 0xff));
-            }
-            mFramesCount = tempFramesCounter;
-
-            /*
-             *  Capture the graph values
-             */
-            mGains = new short[mFramesCount];
-
-            for (int i = 0; i < mFramesCount; i++) {
-                mGains[i] = (short)audioGraphFileReadHandle.read();
-            }
-        } finally {
-            if (audioGraphFileReadHandle != null) {
-                audioGraphFileReadHandle.close();
-            }
-        }
-    }
-
-    /**
-     * @return The duration of a frame in milliseconds
-     */
-    public int getFrameDuration() {
-        return mFrameDurationMs;
-    }
-
-    /**
-     * @return The number of frames within the waveform data
-     */
-    public int getFramesCount() {
-        return mFramesCount;
-    }
-
-    /**
-     * @return The array of frame gains. The size of the array is the frames
-     *         count. The values of the frame gains range from 0 to 255.
-     */
-    public short[] getFrameGains() {
-        return mGains;
-    }
-}
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index 716418c..7a86811 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -274,17 +274,11 @@
 
     fid = env->GetStaticFieldID(imageFormatClazz, "JPEG", "I");
     jpegFormat = env->GetStaticIntField(imageFormatClazz, fid);
-    fid = env->GetStaticFieldID(imageFormatClazz, "RAW_SENSOR", "I");
-    rawSensorFormat = env->GetStaticIntField(imageFormatClazz, fid);
 
-    // Translate the JPEG to BLOB for camera purpose, an add more if more mismatch is found.
+    // Translate the JPEG to BLOB for camera purpose.
     if (format == jpegFormat) {
         format = HAL_PIXEL_FORMAT_BLOB;
     }
-    // Same thing for RAW_SENSOR format
-    if (format == rawSensorFormat) {
-        format = HAL_PIXEL_FORMAT_RAW_SENSOR;
-    }
 
     return format;
 }
diff --git a/media/jni/android_media_MediaCodec.cpp b/media/jni/android_media_MediaCodec.cpp
index d04b1f8..a710c03 100644
--- a/media/jni/android_media_MediaCodec.cpp
+++ b/media/jni/android_media_MediaCodec.cpp
@@ -255,7 +255,7 @@
             env, env->FindClass("android/media/MediaCodec$BufferInfo"));
 
     jmethodID method = env->GetMethodID(clazz.get(), "set", "(IIJI)V");
-    env->CallVoidMethod(bufferInfo, method, offset, size, timeUs, flags);
+    env->CallVoidMethod(bufferInfo, method, (jint)offset, (jint)size, timeUs, flags);
 
     return OK;
 }
diff --git a/media/jni/android_media_MediaDrm.cpp b/media/jni/android_media_MediaDrm.cpp
index 7c45682..4fbd2a4 100644
--- a/media/jni/android_media_MediaDrm.cpp
+++ b/media/jni/android_media_MediaDrm.cpp
@@ -297,8 +297,6 @@
 }
 
 JDrm::~JDrm() {
-    mDrm.clear();
-
     JNIEnv *env = AndroidRuntime::getJNIEnv();
 
     env->DeleteWeakGlobalRef(mObject);
@@ -363,6 +361,13 @@
     }
 }
 
+void JDrm::disconnect() {
+    if (mDrm != NULL) {
+        mDrm->destroyPlugin();
+        mDrm.clear();
+    }
+}
+
 
 // static
 bool JDrm::IsCryptoSchemeSupported(const uint8_t uuid[16], const String8 &mimeType) {
@@ -527,6 +532,7 @@
     sp<JDrm> drm = setDrm(env, thiz, NULL);
     if (drm != NULL) {
         drm->setListener(NULL);
+        drm->disconnect();
     }
 }
 
diff --git a/media/jni/android_media_MediaDrm.h b/media/jni/android_media_MediaDrm.h
index 620ad28..b7b8e5d 100644
--- a/media/jni/android_media_MediaDrm.h
+++ b/media/jni/android_media_MediaDrm.h
@@ -47,6 +47,8 @@
     void notify(DrmPlugin::EventType, int extra, const Parcel *obj);
     status_t setListener(const sp<DrmListener>& listener);
 
+    void disconnect();
+
 protected:
     virtual ~JDrm();
 
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index 4e42ae3..157dd49 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -273,6 +273,13 @@
                             width,
                             height,
                             config);
+    if (jBitmap == NULL) {
+        if (env->ExceptionCheck()) {
+            env->ExceptionClear();
+        }
+        ALOGE("getFrameAtTime: create Bitmap failed!");
+        return NULL;
+    }
 
     SkBitmap *bitmap =
             (SkBitmap *) env->GetLongField(jBitmap, fields.nativeBitmap);
diff --git a/media/jni/android_media_MediaProfiles.cpp b/media/jni/android_media_MediaProfiles.cpp
index 48a9132..1e5c700 100644
--- a/media/jni/android_media_MediaProfiles.cpp
+++ b/media/jni/android_media_MediaProfiles.cpp
@@ -290,75 +290,6 @@
     }
     return static_cast<jint>(levels[index]);
 }
-static jobject
-android_media_MediaProfiles_native_get_videoeditor_profile(JNIEnv *env, jobject thiz)
-{
-    ALOGV("native_get_videoeditor_profile");
-
-    int maxInputFrameWidth =
-            sProfiles->getVideoEditorCapParamByName("videoeditor.input.width.max");
-    int maxInputFrameHeight =
-            sProfiles->getVideoEditorCapParamByName("videoeditor.input.height.max");
-    int maxOutputFrameWidth =
-            sProfiles->getVideoEditorCapParamByName("videoeditor.output.width.max");
-    int maxOutputFrameHeight =
-            sProfiles->getVideoEditorCapParamByName("videoeditor.output.height.max");
-
-    // Check on the values retrieved
-    if (maxInputFrameWidth == -1 || maxInputFrameHeight == -1 ||
-        maxOutputFrameWidth == -1 || maxOutputFrameHeight == -1) {
-
-        jniThrowException(env, "java/lang/RuntimeException",\
-            "Error retrieving videoeditor profile params");
-        return NULL;
-    }
-    ALOGV("native_get_videoeditor_profile \
-        inWidth:%d inHeight:%d,outWidth:%d, outHeight:%d",\
-        maxInputFrameWidth,maxInputFrameHeight,\
-        maxOutputFrameWidth,maxOutputFrameHeight);
-
-    jclass VideoEditorProfileClazz =
-        env->FindClass("android/media/videoeditor/VideoEditorProfile");
-    jmethodID VideoEditorProfileConstructorMethodID =
-        env->GetMethodID(VideoEditorProfileClazz, "<init>", "(IIII)V");
-    return env->NewObject(VideoEditorProfileClazz,
-                          VideoEditorProfileConstructorMethodID,
-                          maxInputFrameWidth,
-                          maxInputFrameHeight,
-                          maxOutputFrameWidth,
-                          maxOutputFrameHeight);
-}
-static jint
-android_media_MediaProfiles_native_get_videoeditor_export_profile(
-    JNIEnv *env, jobject thiz, jint codec)
-{
-    ALOGV("android_media_MediaProfiles_native_get_export_profile index ");
-    int profile =0;
-    profile = sProfiles->getVideoEditorExportParamByName("videoeditor.export.profile", codec);
-    // Check the values retrieved
-    if (profile == -1) {
-        jniThrowException(env, "java/lang/RuntimeException",\
-            "Error retrieving videoeditor export profile params");
-        return -1;
-    }
-    return static_cast<jint>(profile);
-}
-
-static jint
-android_media_MediaProfiles_native_get_videoeditor_export_level(
-    JNIEnv *env, jobject thiz, jint codec)
-{
-    ALOGV("android_media_MediaProfiles_native_get_export_level");
-    int level =0;
-    level = sProfiles->getVideoEditorExportParamByName("videoeditor.export.level", codec);
-    // Check the values retrieved
-    if (level == -1) {
-        jniThrowException(env, "java/lang/RuntimeException",\
-            "Error retrieving videoeditor export level params");
-        return -1;
-    }
-    return static_cast<jint>(level);
-}
 static JNINativeMethod gMethodsForEncoderCapabilitiesClass[] = {
     {"native_init",                            "()V",                    (void *)android_media_MediaProfiles_native_init},
     {"native_get_num_file_formats",            "()I",                    (void *)android_media_MediaProfiles_native_get_num_file_formats},
@@ -396,19 +327,10 @@
     {"native_get_image_encoding_quality_level","(II)I",                   (void *)android_media_MediaProfiles_native_get_image_encoding_quality_level},
 };
 
-static JNINativeMethod gMethodsForVideoEditorProfileClass[] = {
-    {"native_init",                            "()V",         (void *)android_media_MediaProfiles_native_init},
-    {"native_get_videoeditor_profile", "()Landroid/media/videoeditor/VideoEditorProfile;", (void *)android_media_MediaProfiles_native_get_videoeditor_profile},
-    {"native_get_videoeditor_export_profile", "(I)I", (void *)android_media_MediaProfiles_native_get_videoeditor_export_profile},
-    {"native_get_videoeditor_export_level", "(I)I", (void *)android_media_MediaProfiles_native_get_videoeditor_export_level},
-};
-
 static const char* const kEncoderCapabilitiesClassPathName = "android/media/EncoderCapabilities";
 static const char* const kDecoderCapabilitiesClassPathName = "android/media/DecoderCapabilities";
 static const char* const kCamcorderProfileClassPathName = "android/media/CamcorderProfile";
 static const char* const kCameraProfileClassPathName = "android/media/CameraProfile";
-static const char* const kVideoEditorProfileClassPathName =
-    "android/media/videoeditor/VideoEditorProfile";
 
 // This function only registers the native methods, and is called from
 // JNI_OnLoad in android_media_MediaPlayer.cpp
@@ -434,11 +356,6 @@
                gMethodsForCameraProfileClass,
                NELEM(gMethodsForCameraProfileClass));
 
-    int ret5 = AndroidRuntime::registerNativeMethods(env,
-               kVideoEditorProfileClassPathName,
-               gMethodsForVideoEditorProfileClass,
-               NELEM(gMethodsForVideoEditorProfileClass));
-
     // Success if all return values from above are 0
-    return (ret1 || ret2 || ret3 || ret4 || ret5);
+    return (ret1 || ret2 || ret3 || ret4);
 }
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index fd69cad..1685a44 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -14,6 +14,13 @@
  * limitations under the License.
  */
 
+#include <assert.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+
 //#define LOG_NDEBUG 0
 #define LOG_TAG "MediaRecorderJNI"
 #include <utils/Log.h>
@@ -22,11 +29,6 @@
 #include <camera/ICameraService.h>
 #include <camera/Camera.h>
 #include <media/mediarecorder.h>
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-#include <unistd.h>
-#include <fcntl.h>
 #include <utils/threads.h>
 
 #include "jni.h"
@@ -303,7 +305,7 @@
     sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
 
     char params[64];
-    sprintf(params, "max-filesize=%lld", max_filesize_bytes);
+    sprintf(params, "max-filesize=%" PRId64, max_filesize_bytes);
 
     process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxFileSize failed.");
 }
diff --git a/media/jni/android_mtp_MtpDatabase.cpp b/media/jni/android_mtp_MtpDatabase.cpp
index 0e55228..d781336 100644
--- a/media/jni/android_mtp_MtpDatabase.cpp
+++ b/media/jni/android_mtp_MtpDatabase.cpp
@@ -859,6 +859,7 @@
                 result = malloc(exifdata->size);
                 if (result) {
                     memcpy(result, exifdata->data, exifdata->size);
+                    outThumbSize = exifdata->size;
                 }
             }
             exif_data_unref(exifdata);
diff --git a/media/jni/mediaeditor/Android.mk b/media/jni/mediaeditor/Android.mk
deleted file mode 100644
index 312c366..0000000
--- a/media/jni/mediaeditor/Android.mk
+++ /dev/null
@@ -1,81 +0,0 @@
-#
-# Copyright (C) 2011 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.
-#
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
-    VideoEditorMain.cpp \
-    VideoEditorClasses.cpp \
-    VideoEditorOsal.cpp \
-    VideoEditorJava.cpp \
-    VideoEditorPropertiesMain.cpp \
-    VideoEditorThumbnailMain.cpp  \
-    VideoBrowserMain.c
-
-LOCAL_C_INCLUDES += \
-    $(TOP)/frameworks/base/core/jni \
-    $(TOP)/frameworks/base/include \
-    $(TOP)/frameworks/base/include/media \
-    $(TOP)/frameworks/base/media/libmediaplayerservice \
-    $(TOP)/frameworks/base/media/libstagefright \
-    $(TOP)/frameworks/base/media/libstagefright/include \
-    $(TOP)/frameworks/base/media/libstagefright/rtsp \
-    $(JNI_H_INCLUDE) \
-    $(TOP)/frameworks/native/include/media/editor \
-    $(TOP)/frameworks/base/core/jni/mediaeditor \
-    $(TOP)/frameworks/av/libvideoeditor/vss/inc \
-    $(TOP)/frameworks/av/libvideoeditor/vss/common/inc \
-    $(TOP)/frameworks/av/libvideoeditor/vss/mcs/inc \
-    $(TOP)/frameworks/av/libvideoeditor/vss/stagefrightshells/inc \
-    $(TOP)/frameworks/av/libvideoeditor/lvpp \
-    $(TOP)/frameworks/av/libvideoeditor/osal/inc \
-    $(TOP)/frameworks/native/include/media/openmax
-
-LOCAL_SHARED_LIBRARIES := \
-    libandroid_runtime \
-    libaudioutils \
-    libbinder \
-    libcutils \
-    liblog \
-    libdl \
-    libgui \
-    libmedia \
-    libnativehelper \
-    libstagefright \
-    libstagefright_foundation \
-    libstagefright_omx \
-    libutils \
-    libvideoeditor_core \
-    libvideoeditor_osal \
-    libvideoeditor_videofilters \
-    libvideoeditorplayer \
-
-
-LOCAL_CFLAGS += \
-    -DUSE_STAGEFRIGHT_CODECS \
-    -DUSE_STAGEFRIGHT_AUDIODEC \
-    -DUSE_STAGEFRIGHT_VIDEODEC \
-    -DUSE_STAGEFRIGHT_AUDIOENC \
-    -DUSE_STAGEFRIGHT_VIDEOENC \
-    -DUSE_STAGEFRIGHT_READERS \
-    -DUSE_STAGEFRIGHT_3GPP_READER
-
-LOCAL_MODULE:= libvideoeditor_jni
-
-LOCAL_MODULE_TAGS := optional
-
-include $(BUILD_SHARED_LIBRARY)
diff --git a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2 b/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29..0000000
--- a/media/jni/mediaeditor/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/media/jni/mediaeditor/NOTICE b/media/jni/mediaeditor/NOTICE
deleted file mode 100644
index c5b1efa..0000000
--- a/media/jni/mediaeditor/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
-   Copyright (c) 2005-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.
-
-   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.
-
-
-                                 Apache License
-                           Version 2.0, January 2004
-                        http://www.apache.org/licenses/
-
-   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-   1. Definitions.
-
-      "License" shall mean the terms and conditions for use, reproduction,
-      and distribution as defined by Sections 1 through 9 of this document.
-
-      "Licensor" shall mean the copyright owner or entity authorized by
-      the copyright owner that is granting the License.
-
-      "Legal Entity" shall mean the union of the acting entity and all
-      other entities that control, are controlled by, or are under common
-      control with that entity. For the purposes of this definition,
-      "control" means (i) the power, direct or indirect, to cause the
-      direction or management of such entity, whether by contract or
-      otherwise, or (ii) ownership of fifty percent (50%) or more of the
-      outstanding shares, or (iii) beneficial ownership of such entity.
-
-      "You" (or "Your") shall mean an individual or Legal Entity
-      exercising permissions granted by this License.
-
-      "Source" form shall mean the preferred form for making modifications,
-      including but not limited to software source code, documentation
-      source, and configuration files.
-
-      "Object" form shall mean any form resulting from mechanical
-      transformation or translation of a Source form, including but
-      not limited to compiled object code, generated documentation,
-      and conversions to other media types.
-
-      "Work" shall mean the work of authorship, whether in Source or
-      Object form, made available under the License, as indicated by a
-      copyright notice that is included in or attached to the work
-      (an example is provided in the Appendix below).
-
-      "Derivative Works" shall mean any work, whether in Source or Object
-      form, that is based on (or derived from) the Work and for which the
-      editorial revisions, annotations, elaborations, or other modifications
-      represent, as a whole, an original work of authorship. For the purposes
-      of this License, Derivative Works shall not include works that remain
-      separable from, or merely link (or bind by name) to the interfaces of,
-      the Work and Derivative Works thereof.
-
-      "Contribution" shall mean any work of authorship, including
-      the original version of the Work and any modifications or additions
-      to that Work or Derivative Works thereof, that is intentionally
-      submitted to Licensor for inclusion in the Work by the copyright owner
-      or by an individual or Legal Entity authorized to submit on behalf of
-      the copyright owner. For the purposes of this definition, "submitted"
-      means any form of electronic, verbal, or written communication sent
-      to the Licensor or its representatives, including but not limited to
-      communication on electronic mailing lists, source code control systems,
-      and issue tracking systems that are managed by, or on behalf of, the
-      Licensor for the purpose of discussing and improving the Work, but
-      excluding communication that is conspicuously marked or otherwise
-      designated in writing by the copyright owner as "Not a Contribution."
-
-      "Contributor" shall mean Licensor and any individual or Legal Entity
-      on behalf of whom a Contribution has been received by Licensor and
-      subsequently incorporated within the Work.
-
-   2. Grant of Copyright License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      copyright license to reproduce, prepare Derivative Works of,
-      publicly display, publicly perform, sublicense, and distribute the
-      Work and such Derivative Works in Source or Object form.
-
-   3. Grant of Patent License. Subject to the terms and conditions of
-      this License, each Contributor hereby grants to You a perpetual,
-      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-      (except as stated in this section) patent license to make, have made,
-      use, offer to sell, sell, import, and otherwise transfer the Work,
-      where such license applies only to those patent claims licensable
-      by such Contributor that are necessarily infringed by their
-      Contribution(s) alone or by combination of their Contribution(s)
-      with the Work to which such Contribution(s) was submitted. If You
-      institute patent litigation against any entity (including a
-      cross-claim or counterclaim in a lawsuit) alleging that the Work
-      or a Contribution incorporated within the Work constitutes direct
-      or contributory patent infringement, then any patent licenses
-      granted to You under this License for that Work shall terminate
-      as of the date such litigation is filed.
-
-   4. Redistribution. You may reproduce and distribute copies of the
-      Work or Derivative Works thereof in any medium, with or without
-      modifications, and in Source or Object form, provided that You
-      meet the following conditions:
-
-      (a) You must give any other recipients of the Work or
-          Derivative Works a copy of this License; and
-
-      (b) You must cause any modified files to carry prominent notices
-          stating that You changed the files; and
-
-      (c) You must retain, in the Source form of any Derivative Works
-          that You distribute, all copyright, patent, trademark, and
-          attribution notices from the Source form of the Work,
-          excluding those notices that do not pertain to any part of
-          the Derivative Works; and
-
-      (d) If the Work includes a "NOTICE" text file as part of its
-          distribution, then any Derivative Works that You distribute must
-          include a readable copy of the attribution notices contained
-          within such NOTICE file, excluding those notices that do not
-          pertain to any part of the Derivative Works, in at least one
-          of the following places: within a NOTICE text file distributed
-          as part of the Derivative Works; within the Source form or
-          documentation, if provided along with the Derivative Works; or,
-          within a display generated by the Derivative Works, if and
-          wherever such third-party notices normally appear. The contents
-          of the NOTICE file are for informational purposes only and
-          do not modify the License. You may add Your own attribution
-          notices within Derivative Works that You distribute, alongside
-          or as an addendum to the NOTICE text from the Work, provided
-          that such additional attribution notices cannot be construed
-          as modifying the License.
-
-      You may add Your own copyright statement to Your modifications and
-      may provide additional or different license terms and conditions
-      for use, reproduction, or distribution of Your modifications, or
-      for any such Derivative Works as a whole, provided Your use,
-      reproduction, and distribution of the Work otherwise complies with
-      the conditions stated in this License.
-
-   5. Submission of Contributions. Unless You explicitly state otherwise,
-      any Contribution intentionally submitted for inclusion in the Work
-      by You to the Licensor shall be under the terms and conditions of
-      this License, without any additional terms or conditions.
-      Notwithstanding the above, nothing herein shall supersede or modify
-      the terms of any separate license agreement you may have executed
-      with Licensor regarding such Contributions.
-
-   6. Trademarks. This License does not grant permission to use the trade
-      names, trademarks, service marks, or product names of the Licensor,
-      except as required for reasonable and customary use in describing the
-      origin of the Work and reproducing the content of the NOTICE file.
-
-   7. Disclaimer of Warranty. Unless required by applicable law or
-      agreed to in writing, Licensor provides the Work (and each
-      Contributor provides its Contributions) on an "AS IS" BASIS,
-      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-      implied, including, without limitation, any warranties or conditions
-      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-      PARTICULAR PURPOSE. You are solely responsible for determining the
-      appropriateness of using or redistributing the Work and assume any
-      risks associated with Your exercise of permissions under this License.
-
-   8. Limitation of Liability. In no event and under no legal theory,
-      whether in tort (including negligence), contract, or otherwise,
-      unless required by applicable law (such as deliberate and grossly
-      negligent acts) or agreed to in writing, shall any Contributor be
-      liable to You for damages, including any direct, indirect, special,
-      incidental, or consequential damages of any character arising as a
-      result of this License or out of the use or inability to use the
-      Work (including but not limited to damages for loss of goodwill,
-      work stoppage, computer failure or malfunction, or any and all
-      other commercial damages or losses), even if such Contributor
-      has been advised of the possibility of such damages.
-
-   9. Accepting Warranty or Additional Liability. While redistributing
-      the Work or Derivative Works thereof, You may choose to offer,
-      and charge a fee for, acceptance of support, warranty, indemnity,
-      or other liability obligations and/or rights consistent with this
-      License. However, in accepting such obligations, You may act only
-      on Your own behalf and on Your sole responsibility, not on behalf
-      of any other Contributor, and only if You agree to indemnify,
-      defend, and hold each Contributor harmless for any liability
-      incurred by, or claims asserted against, such Contributor by reason
-      of your accepting any such warranty or additional liability.
-
-   END OF TERMS AND CONDITIONS
-
diff --git a/media/jni/mediaeditor/VideoBrowserInternal.h b/media/jni/mediaeditor/VideoBrowserInternal.h
deleted file mode 100644
index f4eaab8..0000000
--- a/media/jni/mediaeditor/VideoBrowserInternal.h
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-
-#ifndef VIDEO_BROWSER_INTERNAL_H
-#define VIDEO_BROWSER_INTERNAL_H
-
-#include "VideoBrowserMain.h"
-
-#include "M4READER_Common.h"
-#include "M4DECODER_Common.h"
-
-
-#define VIDEO_BROWSER_BGR565
-
-/*---------------------------- MACROS ----------------------------*/
-#define CHECK_PTR(fct, p, err, errValue) \
-{ \
-    if (M4OSA_NULL == p) \
-    { \
-        err = errValue ; \
-        M4OSA_TRACE1_1("" #fct "(L%d): " #p " is NULL, returning " #errValue "", __LINE__) ; \
-        goto fct##_cleanUp; \
-    } \
-}
-
-#define CHECK_ERR(fct, err) \
-{ \
-    if (M4OSA_ERR_IS_ERROR(err)) \
-    { \
-        M4OSA_TRACE1_2("" #fct "(L%d): ERROR 0x%.8x returned", __LINE__,err) ; \
-        goto fct##_cleanUp; \
-    } \
-    else if (M4OSA_ERR_IS_WARNING(err)) \
-    { \
-        M4OSA_TRACE2_2("" #fct "(L%d): WARNING 0x%.8x returned", __LINE__,err) ; \
-    } \
-}
-
-#define CHECK_STATE(fct, state, pC) \
-{ \
-    if (state != pC->m_state) \
-    { \
-        M4OSA_TRACE1_1("" #fct " called in bad state %d", pC->m_state) ; \
-        err = M4ERR_STATE ; \
-        goto fct##_cleanUp; \
-    } \
-}
-
-#define SAFE_FREE(p) \
-{ \
-    if (M4OSA_NULL != p) \
-    { \
-        free(p) ; \
-        p = M4OSA_NULL ; \
-    } \
-}
-
-/*--- Video Browser state ---*/
-typedef enum
-{
-    VideoBrowser_kVBCreating,
-    VideoBrowser_kVBOpened,
-    VideoBrowser_kVBBrowsing
-} VideoBrowser_videoBrowerState;
-
-
-/*--- Video Browser execution context. ---*/
-typedef struct
-{
-    VideoBrowser_videoBrowerState       m_state ;
-    VideoBrowser_videoBrowerDrawMode    m_drawmode;
-
-    M4OSA_Context                       g_hbmp2;
-    M4OSA_Context                       dc;
-    M4OSA_Int16*                        g_bmPixels2;
-
-    /*--- Reader parameters ---*/
-    M4OSA_FileReadPointer               m_fileReadPtr;
-    M4READER_GlobalInterface*           m_3gpReader ;
-    M4READER_DataInterface*             m_3gpData ;
-    M4READER_MediaType                  m_mediaType ;
-    M4OSA_Context                       m_pReaderCtx ;
-
-    M4_StreamHandler*                   m_pStreamHandler ;
-    M4_AccessUnit                       m_accessUnit ;
-
-    /*--- Decoder parameters ---*/
-    M4DECODER_VideoInterface*           m_pDecoder ;
-    M4OSA_Context                       m_pDecoderCtx ;
-
-    /*--- Common display parameters ---*/
-    M4OSA_UInt32                        m_x ;
-    M4OSA_UInt32                        m_y ;
-    M4VIFI_ImagePlane                   m_outputPlane[3] ;
-
-    /*--- Current browsing time ---*/
-    M4OSA_UInt32                        m_currentCTS ;
-
-    /*--- Platform dependent display parameters ---*/
-    M4OSA_Context                       m_pCoreContext ;
-
-    /*--- Callback function settings ---*/
-    videoBrowser_Callback               m_pfCallback;
-    M4OSA_Void*                         m_pCallbackUserData;
-
-    /*--- Codec Loader core context ---*/
-    M4OSA_Context                       m_pCodecLoaderContext;
-
-    /*--- Required color type ---*/
-    VideoBrowser_VideoColorType         m_frameColorType;
-
-} VideoBrowserContext;
-
-#endif /* VIDEO_BROWSER_INTERNAL_H */
diff --git a/media/jni/mediaeditor/VideoBrowserMain.c b/media/jni/mediaeditor/VideoBrowserMain.c
deleted file mode 100644
index c6c6000..0000000
--- a/media/jni/mediaeditor/VideoBrowserMain.c
+++ /dev/null
@@ -1,562 +0,0 @@
-/*
- * Copyright (C) 2011 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 "VideoEditorVideoDecoder.h"
-#include "VideoEditor3gpReader.h"
-
-#include <utils/Log.h>
-#include "VideoBrowserInternal.h"
-#include "LVOSA_FileReader_optim.h"
-
-//#define M4OSA_TRACE_LEVEL 1
-#if (M4OSA_TRACE_LEVEL >= 1)
-#undef M4OSA_TRACE1_0
-#undef M4OSA_TRACE1_1
-#undef M4OSA_TRACE1_2
-#undef M4OSA_TRACE1_3
-
-#define M4OSA_TRACE1_0(a)       __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a);
-#define M4OSA_TRACE1_1(a,b)     __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b);
-#define M4OSA_TRACE1_2(a,b,c)   __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c);
-#define M4OSA_TRACE1_3(a,b,c,d) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c,d);
-#endif
-
-/******************************************************************************
- * M4OSA_ERR     videoBrowserSetWindow(
- *          M4OSA_Context pContext, M4OSA_UInt32 x,
- *          M4OSA_UInt32 y, M4OSA_UInt32 dx, M4OSA_UInt32 dy);
- * @brief        This function sets the size and the position of the display.
- * @param        pContext       (IN) : Video Browser context
- * @param        pPixelArray    (IN) : Array to hold the video frame.
- * @param        x              (IN) : Horizontal position of the top left
- *                                     corner
- * @param        y              (IN) : Vertical position of the top left corner
- * @param        dx             (IN) : Width of the display window
- * @param        dy             (IN) : Height of the video window
- * @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
- ******************************************************************************/
-M4OSA_ERR videoBrowserSetWindow(
-        M4OSA_Context pContext,
-        M4OSA_Int32 *pPixelArray,
-        M4OSA_UInt32 x, M4OSA_UInt32 y,
-        M4OSA_UInt32 dx, M4OSA_UInt32 dy)
-{
-    VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
-    M4OSA_ERR err = M4NO_ERROR;
-
-    M4OSA_TRACE2_5("videoBrowserSetWindow: entering with 0x%x %d %d %d %d ",
-            pContext, x, y, dx, dy);
-
-    /*--- Sanity checks ---*/
-    CHECK_PTR(videoBrowserSetWindow, pContext, err, M4ERR_PARAMETER);
-    CHECK_PTR(videoBrowserSetWindow, pPixelArray, err, M4ERR_PARAMETER);
-    CHECK_STATE(videoBrowserSetWindow, VideoBrowser_kVBOpened, pC);
-
-    pC->m_outputPlane[0].u_topleft = 0;
-
-    pC->m_outputPlane[0].u_height = dy;
-    pC->m_outputPlane[0].u_width = dx;
-    pC->m_x = x;
-    pC->m_y = y;
-
-    if (pC->m_frameColorType == VideoBrowser_kGB565) {
-        pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width << 1;
-        pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(
-            pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height,
-            VIDEOBROWSER, (M4OSA_Char *)"output plane");
-
-        CHECK_PTR(videoBrowserSetWindow,
-            pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
-    }
-    else if (pC->m_frameColorType == VideoBrowser_kYUV420) {
-        pC->m_outputPlane[0].u_stride = pC->m_outputPlane[0].u_width;
-        pC->m_outputPlane[1].u_height = pC->m_outputPlane[0].u_height >> 1;
-        pC->m_outputPlane[1].u_width = pC->m_outputPlane[0].u_width >> 1;
-        pC->m_outputPlane[1].u_topleft = 0;
-        pC->m_outputPlane[1].u_stride = pC->m_outputPlane[1].u_width;
-
-        pC->m_outputPlane[2].u_height = pC->m_outputPlane[0].u_height >> 1;
-        pC->m_outputPlane[2].u_width = pC->m_outputPlane[0].u_width >> 1;
-        pC->m_outputPlane[2].u_topleft = 0;
-        pC->m_outputPlane[2].u_stride = pC->m_outputPlane[2].u_width;
-
-        pC->m_outputPlane[0].pac_data = (M4OSA_UInt8*)pPixelArray;
-
-        CHECK_PTR(videoBrowserSetWindow,
-            pC->m_outputPlane[0].pac_data, err, M4ERR_ALLOC);
-
-        pC->m_outputPlane[1].pac_data =
-            pC->m_outputPlane[0].pac_data +
-            (pC->m_outputPlane[0].u_stride * pC->m_outputPlane[0].u_height);
-
-        pC->m_outputPlane[2].pac_data =
-            pC->m_outputPlane[1].pac_data +
-            (pC->m_outputPlane[1].u_stride * pC->m_outputPlane[1].u_height);
-    }
-
-
-    M4OSA_TRACE2_0("videoBrowserSetWindow returned NO ERROR");
-    return M4NO_ERROR;
-
-videoBrowserSetWindow_cleanUp:
-
-    M4OSA_TRACE2_1("videoBrowserSetWindow returned 0x%x", err);
-    return err;
-}
-
-/******************************************************************************
-* @brief  This function allocates the resources needed for browsing a video file
-* @param   ppContext     (OUT): Pointer on a context filled by this function.
-* @param   pURL          (IN) : Path of File to browse
-* @param   DrawMode      (IN) : Indicate which method is used to draw (Direct draw etc...)
-* @param   pfCallback    (IN) : Callback function to be called when a frame must be displayed
-* @param   pCallbackData (IN) : User defined data that will be passed as parameter of the callback
-* @param   clrType       (IN) : Required color type.
-* @return  M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserCreate(
-        M4OSA_Context* ppContext,
-        M4OSA_Char* pURL,
-        M4OSA_UInt32 DrawMode,
-        M4OSA_FileReadPointer* ptrF,
-        videoBrowser_Callback pfCallback,
-        M4OSA_Void* pCallbackData,
-        VideoBrowser_VideoColorType clrType)
-{
-    VideoBrowserContext* pContext = M4OSA_NULL;
-    M4READER_MediaFamily mediaFamily = M4READER_kMediaFamilyUnknown;
-    M4_StreamHandler* pStreamHandler = M4OSA_NULL;
-    M4_VideoStreamHandler* pVideoStreamHandler = M4OSA_NULL;
-    M4DECODER_VideoType decoderType;
-    M4DECODER_OutputFilter FilterOption;
-
-    M4OSA_Bool deb = M4OSA_TRUE;
-    M4OSA_ERR err = M4NO_ERROR;
-
-    M4OSA_TRACE1_2(
-        "videoBrowserCreate: entering with 0x%x 0x%x", ppContext, pURL);
-
-    /*--- Sanity checks ---*/
-    CHECK_PTR(videoBrowserCreate, ppContext, err, M4ERR_PARAMETER);
-    *ppContext = M4OSA_NULL ;
-    CHECK_PTR(videoBrowserCreate, pURL,  err, M4ERR_PARAMETER);
-
-    /*--- Create context ---*/
-    pContext = (VideoBrowserContext*)M4OSA_32bitAlignedMalloc(
-            sizeof(VideoBrowserContext),
-            VIDEOBROWSER, (M4OSA_Char*)"Video browser context");
-
-    CHECK_PTR(videoBrowserCreate, pContext,err, M4ERR_ALLOC);
-    memset((void *)pContext, 0,sizeof(VideoBrowserContext));
-
-    /*--- Initialize the context parameters ---*/
-    pContext->m_state = VideoBrowser_kVBCreating ;
-    pContext->m_frameColorType = clrType;
-
-    /*--- Copy the file reader functions ---*/
-    memcpy((void *)&pContext->m_fileReadPtr,
-                 (void *)ptrF,
-                 sizeof(M4OSA_FileReadPointer)) ;
-
-    /* PR#SP00013 DGR bug 13 : first frame is not visible */
-    pContext->m_drawmode = DrawMode;
-
-
-    /* Retrieve the 3gp reader interface */
-    VideoEditor3gpReader_getInterface(&pContext->m_mediaType,
-        &pContext->m_3gpReader, &pContext->m_3gpData);
-
-    CHECK_PTR(videoBrowserCreate, pContext->m_3gpReader,  err, M4ERR_ALLOC);
-    CHECK_PTR(videoBrowserCreate, pContext->m_3gpData,    err, M4ERR_ALLOC);
-
-    /*--- Create the file reader ---*/
-    err = pContext->m_3gpReader->m_pFctCreate(&pContext->m_pReaderCtx);
-    CHECK_ERR(videoBrowserCreate, err);
-    CHECK_PTR(videoBrowserCreate, pContext->m_pReaderCtx, err, M4ERR_ALLOC);
-    pContext->m_3gpData->m_readerContext = pContext->m_pReaderCtx;
-
-    /*--- Set the OSAL file reader functions ---*/
-    err = pContext->m_3gpReader->m_pFctSetOption(
-            pContext->m_pReaderCtx,
-            M4READER_kOptionID_SetOsaFileReaderFctsPtr,
-            (M4OSA_DataOption)(&pContext->m_fileReadPtr));
-
-    CHECK_ERR(videoBrowserCreate, err) ;
-
-    /*--- Open the file ---*/
-    err = pContext->m_3gpReader->m_pFctOpen(pContext->m_pReaderCtx, pURL);
-    CHECK_ERR(videoBrowserCreate, err) ;
-
-    /*--- Try to find a video stream ---*/
-    while (err == M4NO_ERROR)
-    {
-        err = pContext->m_3gpReader->m_pFctGetNextStream(
-                pContext->m_pReaderCtx, &mediaFamily, &pStreamHandler);
-
-        /*in case we found a bifs stream or something else...*/
-        if ((err == (M4OSA_UInt32)M4ERR_READER_UNKNOWN_STREAM_TYPE) ||
-            (err == (M4OSA_UInt32)M4WAR_TOO_MUCH_STREAMS))
-        {
-            err = M4NO_ERROR;
-            continue;
-        }
-
-        if (err != M4WAR_NO_MORE_STREAM)
-        {
-            if (M4READER_kMediaFamilyVideo != mediaFamily)
-            {
-                err = M4NO_ERROR;
-                continue;
-            }
-
-            pContext->m_pStreamHandler = pStreamHandler;
-
-            err = pContext->m_3gpReader->m_pFctReset(
-                    pContext->m_pReaderCtx, pContext->m_pStreamHandler);
-
-            CHECK_ERR(videoBrowserCreate, err);
-
-            err = pContext->m_3gpReader->m_pFctFillAuStruct(
-                    pContext->m_pReaderCtx,
-                    pContext->m_pStreamHandler,
-                    &pContext->m_accessUnit);
-
-            CHECK_ERR(videoBrowserCreate, err);
-
-            pVideoStreamHandler =
-                (M4_VideoStreamHandler*)pContext->m_pStreamHandler;
-
-            switch (pContext->m_pStreamHandler->m_streamType)
-            {
-                case M4DA_StreamTypeVideoMpeg4:
-                case M4DA_StreamTypeVideoH263:
-                {
-                    pContext->m_pCodecLoaderContext = M4OSA_NULL;
-                    decoderType = M4DECODER_kVideoTypeMPEG4;
-
-#ifdef USE_SOFTWARE_DECODER
-                        err = VideoEditorVideoDecoder_getSoftwareInterface_MPEG4(
-                            &decoderType, &pContext->m_pDecoder);
-#else
-                        err = VideoEditorVideoDecoder_getInterface_MPEG4(
-                            &decoderType, (void **)&pContext->m_pDecoder);
-#endif
-                    CHECK_ERR(videoBrowserCreate, err) ;
-
-                    err = pContext->m_pDecoder->m_pFctCreate(
-                            &pContext->m_pDecoderCtx,
-                            pContext->m_pStreamHandler,
-                            pContext->m_3gpReader,
-                            pContext->m_3gpData,
-                            &pContext->m_accessUnit,
-                            pContext->m_pCodecLoaderContext) ;
-
-                    CHECK_ERR(videoBrowserCreate, err) ;
-                }
-                break;
-
-                case M4DA_StreamTypeVideoMpeg4Avc:
-                {
-                    pContext->m_pCodecLoaderContext = M4OSA_NULL;
-
-                    decoderType = M4DECODER_kVideoTypeAVC;
-
-#ifdef USE_SOFTWARE_DECODER
-                        err = VideoEditorVideoDecoder_getSoftwareInterface_H264(
-                            &decoderType, &pContext->m_pDecoder);
-#else
-                        err = VideoEditorVideoDecoder_getInterface_H264(
-                            &decoderType, (void **)&pContext->m_pDecoder);
-#endif
-                   CHECK_ERR(videoBrowserCreate, err) ;
-
-                    err = pContext->m_pDecoder->m_pFctCreate(
-                            &pContext->m_pDecoderCtx,
-                            pContext->m_pStreamHandler,
-                            pContext->m_3gpReader,
-                            pContext->m_3gpData,
-                            &pContext->m_accessUnit,
-                            pContext->m_pCodecLoaderContext) ;
-
-                    CHECK_ERR(videoBrowserCreate, err) ;
-                }
-                break;
-
-                default:
-                    err = M4ERR_VB_MEDIATYPE_NOT_SUPPORTED;
-                    goto videoBrowserCreate_cleanUp;
-            }
-        }
-    }
-
-    if (err == M4WAR_NO_MORE_STREAM)
-    {
-        err = M4NO_ERROR ;
-    }
-
-    if (M4OSA_NULL == pContext->m_pStreamHandler)
-    {
-        err = M4ERR_VB_NO_VIDEO ;
-        goto videoBrowserCreate_cleanUp ;
-    }
-
-    err = pContext->m_pDecoder->m_pFctSetOption(
-            pContext->m_pDecoderCtx,
-            M4DECODER_kOptionID_DeblockingFilter,
-            (M4OSA_DataOption)&deb);
-
-    if (err == M4WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED)
-    {
-        err = M4NO_ERROR;
-    }
-    CHECK_ERR(videoBrowserCreate, err);
-
-    FilterOption.m_pFilterUserData = M4OSA_NULL;
-
-
-    if (pContext->m_frameColorType == VideoBrowser_kGB565) {
-        FilterOption.m_pFilterFunction =
-            (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toBGR565;
-    }
-    else if (pContext->m_frameColorType == VideoBrowser_kYUV420) {
-        FilterOption.m_pFilterFunction =
-            (M4OSA_Void*)M4VIFI_ResizeBilinearYUV420toYUV420;
-    }
-    else {
-        err = M4ERR_PARAMETER;
-        goto videoBrowserCreate_cleanUp;
-    }
-
-    err = pContext->m_pDecoder->m_pFctSetOption(
-            pContext->m_pDecoderCtx,
-            M4DECODER_kOptionID_OutputFilter,
-            (M4OSA_DataOption)&FilterOption);
-
-    CHECK_ERR(videoBrowserCreate, err);
-
-    /* store the callback details */
-    pContext->m_pfCallback = pfCallback;
-    pContext->m_pCallbackUserData = pCallbackData;
-    /* store the callback details */
-
-    pContext->m_state = VideoBrowser_kVBOpened;
-    *ppContext = pContext;
-
-    M4OSA_TRACE1_0("videoBrowserCreate returned NO ERROR");
-    return M4NO_ERROR;
-
-videoBrowserCreate_cleanUp:
-
-    if (M4OSA_NULL != pContext)
-    {
-        if (M4OSA_NULL != pContext->m_pDecoderCtx)
-        {
-            pContext->m_pDecoder->m_pFctDestroy(pContext->m_pDecoderCtx);
-            pContext->m_pDecoderCtx = M4OSA_NULL;
-        }
-
-        if (M4OSA_NULL != pContext->m_pReaderCtx)
-        {
-            pContext->m_3gpReader->m_pFctClose(pContext->m_pReaderCtx);
-            pContext->m_3gpReader->m_pFctDestroy(pContext->m_pReaderCtx);
-            pContext->m_pReaderCtx = M4OSA_NULL;
-        }
-        SAFE_FREE(pContext->m_pDecoder);
-        SAFE_FREE(pContext->m_3gpReader);
-        SAFE_FREE(pContext->m_3gpData);
-        SAFE_FREE(pContext);
-    }
-
-    M4OSA_TRACE2_1("videoBrowserCreate returned 0x%x", err);
-    return err;
-}
-
-/******************************************************************************
-* M4OSA_ERR     videoBrowserCleanUp(M4OSA_Context pContext);
-* @brief        This function frees the resources needed for browsing a
-*               video file.
-* @param        pContext     (IN) : Video browser context
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE
-******************************************************************************/
-M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext)
-{
-    VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
-    M4OSA_ERR err = M4NO_ERROR;
-
-    M4OSA_TRACE2_1("videoBrowserCleanUp: entering with 0x%x", pContext);
-
-    /*--- Sanity checks ---*/
-    CHECK_PTR(videoBrowserCleanUp, pContext, err, M4ERR_PARAMETER);
-
-    if (M4OSA_NULL != pC->m_pDecoderCtx)
-    {
-        pC->m_pDecoder->m_pFctDestroy(pC->m_pDecoderCtx);
-        pC->m_pDecoderCtx = M4OSA_NULL ;
-    }
-
-    if (M4OSA_NULL != pC->m_pReaderCtx)
-    {
-        pC->m_3gpReader->m_pFctClose(pC->m_pReaderCtx) ;
-        pC->m_3gpReader->m_pFctDestroy(pC->m_pReaderCtx);
-        pC->m_pReaderCtx = M4OSA_NULL;
-    }
-
-    SAFE_FREE(pC->m_pDecoder);
-    SAFE_FREE(pC->m_3gpReader);
-    SAFE_FREE(pC->m_3gpData);
-
-    if (pC->m_frameColorType != VideoBrowser_kYUV420) {
-        SAFE_FREE(pC->m_outputPlane[0].pac_data);
-    }
-    SAFE_FREE(pC);
-
-    M4OSA_TRACE2_0("videoBrowserCleanUp returned NO ERROR");
-    return M4NO_ERROR;
-
-videoBrowserCleanUp_cleanUp:
-
-    M4OSA_TRACE2_1("videoBrowserCleanUp returned 0x%x", err);
-    return err;
-}
-/******************************************************************************
-* M4OSA_ERR     videoBrowserPrepareFrame(
-*       M4OSA_Context pContext, M4OSA_UInt32* pTime);
-* @brief        This function prepares the frame.
-* @param        pContext     (IN) : Video browser context
-* @param        pTime        (IN/OUT) : Pointer on the time to reach. Updated
-*                                       by this function with the reached time
-* @param        tolerance    (IN) :  We may decode an earlier frame within the tolerance.
-*                                    The time difference is specified in milliseconds.
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime,
-    M4OSA_UInt32 tolerance)
-{
-    VideoBrowserContext* pC = (VideoBrowserContext*)pContext;
-    M4OSA_ERR err = M4NO_ERROR;
-    M4OSA_UInt32 targetTime = 0;
-    M4_MediaTime timeMS = 0;
-    M4OSA_Bool bJumpNeeded = M4OSA_FALSE;
-
-    /*--- Sanity checks ---*/
-    CHECK_PTR(videoBrowserPrepareFrame, pContext, err, M4ERR_PARAMETER);
-    CHECK_PTR(videoBrowserPrepareFrame, pTime,  err, M4ERR_PARAMETER);
-
-    targetTime = *pTime ;
-
-    /*--- Check the state, if this is the first call to this function
-          we move to the state "browsing" ---*/
-    if (VideoBrowser_kVBOpened == pC->m_state)
-    {
-        pC->m_state = VideoBrowser_kVBBrowsing;
-    }
-    else if (VideoBrowser_kVBBrowsing != pC->m_state)
-    {
-        err = M4ERR_STATE ;
-        goto videoBrowserPrepareFrame_cleanUp;
-    }
-
-    // If we jump backward or forward to a time greater than current position by
-    // 85ms (~ 2 frames), we want to jump.
-    if (pC->m_currentCTS == 0 ||
-        targetTime < pC->m_currentCTS ||
-        targetTime > (pC->m_currentCTS + 85))
-    {
-        bJumpNeeded = M4OSA_TRUE;
-    }
-
-    timeMS = (M4_MediaTime)targetTime;
-    err = pC->m_pDecoder->m_pFctDecode(
-        pC->m_pDecoderCtx, &timeMS, bJumpNeeded, tolerance);
-
-    if ((err != M4NO_ERROR) && (err != M4WAR_NO_MORE_AU))
-    {
-        return err;
-    }
-
-    err = pC->m_pDecoder->m_pFctRender(
-        pC->m_pDecoderCtx, &timeMS, pC->m_outputPlane, M4OSA_TRUE);
-
-    if (M4WAR_VIDEORENDERER_NO_NEW_FRAME == err)
-    {
-        return err;
-    }
-    CHECK_ERR(videoBrowserPrepareFrame, err) ;
-
-    pC->m_currentCTS = (M4OSA_UInt32)timeMS;
-
-    *pTime = pC->m_currentCTS;
-
-    return M4NO_ERROR;
-
-videoBrowserPrepareFrame_cleanUp:
-
-    if ((M4WAR_INVALID_TIME == err) || (M4WAR_NO_MORE_AU == err))
-    {
-        err = M4NO_ERROR;
-    }
-    else if (M4OSA_NULL != pC)
-    {
-        pC->m_currentCTS = 0;
-    }
-
-    M4OSA_TRACE2_1("videoBrowserPrepareFrame returned 0x%x", err);
-    return err;
-}
-
-/******************************************************************************
-* M4OSA_ERR     videoBrowserDisplayCurrentFrame(M4OSA_Context pContext);
-* @brief        This function displays the current frame.
-* @param        pContext     (IN) : Video browser context
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext)
-{
-    VideoBrowserContext* pC = (VideoBrowserContext*)pContext ;
-    M4OSA_ERR err = M4NO_ERROR ;
-
-    /*--- Sanity checks ---*/
-    CHECK_PTR(videoBrowserDisplayCurrentFrame, pContext, err, M4ERR_PARAMETER);
-
-    // Request display of the frame
-    pC->m_pfCallback((M4OSA_Context) pC,             // VB context
-        VIDEOBROWSER_DISPLAY_FRAME,                  // action requested
-        M4NO_ERROR,                                  // error code
-        (M4OSA_Void*) &(pC->m_outputPlane[0]),       // image to be displayed
-        (M4OSA_Void*) pC->m_pCallbackUserData);      // user-provided data
-
-#ifdef DUMPTOFILE
-    {
-        M4OSA_Context fileContext;
-        M4OSA_Char* fileName = "/sdcard/textBuffer_RGB565.rgb";
-        M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,
-            M4OSA_kFileWrite | M4OSA_kFileCreate);
-
-        M4OSA_fileWriteData(fileContext,
-            (M4OSA_MemAddr8) pC->m_outputPlane[0].pac_data,
-            pC->m_outputPlane[0].u_height*pC->m_outputPlane[0].u_width*2);
-
-        M4OSA_fileWriteClose(fileContext);
-    }
-#endif
-
-    M4OSA_TRACE2_0("videoBrowserDisplayCurrentFrame returned NO ERROR") ;
-    return M4NO_ERROR;
-
-videoBrowserDisplayCurrentFrame_cleanUp:
-
-    M4OSA_TRACE2_1("videoBrowserDisplayCurrentFrame returned 0x%x", err) ;
-    return err;
-}
diff --git a/media/jni/mediaeditor/VideoBrowserMain.h b/media/jni/mediaeditor/VideoBrowserMain.h
deleted file mode 100644
index 00b5e05..0000000
--- a/media/jni/mediaeditor/VideoBrowserMain.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-
-#ifndef VIDEO_BROWSER_MAIN_H
-#define VIDEO_BROWSER_MAIN_H
-
-/**
- ************************************************************************
- * @file    VideoBrowserMain.h
- * @brief   Video browser Interface functions
- ************************************************************************
-*/
-
-#define VIDEOBROWSER    0x423
-
-#include "M4OSA_Memory.h"
-#include "M4OSA_CharStar.h"
-#include "M4OSA_OptionID.h"
-#include "M4OSA_Debug.h"
-#include "M4VIFI_FiltersAPI.h"
-#include "M4OSA_FileReader.h"
-
-
-/**
- ************************************************************************
- * @brief    Error codes definition.
- * @note    These value are the Browser engine specific error codes.
- ************************************************************************
-*/
-#define M4ERR_VB_MEDIATYPE_NOT_SUPPORTED    M4OSA_ERR_CREATE(M4_ERR, VIDEOBROWSER, 0x01)
-#define M4ERR_VB_NO_VIDEO                   M4OSA_ERR_CREATE(M4_ERR, VIDEOBROWSER, 0x02)
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- *  Video Browser draw mode, extension for angle based bliting can be done
- */
-typedef enum
-{
-    VideoBrowser_kVBNormalBliting
-} VideoBrowser_videoBrowerDrawMode;
-
-
-/*--- Video Browser output frame color type ---*/
-typedef enum
-{
-    VideoBrowser_kYUV420,
-    VideoBrowser_kGB565
-} VideoBrowser_VideoColorType;
-
-/**
- ************************************************************************
- * enumeration  VideoBrowser_Notification
- * @brief       Video Browser notification type.
- * @note        This callback mechanism must be used to wait the completion of an asynchronous
- * operation, before calling another API function.
- ************************************************************************
-*/
-typedef enum
-{
-    /**
-     * A frame is ready to be displayed, it should be displayed in the callback function
-     * pCbData type = M4VIFI_ImagePlane*
-     */
-    VIDEOBROWSER_DISPLAY_FRAME            = 0x00000001,
-    VIDEOBROWSER_NOTIFICATION_NONE        = 0xffffffff
-}VideoBrowser_Notification;
-
-
-/**
- ************************************************************************
- * @brief    videoBrowser_Callback type definition
- * @param    pInstance          (IN) Video Browser context.
- * @param    notificationID     (IN) Id of the callback which generated the error
- * @param    errCode            (IN) Error code from the core
- * @param    pCbData            (IN) pointer to data associated wit the callback.
- * @param    pCbUserData        (IN) pointer to application user data passed in init.
- * @note    This callback mechanism is used to request display of an image
- ************************************************************************
-*/
-typedef M4OSA_Void (*videoBrowser_Callback) (M4OSA_Context pInstance,
-                                        VideoBrowser_Notification notificationID,
-                                        M4OSA_ERR errCode,
-                                        M4OSA_Void* pCbData,
-                                        M4OSA_Void* pCallbackUserData);
-
-
-/******************************************************************************
-* @brief   This function allocates the resources needed for browsing a video file.
-* @param   ppContext     (OUT): Pointer on a context filled by this function.
-* @param   pURL          (IN) : Path of File to browse
-* @param   DrawMode      (IN) : Indicate which method is used to draw (Direct draw etc...)
-* @param   pfCallback    (IN) : Callback function to be called when a frame must be displayed
-* @param   pCallbackData (IN)  : User defined data that will be passed as parameter of the callback
-* @param   clrType       (IN) : Required color type.
-* @return  M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserCreate(M4OSA_Context* ppContext, M4OSA_Char* pURL,
-                                        M4OSA_UInt32 DrawMode,
-                                        M4OSA_FileReadPointer* ptrF,
-                                        videoBrowser_Callback pfCallback,
-                                        M4OSA_Void* pCallbackData,
-                                        VideoBrowser_VideoColorType clrType);
-
-/******************************************************************************
-* @brief        This function frees the resources needed for browsing a video file.
-* @param        pContext     (IN) : Video browser context
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE
-******************************************************************************/
-M4OSA_ERR videoBrowserCleanUp(M4OSA_Context pContext) ;
-
-
-/******************************************************************************
-* @brief        This function allocates the resources needed for browsing a video file.
-* @param        pContext  (IN)      : Video browser context
-* @param        pTime     (IN/OUT)  : Pointer on the time to reach. Updated by
-*                                     this function with the reached time
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserPrepareFrame(M4OSA_Context pContext, M4OSA_UInt32* pTime,
-        M4OSA_UInt32 tolerance);
-
-/******************************************************************************
-* @brief        This function sets the size and the position of the display.
-* @param        pContext     (IN) : Video Browser context
-* @param        pixelArray   (IN) : Array to hold the video frame.
-* @param        x            (IN) : Horizontal position of the top left corner
-* @param        y            (IN) : Vertical position of the top left corner
-* @param        dx           (IN) : Width of the display window
-* @param        dy           (IN) : Height of the video window
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserSetWindow(M4OSA_Context pContext, M4OSA_Int32* pixelArray,
-                                M4OSA_UInt32 x, M4OSA_UInt32 y,
-                                M4OSA_UInt32 dx, M4OSA_UInt32 dy);
-
-/******************************************************************************
-* @brief        This function displays the current frame.
-* @param        pContext     (IN) : Video browser context
-* @return       M4NO_ERROR / M4ERR_PARAMETER / M4ERR_STATE / M4ERR_ALLOC
-******************************************************************************/
-M4OSA_ERR videoBrowserDisplayCurrentFrame(M4OSA_Context pContext);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* VIDEO_BROWSER_MAIN_H */
diff --git a/media/jni/mediaeditor/VideoEditorClasses.cpp b/media/jni/mediaeditor/VideoEditorClasses.cpp
deleted file mode 100644
index d29fad3..0000000
--- a/media/jni/mediaeditor/VideoEditorClasses.cpp
+++ /dev/null
@@ -1,3146 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorClasses"
-
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Debug.h>
-#include <M4OSA_Thread.h>
-#include <M4VSS3GPP_API.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4DECODER_Common.h>
-};
-
-#define VIDEOEDIT_PROP_JAVA_RESULT_STRING_MAX                     (128)
-
-#define VIDEOEDIT_JAVA__RESULT_STRING_MAX                     (128)
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioEffect)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",     M4VSS3GPP_kAudioEffectType_None),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_IN",  M4VSS3GPP_kAudioEffectType_FadeIn),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_OUT", M4VSS3GPP_kAudioEffectType_FadeOut)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioEffect, AUDIO_EFFECT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioFormat)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NO_AUDIO",          M4VIDEOEDITING_kNoneAudio),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("AMR_NB",            M4VIDEOEDITING_kAMR_NB),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("AAC",               M4VIDEOEDITING_kAAC),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("AAC_PLUS",          M4VIDEOEDITING_kAACplus),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ENHANCED_AAC_PLUS", M4VIDEOEDITING_keAACplus),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MP3",               M4VIDEOEDITING_kMP3),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("EVRC",              M4VIDEOEDITING_kEVRC),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PCM",               M4VIDEOEDITING_kPCM),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NULL_AUDIO",        M4VIDEOEDITING_kNullAudio),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED_AUDIO", M4VIDEOEDITING_kUnsupportedAudio)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioFormat, AUDIO_FORMAT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioSamplingFrequency)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_DEFAULT", M4VIDEOEDITING_kDefault_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_8000",    M4VIDEOEDITING_k8000_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_16000",   M4VIDEOEDITING_k16000_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_22050",   M4VIDEOEDITING_k22050_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_24000",   M4VIDEOEDITING_k24000_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_32000",   M4VIDEOEDITING_k32000_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_44100",   M4VIDEOEDITING_k44100_ASF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FREQ_48000",   M4VIDEOEDITING_k48000_ASF)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioSamplingFrequency,AUDIO_SAMPLING_FREQUENCY_CLASS_NAME,
-                                     M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(AudioTransition)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",       M4VSS3GPP_kAudioTransitionType_None),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CROSS_FADE", M4VSS3GPP_kAudioTransitionType_CrossFade)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(AudioTransition, AUDIO_TRANSITION_CLASS_NAME, M4OSA_NULL,
-                                     M4OSA_NULL)
-
-
-static const char*
-videoEditClasses_getUnknownBitrateString(int bitrate)
-{
-    static char string[VIDEOEDIT_JAVA__RESULT_STRING_MAX] = "";
-
-    M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1, (M4OSA_Char*)"%d", bitrate);
-
-    // Return the bitrate string.
-    return(string);
-}
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Bitrate)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("VARIABLE",     M4VIDEOEDITING_kVARIABLE_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("UNDEFINED",    M4VIDEOEDITING_kUndefinedBitrate),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_9_2_KBPS",  M4VIDEOEDITING_k9_2_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_12_2_KBPS", M4VIDEOEDITING_k12_2_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_16_KBPS",   M4VIDEOEDITING_k16_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_24_KBPS",   M4VIDEOEDITING_k24_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_32_KBPS",   M4VIDEOEDITING_k32_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_48_KBPS",   M4VIDEOEDITING_k48_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_64_KBPS",   M4VIDEOEDITING_k64_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_96_KBPS",   M4VIDEOEDITING_k96_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_128_KBPS",  M4VIDEOEDITING_k128_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_192_KBPS",  M4VIDEOEDITING_k192_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_256_KBPS",  M4VIDEOEDITING_k256_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_288_KBPS",  M4VIDEOEDITING_k288_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_384_KBPS",  M4VIDEOEDITING_k384_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_512_KBPS",  M4VIDEOEDITING_k512_KBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_800_KBPS",  M4VIDEOEDITING_k800_KBPS),
-/*+ New Encoder bitrates */
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_2_MBPS",  M4VIDEOEDITING_k2_MBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_5_MBPS",  M4VIDEOEDITING_k5_MBPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BR_8_MBPS",  M4VIDEOEDITING_k8_MBPS)
-/*- New Encoder bitrates */
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Bitrate, BITRATE_CLASS_NAME,
- videoEditClasses_getUnknownBitrateString, videoEditClasses_getUnknownBitrateString)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(ClipType)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("THREE_GPP",   M4VIDEOEDITING_kFileType_3GPP),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MP4",         M4VIDEOEDITING_kFileType_MP4),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("AMR",         M4VIDEOEDITING_kFileType_AMR),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MP3",         M4VIDEOEDITING_kFileType_MP3),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PCM",         M4VIDEOEDITING_kFileType_PCM),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("JPG",         M4VIDEOEDITING_kFileType_JPG),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PNG",         M4VIDEOEDITING_kFileType_PNG),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("M4V",         M4VIDEOEDITING_kFileType_M4V),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kFileType_Unsupported)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(ClipType, FILE_TYPE_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Engine)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("TASK_LOADING_SETTINGS",    TASK_LOADING_SETTINGS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("TASK_ENCODING",            TASK_ENCODING)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME, M4OSA_NULL,
-                                     M4OSA_NULL)
-
-
-static const char*
-videoEditClasses_getUnknownErrorName(int error)
-{
-    static char string[VIDEOEDIT_JAVA__RESULT_STRING_MAX] = "ERR_INTERNAL";
-
-    // Format the unknown error string.
-    M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1, (M4OSA_Char*)"ERR_INTERNAL(%s)",
-                    videoEditOsal_getResultString(error));
-
-    // Return the error string.
-    return(string);
-}
-
-static const char*
-videoEditClasses_getUnknownErrorString(int error)
-{
-    // Return the result string.
-    return(videoEditOsal_getResultString(error));
-}
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(Error)
-{
-    // M4OSA_Clock.h
-    VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_TIMESCALE_TOO_BIG",                   \
-          M4WAR_TIMESCALE_TOO_BIG                               ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_CLOCK_BAD_REF_YEAR",                  \
-          M4ERR_CLOCK_BAD_REF_YEAR                              ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FILE_NOT_FOUND",                      \
-          M4ERR_FILE_NOT_FOUND                                  ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_TRANSCODING_NECESSARY",               \
-          M4VSS3GPP_WAR_TRANSCODING_NECESSARY                   ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("WAR_MAX_OUTPUT_SIZE_EXCEEDED",            \
-          M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED                   ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BUFFER_OUT_TOO_SMALL",                \
-          M4xVSSWAR_BUFFER_OUT_TOO_SMALL                        ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NOMORE_SPACE_FOR_FILE",               \
-          M4xVSSERR_NO_MORE_SPACE                               ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_FILE_TYPE",                   \
-          M4VSS3GPP_ERR_INVALID_FILE_TYPE                       ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_EFFECT_KIND",                 \
-          M4VSS3GPP_ERR_INVALID_EFFECT_KIND                     ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_EFFECT_TYPE",           \
-          M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE               ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_AUDIO_EFFECT_TYPE",           \
-          M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE               ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_TRANSITION_TYPE",       \
-          M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE           ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_AUDIO_TRANSITION_TYPE",       \
-          M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE           ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_VIDEO_ENCODING_FRAME_RATE",   \
-          M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE       ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EXTERNAL_EFFECT_NULL",                \
-          M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL                    ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EXTERNAL_TRANSITION_NULL",            \
-          M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL                ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BEGIN_CUT_LARGER_THAN_DURATION",      \
-          M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION          ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_BEGIN_CUT_LARGER_THAN_END_CUT",       \
-          M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT           ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_OVERLAPPING_TRANSITIONS",             \
-         M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS                  ),
-#ifdef M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ANALYSIS_DATA_SIZE_TOO_SMALL",        \
-          M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL            ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_3GPP_FILE",                     \
-        M4VSS3GPP_ERR_INVALID_3GPP_FILE                         ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT",        \
-        M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT            ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT",        \
-        M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT            ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AMR_EDITING_UNSUPPORTED",               \
-        M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED                   ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_VIDEO_AU_TOO_LARGE",              \
-        M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE                  ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_AU_TOO_LARGE",              \
-        M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE                  ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_CORRUPTED_AU",              \
-        M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU                  ),
-#ifdef M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INPUT_AUDIO_CORRUPTED_AU",              \
-        M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU              ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ENCODER_ACCES_UNIT_ERROR",              \
-        M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR                  ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT",      \
-        M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT          ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_H263_PROFILE",      \
-        M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE          ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE",     \
-        M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE         ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_MPEG4_RVLC",        \
-        M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC            ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT",      \
-        M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT          ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE",   \
-        M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE       ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE",\
-     M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_CLIP_ANALYSIS_VERSION",        \
-         M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION            ),
-#ifdef M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INVALID_CLIP_ANALYSIS_PLATFORM",       \
-        M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM            ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_FORMAT",            \
-         M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT                ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE",        \
-         M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE            ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_TIME_SCALE",        \
-         M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE            ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING", \
-         M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING     ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_MP3_ASSEMBLY",             \
-         M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY                 ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NO_SUPPORTED_STREAM_IN_FILE",          \
-         M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE              ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ADDVOLUME_EQUALS_ZERO",                \
-         M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO                    ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION",    \
-         M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION        ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT",    \
-         M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT        ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_UNSUPPORTED_ADDED_AUDIO_STREAM",       \
-         M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM           ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_MIXING_UNSUPPORTED",             \
-         M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED                 ),
-#ifdef M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_MIXING_MP3_UNSUPPORTED",         \
-          M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED            ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK", \
-      M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK        ),
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_AAC",         \
-       M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC               ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_AUDIO_CANNOT_BE_MIXED",                \
-        M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED                     ),
-#ifdef M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED",        \
-         M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED            ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_FEATURE_UNSUPPORTED_WITH_EVRC",        \
-          M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC           ),
-#endif
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_H263_PROFILE_NOT_SUPPORTED",           \
-          M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED              ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE",    \
-          M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE       ),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ERR_INTERNAL",                             \
-          M4NO_ERROR                                            ),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(Error, ERROR_CLASS_NAME,
- videoEditClasses_getUnknownErrorName, videoEditClasses_getUnknownErrorString)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(FileType)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("THREE_GPP",   VideoEditClasses_kFileType_3GPP),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MP4",         VideoEditClasses_kFileType_MP4),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("AMR",         VideoEditClasses_kFileType_AMR),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MP3",         VideoEditClasses_kFileType_MP3),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PCM",         VideoEditClasses_kFileType_PCM),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("JPG",         VideoEditClasses_kFileType_JPG),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("GIF",         VideoEditClasses_kFileType_GIF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PNG",         VideoEditClasses_kFileType_PNG),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("M4V",         VideoEditClasses_kFileType_M4V),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", VideoEditClasses_kFileType_Unsupported)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(FileType, FILE_TYPE_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(MediaRendering)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("RESIZING",      M4xVSS_kResizing),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CROPPING",      M4xVSS_kCropping),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_BORDERS", M4xVSS_kBlackBorders)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(MediaRendering, MEDIA_RENDERING_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(SlideDirection)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("RIGHT_OUT_LEFT_IN", M4xVSS_SlideTransition_RightOutLeftIn),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("LEFT_OUT_RIGTH_IN", M4xVSS_SlideTransition_LeftOutRightIn),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("TOP_OUT_BOTTOM_IN", M4xVSS_SlideTransition_TopOutBottomIn),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BOTTOM_OUT_TOP_IN", M4xVSS_SlideTransition_BottomOutTopIn)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(SlideDirection, SLIDE_DIRECTION_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(TransitionBehaviour)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SPEED_UP",    M4VSS3GPP_TransitionBehaviour_SpeedUp),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("LINEAR",      M4VSS3GPP_TransitionBehaviour_Linear),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SPEED_DOWN",  M4VSS3GPP_TransitionBehaviour_SpeedDown),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SLOW_MIDDLE", M4VSS3GPP_TransitionBehaviour_SlowMiddle),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FAST_MIDDLE", M4VSS3GPP_TransitionBehaviour_FastMiddle)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(TransitionBehaviour, TRANSITION_BEHAVIOUR_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoEffect)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",            M4VSS3GPP_kVideoEffectType_None),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_FROM_BLACK", M4VSS3GPP_kVideoEffectType_FadeFromBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_TO_BLACK",   M4VSS3GPP_kVideoEffectType_FadeToBlack),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL",        M4VSS3GPP_kVideoEffectType_External),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("BLACK_AND_WHITE", M4xVSS_kVideoEffectType_BlackAndWhite),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("PINK",            M4xVSS_kVideoEffectType_Pink),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("GREEN",           M4xVSS_kVideoEffectType_Green),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SEPIA",           M4xVSS_kVideoEffectType_Sepia),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NEGATIVE",        M4xVSS_kVideoEffectType_Negative),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FRAMING",         M4xVSS_kVideoEffectType_Framing),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("TEXT",            M4xVSS_kVideoEffectType_Text),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ZOOM_IN",         M4xVSS_kVideoEffectType_ZoomIn),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ZOOM_OUT",        M4xVSS_kVideoEffectType_ZoomOut),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FIFTIES",         M4xVSS_kVideoEffectType_Fifties),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("COLORRGB16",      M4xVSS_kVideoEffectType_ColorRGB16),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("GRADIENT",        M4xVSS_kVideoEffectType_Gradient),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoEffect, VIDEO_EFFECT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFormat)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NO_VIDEO",    M4VIDEOEDITING_kNoneVideo),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("H263",        M4VIDEOEDITING_kH263),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("MPEG4",       M4VIDEOEDITING_kMPEG4),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("H264",        M4VIDEOEDITING_kH264),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NULL_VIDEO",  M4VIDEOEDITING_kNullVideo),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("UNSUPPORTED", M4VIDEOEDITING_kUnsupportedVideo),
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFormat, VIDEO_FORMAT_CLASS_NAME, M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFrameRate)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_5_FPS",    M4VIDEOEDITING_k5_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_7_5_FPS",  M4VIDEOEDITING_k7_5_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_10_FPS",   M4VIDEOEDITING_k10_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_12_5_FPS", M4VIDEOEDITING_k12_5_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_15_FPS",   M4VIDEOEDITING_k15_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_20_FPS",   M4VIDEOEDITING_k20_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_25_FPS",   M4VIDEOEDITING_k25_FPS),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FR_30_FPS",   M4VIDEOEDITING_k30_FPS)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameRate, VIDEO_FRAME_RATE_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoFrameSize)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SQCIF", M4VIDEOEDITING_kSQCIF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("QQVGA", M4VIDEOEDITING_kQQVGA),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("QCIF",  M4VIDEOEDITING_kQCIF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("QVGA",  M4VIDEOEDITING_kQVGA),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CIF",   M4VIDEOEDITING_kCIF),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("VGA",   M4VIDEOEDITING_kVGA),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA", M4VIDEOEDITING_kWVGA),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NTSC", M4VIDEOEDITING_kNTSC),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("nHD", M4VIDEOEDITING_k640_360),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("WVGA16x9", M4VIDEOEDITING_k854_480),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("V720p", M4VIDEOEDITING_k1280_720),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("W720p", M4VIDEOEDITING_k1080_720),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("S720p", M4VIDEOEDITING_k960_720),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("V1080p", M4VIDEOEDITING_k1920_1080)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoFrameSize, VIDEO_FRAME_SIZE_CLASS_NAME,
- M4OSA_NULL, M4OSA_NULL)
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANTS(VideoTransition)
-{
-    VIDEOEDIT_JAVA_CONSTANT_INIT("NONE",             M4VSS3GPP_kVideoTransitionType_None),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("CROSS_FADE",       M4VSS3GPP_kVideoTransitionType_CrossFade),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("EXTERNAL",         M4VSS3GPP_kVideoTransitionType_External),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("ALPHA_MAGIC",      M4xVSS_kVideoTransitionType_AlphaMagic),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("SLIDE_TRANSITION", M4xVSS_kVideoTransitionType_SlideTransition),
-    VIDEOEDIT_JAVA_CONSTANT_INIT("FADE_BLACK",       M4xVSS_kVideoTransitionType_FadeBlack)
-};
-
-VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(VideoTransition, VIDEO_TRANSITION_CLASS_NAME,
-                                     M4OSA_NULL, M4OSA_NULL)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(AlphaMagic)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("file",            "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("blendingPercent", "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("invertRotation",  "Z"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rgbWidth",  "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rgbHeight",  "I"                 )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(AlphaMagic, ALPHA_MAGIC_SETTINGS_CLASS_NAME)
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Properties)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("duration",               "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("fileType",               "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFormat",            "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoDuration",          "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoBitrate",           "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("width",                  "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("height",                 "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("averageFrameRate",       "F"),
-    VIDEOEDIT_JAVA_FIELD_INIT("profile",                "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("level",                  "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("profileSupported",       "Z"),
-    VIDEOEDIT_JAVA_FIELD_INIT("levelSupported",         "Z"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioFormat",            "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioDuration",          "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioBitrate",           "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioChannels",          "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioSamplingFrequency", "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoRotation",          "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Properties, PROPERTIES_CLASS_NAME)
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(BackgroundMusic)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("file",          "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("fileType",      "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("insertionTime", "J"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("volumePercent", "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("beginLoop",     "J"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("endLoop",       "J"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("enableDucking",   "Z"               ),
-    VIDEOEDIT_JAVA_FIELD_INIT("duckingThreshold","I"               ),
-    VIDEOEDIT_JAVA_FIELD_INIT("lowVolume",         "I"             ),
-    VIDEOEDIT_JAVA_FIELD_INIT("isLooping",         "Z"             )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(BackgroundMusic, BACKGROUND_MUSIC_SETTINGS_CLASS_NAME)
-
-/*
-VIDEOEDIT_JAVA_DEFINE_FIELDS(BestEditSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFormat",    "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFrameSize", "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioFormat",    "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioChannels",  "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(BestEditSettings, BEST_EDIT_SETTINGS_CLASS_NAME)
-*/
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(ClipSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("clipPath",             "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("fileType",             "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("beginCutTime",         "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("endCutTime",           "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("beginCutPercent",      "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("endCutPercent",        "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomEnabled",       "Z"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomPercentStart",  "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftXStart", "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftYStart", "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomPercentEnd",    "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftXEnd",   "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("panZoomTopLeftYEnd",   "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("mediaRendering",       "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rgbWidth",           "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rgbHeight",          "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rotationDegree",     "I"                 )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(ClipSettings, CLIP_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(EditSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("clipSettingsArray",       "[L"CLIP_SETTINGS_CLASS_NAME";"         ),
-    VIDEOEDIT_JAVA_FIELD_INIT("transitionSettingsArray", "[L"TRANSITION_SETTINGS_CLASS_NAME";"   ),
-    VIDEOEDIT_JAVA_FIELD_INIT("effectSettingsArray",     "[L"EFFECT_SETTINGS_CLASS_NAME";"       ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFrameRate",          "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("outputFile",              "Ljava/lang/String;"                    ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFrameSize",          "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoFormat",             "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoProfile",            "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoLevel",              "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioFormat",             "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioSamplingFreq",       "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("maxFileSize",             "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioChannels",           "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoBitrate",            "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioBitrate",            "I"                                     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("backgroundMusicSettings",\
-    "L"BACKGROUND_MUSIC_SETTINGS_CLASS_NAME";"),
-    VIDEOEDIT_JAVA_FIELD_INIT("primaryTrackVolume",            "I"                               )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(EditSettings, EDIT_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(EffectSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("startTime",                       "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("duration",                        "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoEffectType",                 "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioEffectType",                 "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("startPercent",                    "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("durationPercent",                 "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("framingFile",                     "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("framingBuffer",                   "[I"                ),
-    VIDEOEDIT_JAVA_FIELD_INIT("bitmapType",                      "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("width",                           "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("height",                          "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("topLeftX",                        "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("topLeftY",                        "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("framingResize",                   "Z"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("framingScaledSize",               "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("text",                            "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("textRenderingData",               "Ljava/lang/String;"),
-    VIDEOEDIT_JAVA_FIELD_INIT("textBufferWidth",                 "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("textBufferHeight",                "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("fiftiesFrameRate",                "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("rgb16InputColor",                 "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingStartPercent",       "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingMiddlePercent",      "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingEndPercent",         "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingFadeInTimePercent",  "I"                 ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaBlendingFadeOutTimePercent", "I"                 )
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(EffectSettings, EFFECT_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Engine)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("mManualEditContext", "J")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(SlideTransitionSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("direction", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(SlideTransitionSettings, SLIDE_TRANSITION_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(TransitionSettings)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("duration",            "I"                                       ),
-    VIDEOEDIT_JAVA_FIELD_INIT("videoTransitionType", "I"                                       ),
-    VIDEOEDIT_JAVA_FIELD_INIT("audioTransitionType", "I"                                       ),
-    VIDEOEDIT_JAVA_FIELD_INIT("transitionBehaviour", "I"                                       ),
-    VIDEOEDIT_JAVA_FIELD_INIT("alphaSettings",       "L"ALPHA_MAGIC_SETTINGS_CLASS_NAME";"     ),
-    VIDEOEDIT_JAVA_FIELD_INIT("slideSettings",       "L"SLIDE_TRANSITION_SETTINGS_CLASS_NAME";")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(TransitionSettings, TRANSITION_SETTINGS_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_FIELDS(Version)
-{
-    VIDEOEDIT_JAVA_FIELD_INIT("major",    "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("minor",    "I"),
-    VIDEOEDIT_JAVA_FIELD_INIT("revision", "I")
-};
-
-VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(Version, VERSION_CLASS_NAME)
-
-
-VIDEOEDIT_JAVA_DEFINE_METHODS(Engine)
-{
-    VIDEOEDIT_JAVA_METHOD_INIT("onProgressUpdate", "(II)V")
-};
-
-VIDEOEDIT_JAVA_DEFINE_METHOD_CLASS(Engine, MANUAL_EDIT_ENGINE_CLASS_NAME)
-
-
-static const char*
-videoEditClasses_getBrandString(M4OSA_UInt32 brand)
-{
-    static char         brandString[11] = "0x00000000";
-           const char*  pBrandString    = M4OSA_NULL;
-           M4OSA_UInt8* pBrand          = (M4OSA_UInt8*)&brand;
-           M4OSA_UInt32 brandHost       = 0;
-
-    // Convert the brand from big endian to host.
-    brandHost =  pBrand[0];
-    brandHost =  brandHost << 8;
-    brandHost += pBrand[1];
-    brandHost =  brandHost << 8;
-    brandHost += pBrand[2];
-    brandHost =  brandHost << 8;
-    brandHost += pBrand[3];
-
-    switch (brandHost)
-    {
-    case M4VIDEOEDITING_BRAND_0000:
-        pBrandString = "0000";
-        break;
-    case M4VIDEOEDITING_BRAND_3G2A:
-        pBrandString = "3G2A";
-        break;
-    case M4VIDEOEDITING_BRAND_3GP4:
-        pBrandString = "3GP4";
-        break;
-    case M4VIDEOEDITING_BRAND_3GP5:
-        pBrandString = "3GP5";
-        break;
-    case M4VIDEOEDITING_BRAND_3GP6:
-        pBrandString = "3GP6";
-        break;
-    case M4VIDEOEDITING_BRAND_AVC1:
-        pBrandString = "AVC1";
-        break;
-    case M4VIDEOEDITING_BRAND_EMP:
-        pBrandString = "EMP";
-        break;
-    case M4VIDEOEDITING_BRAND_ISOM:
-        pBrandString = "ISOM";
-        break;
-    case M4VIDEOEDITING_BRAND_MP41:
-        pBrandString = "MP41";
-        break;
-    case M4VIDEOEDITING_BRAND_MP42:
-        pBrandString = "MP42";
-        break;
-    case M4VIDEOEDITING_BRAND_VFJ1:
-        pBrandString = "VFJ1";
-        break;
-    default:
-        M4OSA_chrSPrintf((M4OSA_Char *)brandString,
-                         sizeof(brandString) - 1,
-                         (M4OSA_Char*)"0x%08X", brandHost);
-        pBrandString = brandString;
-        break;
-    }
-
-    // Return the brand string.
-    return(pBrandString);
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-static void
-videoEditClasses_logFtypBox(
-                M4VIDEOEDITING_FtypBox*             pBox,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the FtypBox.
-    if (M4OSA_NULL != pBox)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "%*c major_brand:        %s",    indentation, ' ',
-                 videoEditClasses_getBrandString(pBox->major_brand));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "%*c minor_version:      %08X",  indentation, ' ',
-                (unsigned int)pBox->minor_version);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "%*c nbCompatibleBrands: %u",    indentation, ' ',
-                (unsigned int)pBox->nbCompatibleBrands);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "%*c compatible_brands:", indentation, ' ');
-                indentation += VIDEOEDIT_LOG_INDENTATION;
-        for (int i = 0; (i < (int)pBox->nbCompatibleBrands) &&\
-         (i < M4VIDEOEDITING_MAX_COMPATIBLE_BRANDS); i++)
-        {
-            VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "%*c compatible_brand[%d]: %s",    indentation, ' ',
-                    i, videoEditClasses_getBrandString(pBox->compatible_brands[i]));
-        }
-        indentation -= VIDEOEDIT_LOG_INDENTATION;
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
-                 indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_init(
-                bool*                               pResult,
-                JNIEnv*                             pEnv)
-{
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",\
-        "videoEditClasses_init()");
-
-        // Initialize the constants.
-        videoEditJava_initAudioEffectConstants(pResult, pEnv);
-        videoEditJava_initAudioFormatConstants(pResult, pEnv);
-        videoEditJava_initAudioSamplingFrequencyConstants(pResult, pEnv);
-        videoEditJava_initAudioTransitionConstants(pResult, pEnv);
-        videoEditJava_initBitrateConstants(pResult, pEnv);
-        videoEditJava_initClipTypeConstants(pResult, pEnv);
-        videoEditJava_initEngineConstants(pResult, pEnv);
-        videoEditJava_initErrorConstants(pResult, pEnv);
-        videoEditJava_initFileTypeConstants(pResult, pEnv);
-        videoEditJava_initMediaRenderingConstants(pResult, pEnv);
-        videoEditJava_initSlideDirectionConstants(pResult, pEnv);
-        videoEditJava_initTransitionBehaviourConstants(pResult, pEnv);
-        videoEditJava_initVideoEffectConstants(pResult, pEnv);
-        videoEditJava_initVideoFormatConstants(pResult, pEnv);
-        videoEditJava_initVideoFrameRateConstants(pResult, pEnv);
-        videoEditJava_initVideoFrameSizeConstants(pResult, pEnv);
-        videoEditJava_initVideoTransitionConstants(pResult, pEnv);
-
-        // Initialize the fields.
-        videoEditJava_initAlphaMagicFields(pResult, pEnv);
-        videoEditJava_initBackgroundMusicFields(pResult, pEnv);
-        videoEditJava_initClipSettingsFields(pResult, pEnv);
-        videoEditJava_initEditSettingsFields(pResult, pEnv);
-        videoEditJava_initEffectSettingsFields(pResult, pEnv);
-        videoEditJava_initEngineFields(pResult, pEnv);
-        videoEditJava_initSlideTransitionSettingsFields(pResult, pEnv);
-        videoEditJava_initTransitionSettingsFields(pResult, pEnv);
-        videoEditJava_initVersionFields(pResult, pEnv);
-        // Initialize the methods.
-        videoEditJava_initEngineMethods(pResult, pEnv);
-    }
-}
-
-void
-videoEditPropClass_init(
-                bool*                               pResult,
-                JNIEnv*                             pEnv)
-{
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",\
-            "videoEditPropClass_init()");
-
-        // Initialize the constants.
-        videoEditJava_initAudioFormatConstants(pResult, pEnv);
-        videoEditJava_initErrorConstants(pResult, pEnv);
-        videoEditJava_initFileTypeConstants(pResult, pEnv);
-        videoEditJava_initVideoFormatConstants(pResult, pEnv);
-
-        // Initialize the fields.
-        videoEditJava_initPropertiesFields(pResult, pEnv);
-    }
-}
-
-void
-videoEditClasses_getAlphaMagicSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_AlphaMagicSettings**         ppSettings)
-{
-    VideoEditJava_AlphaMagicFieldIds fieldIds;
-    M4xVSS_AlphaMagicSettings* pSettings = M4OSA_NULL;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_AlphaMagicFieldIds));
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                   "videoEditClasses_getAlphaMagicSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getAlphaMagicFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only validate the AlphaMagicSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the clip is set.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    "alphaSettings is null");
-    }
-
-    // Only retrieve the AlphaMagicSettings if the fields could be located and validated.
-    if (*pResult)
-    {
-        // Allocate memory for the AlphaMagicSettings.
-        pSettings = (M4xVSS_AlphaMagicSettings*)videoEditOsal_alloc(pResult, pEnv,
-                sizeof(M4xVSS_AlphaMagicSettings), "AlphaMagicSettings");
-
-        // Check if memory could be allocated for the AlphaMagicSettings.
-        if (*pResult)
-        {
-            // Set the alpha magic file path (JPG file).
-            pSettings->pAlphaFilePath = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
-                    fieldIds.file, M4OSA_NULL);
-
-            // Check if the alpha magic file path is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                    (M4OSA_NULL == pSettings->pAlphaFilePath), "alphaSettings.file is null");
-        }
-
-        // Check if the alpha file path could be retrieved.
-        if (*pResult)
-        {
-            // Set the blending percentage between 0 and 100.
-            pSettings->blendingPercent = (M4OSA_UInt8)pEnv->GetIntField(object,
-                    fieldIds.blendingPercent);
-
-            // Set the direct effect or reverse.
-            pSettings->isreverse = (M4OSA_Bool)pEnv->GetBooleanField(object,
-                    fieldIds.invertRotation);
-
-            // Get the rgb width
-            pSettings->width = (M4OSA_UInt32) pEnv->GetIntField(object, fieldIds.rgbWidth );
-
-            pSettings->height = (M4OSA_UInt32) pEnv->GetIntField(object, fieldIds.rgbHeight );
-
-             VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "((((((((((path %s", pSettings->pAlphaFilePath);
-
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "------- getAlphaMagicSettings width %d", pEnv->GetIntField(object,
-                    fieldIds.rgbWidth ));
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                   "-------- getAlphaMagicSettings Height %d",
-                   pEnv->GetIntField(object, fieldIds.rgbHeight ));
-        }
-
-        // Check if settings could be set.
-        if (*pResult)
-        {
-            // Return the settings.
-            (*ppSettings) = pSettings;
-        }
-        else
-        {
-            // Free the settings.
-            videoEditClasses_freeAlphaMagicSettings(&pSettings);
-        }
-    }
-}
-
-void
-videoEditClasses_freeAlphaMagicSettings(
-                M4xVSS_AlphaMagicSettings**         ppSettings)
-{
-    // Check if memory was allocated for the AlphaMagicSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                  "videoEditClasses_freeAlphaMagicSettings()");
-
-        // Free the alpha file path.
-        videoEditOsal_free((*ppSettings)->pAlphaFilePath);
-        (*ppSettings)->pAlphaFilePath = M4OSA_NULL;
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logAlphaMagicSettings(
-                M4xVSS_AlphaMagicSettings*          pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the AlphaMagicSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-             "%*c pAlphaFilePath:  %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->pAlphaFilePath) ? \
-            (char *)pSettings->pAlphaFilePath : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-             "%*c blendingPercent: %u %%", indentation, ' ',
-            (unsigned int)pSettings->blendingPercent);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c isreverse:       %s",    indentation, ' ',
-            pSettings->isreverse ? "true" : "false");
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_getBackgroundMusicSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_BGMSettings**                ppSettings)
-{
-    VideoEditJava_BackgroundMusicFieldIds fieldIds;
-    M4xVSS_BGMSettings*           pSettings = M4OSA_NULL;
-    bool                          converted = true;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_BackgroundMusicFieldIds));
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-               "videoEditClasses_getBackgroundMusicSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getBackgroundMusicFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only retrieve the BackgroundMusicSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the object is valid.
-        if (NULL != object)
-        {
-            // Allocate memory for the BackgroundMusicSettings.
-            pSettings = (M4xVSS_BGMSettings*)videoEditOsal_alloc(pResult, pEnv,
-                sizeof(M4xVSS_BGMSettings), "BackgroundMusicSettings");
-
-            // Check if memory could be allocated for the BackgroundMusicSettings.
-            if (*pResult)
-            {
-                // Set the input file path.
-                pSettings->pFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
-                        fieldIds.file, M4OSA_NULL);
-
-                // Check if the input file path is valid.
-                videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        (M4OSA_NULL == pSettings->pFile), "backgroundMusicSettings.file is null");
-            }
-
-            // Check if the input file path could be retrieved.
-            if (*pResult)
-            {
-                // Set the file type .3gp, .amr, .mp3.
-                pSettings->FileType = M4VIDEOEDITING_kFileType_PCM;
-                /*(M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
-                 &converted, pEnv->GetIntField(object, fieldIds.fileType));*/
-
-                // Check if the file type is valid.
-                videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        !converted, "backgroundMusicSettings.fileType is invalid");
-            }
-
-            // Check if the file type could be retrieved.
-            if (*pResult)
-            {
-                // Set the time, in milliseconds, at which the added audio track is inserted.
-                pSettings->uiAddCts = (M4OSA_UInt32)pEnv->GetLongField(object,
-                        fieldIds.insertionTime);
-
-                // Set the volume, in percentage (0..100), of the added audio track.
-                pSettings->uiAddVolume = (M4OSA_UInt32)pEnv->GetIntField(object,
-                        fieldIds.volumePercent);
-
-                // Set the start time of the loop in milli seconds.
-                pSettings->uiBeginLoop = (M4OSA_UInt32)pEnv->GetLongField(object,
-                        fieldIds.beginLoop);
-
-                // Set the end time of the loop in milli seconds.
-                pSettings->uiEndLoop = (M4OSA_UInt32)pEnv->GetLongField(object,
-                        fieldIds.endLoop);
-                // Set the end time of the loop in milli seconds.
-                pSettings->b_DuckingNeedeed =
-                        (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.enableDucking);
-
-                // Set the end time of the loop in milli seconds.
-                pSettings->InDucking_threshold =
-                        (M4OSA_Int32)pEnv->GetIntField(object, fieldIds.duckingThreshold);
-
-                // Set the end time of the loop in milli seconds.
-                pSettings->lowVolume =
-                        (M4OSA_Float)(((M4OSA_Float)pEnv->GetIntField(object, fieldIds.lowVolume)));
-
-                // Set the end time of the loop in milli seconds.
-                pSettings->bLoop = (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.isLooping);
-
-                // Set sampling freq and channels
-                pSettings->uiSamplingFrequency = M4VIDEOEDITING_k32000_ASF;
-                pSettings->uiNumChannels = 2;
-            }
-
-            // Check if settings could be set.
-            if (*pResult)
-            {
-                // Return the settings.
-                (*ppSettings) = pSettings;
-            }
-            else
-            {
-                // Free the settings.
-                videoEditClasses_freeBackgroundMusicSettings(&pSettings);
-            }
-        }
-    }
-}
-
-void
-videoEditClasses_freeBackgroundMusicSettings(
-                M4xVSS_BGMSettings**                ppSettings)
-{
-    // Check if memory was allocated for the BackgroundMusicSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-         "videoEditClasses_freeBackgroundMusicSettings()");
-
-        // Free the input file path.
-        videoEditOsal_free((*ppSettings)->pFile);
-        (*ppSettings)->pFile = M4OSA_NULL;
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logBackgroundMusicSettings(
-                M4xVSS_BGMSettings*                 pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the BackgroundMusicSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c pFile:       %s",
-            indentation, ' ',
-            (M4OSA_NULL != pSettings->pFile) ? (char *)pSettings->pFile : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c FileType:    %s",    indentation, ' ',
-            videoEditJava_getClipTypeString(pSettings->FileType));
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiAddCts:    %u ms",
-            indentation, ' ', (unsigned int)pSettings->uiAddCts);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiAddVolume: %u %%",
-            indentation, ' ', (unsigned int)pSettings->uiAddVolume);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiBeginLoop: %u ms",
-            indentation, ' ', (unsigned int)pSettings->uiBeginLoop);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c uiEndLoop:   %u ms",
-            indentation, ' ', (unsigned int)pSettings->uiEndLoop);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c b_DuckingNeedeed:\
-            %u ", indentation, ' ', (bool)pSettings->b_DuckingNeedeed);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c InDucking_threshold: \
-            %u ms", indentation, ' ', (unsigned int)pSettings->InDucking_threshold);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c lowVolume:   %2.2f ",\
-            indentation, ' ', (float)pSettings->lowVolume);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c bLoop:   %u ms",\
-            indentation, ' ', (bool)pSettings->bLoop);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
-            indentation, ' ');
-    }
-}
-#endif
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logClipProperties(
-                M4VIDEOEDITING_ClipProperties*      pProperties,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the ClipProperties.
-    if (M4OSA_NULL != pProperties)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bAnalysed:                        %s",       indentation, ' ',
-            pProperties->bAnalysed ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c Version:                          %d.%d.%d", indentation, ' ',
-            pProperties->Version[0], pProperties->Version[1], pProperties->Version[2]);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiClipDuration:                   %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c FileType:                         %s",       indentation, ' ',
-            videoEditJava_getClipTypeString(pProperties->FileType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c ftyp:",
-                                              indentation, ' ');
-        videoEditClasses_logFtypBox(&pProperties->ftyp, indentation + VIDEOEDIT_LOG_INDENTATION);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c VideoStreamType:                  %s",       indentation, ' ',
-            videoEditJava_getVideoFormatString(pProperties->VideoStreamType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiClipVideoDuration:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipVideoDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiVideoBitrate:                   %s",       indentation, ' ',
-            videoEditJava_getBitrateString(pProperties->uiVideoBitrate));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiVideoMaxAuSize:                 %u",       indentation, ' ',
-            (unsigned int)pProperties->uiVideoMaxAuSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiVideoWidth:                     %u",       indentation, ' ',
-            (unsigned int)pProperties->uiVideoWidth);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiVideoHeight:                    %u",       indentation, ' ',
-            (unsigned int)(unsigned int)pProperties->uiVideoHeight);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiVideoTimeScale:                 %u",       indentation, ' ',
-            (unsigned int)pProperties->uiVideoTimeScale);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c fAverageFrameRate:                %.3f",     indentation, ' ',
-            pProperties->fAverageFrameRate);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bMPEG4dataPartition:              %s",       indentation, ' ',
-            pProperties->bMPEG4dataPartition ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bMPEG4rvlc:                       %s",       indentation, ' ',
-            pProperties->bMPEG4rvlc ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bMPEG4resynchMarker:              %s",       indentation, ' ',
-            pProperties->bMPEG4resynchMarker ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c AudioStreamType:                  %s",       indentation, ' ',
-            videoEditJava_getAudioFormatString(pProperties->AudioStreamType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiClipAudioDuration:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipAudioDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiAudioBitrate:                   %s",       indentation, ' ',
-            videoEditJava_getBitrateString(pProperties->uiAudioBitrate));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiAudioMaxAuSize:                 %u",       indentation, ' ',
-            (unsigned int)pProperties->uiAudioMaxAuSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiNbChannels:                     %u",       indentation, ' ',
-            (unsigned int)pProperties->uiNbChannels);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiSamplingFrequency:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiSamplingFrequency);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiExtendedSamplingFrequency:      %u",       indentation, ' ',
-            (unsigned int)pProperties->uiExtendedSamplingFrequency);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiDecodedPcmSize:                 %u",       indentation, ' ',
-            (unsigned int)pProperties->uiDecodedPcmSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bVideoIsEditable:                 %s",       indentation, ' ',
-            pProperties->bVideoIsEditable ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bAudioIsEditable:                 %s",       indentation, ' ',
-            pProperties->bAudioIsEditable ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bVideoIsCompatibleWithMasterClip: %s",       indentation, ' ',
-            pProperties->bVideoIsCompatibleWithMasterClip ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bAudioIsCompatibleWithMasterClip: %s",       indentation, ' ',
-            pProperties->bAudioIsCompatibleWithMasterClip ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiClipAudioVolumePercentage:      %d",       indentation, ' ',
-                        pProperties->uiClipAudioVolumePercentage);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES", "%*c <null>",
-            indentation, ' ');
-    }
-}
-#endif
-
-void
-videoEditClasses_getClipSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_ClipSettings**            ppSettings)
-{
-
-    VideoEditJava_ClipSettingsFieldIds fieldIds;
-    M4VSS3GPP_ClipSettings*    pSettings = M4OSA_NULL;
-    M4OSA_ERR                  result    = M4NO_ERROR;
-    bool                       converted = true;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_ClipSettingsFieldIds));
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "videoEditClasses_getClipSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getClipSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only validate the ClipSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the clip is set.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    "clip is null");
-    }
-
-    // Only retrieve the ClipSettings if the fields could be located and validated.
-    if (*pResult)
-    {
-        // Allocate memory for the ClipSettings.
-        pSettings = (M4VSS3GPP_ClipSettings *)videoEditOsal_alloc(pResult, pEnv,
-            sizeof(M4VSS3GPP_ClipSettings), "ClipSettings");
-
-        // Check if memory could be allocated for the ClipSettings.
-        if (*pResult)
-        {
-            // Log the API call.
-            VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4xVSS_CreateClipSettings()");
-
-            // Initialize the ClipSettings.
-            result = M4xVSS_CreateClipSettings(pSettings, NULL, 0, 0);
-
-            // Log the result.
-            VIDEOEDIT_LOG_RESULT(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                videoEditOsal_getResultString(result));
-
-            // Check if the initialization succeeded.
-            videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
-                (M4NO_ERROR != result), result);
-        }
-
-        // Check if the allocation and initialization succeeded
-        //(required because pSettings is dereferenced).
-        if (*pResult)
-        {
-            // Set the input file path.
-            pSettings->pFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
-                fieldIds.clipPath, &pSettings->filePathSize);
-
-            // Check if the file path is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                    (M4OSA_NULL == pSettings->pFile), "clip.clipPath is null");
-        }
-
-        // Check if the input file could be retrieved.
-        if (*pResult)
-        {
-            // Set the file type .3gp, .amr, .mp3.
-            pSettings->FileType = (M4VIDEOEDITING_FileType)videoEditJava_getClipTypeJavaToC(
-                                        &converted, pEnv->GetIntField(object, fieldIds.fileType));
-
-            if (( pSettings->FileType == M4VIDEOEDITING_kFileType_JPG) ||
-                 ( pSettings->FileType == M4VIDEOEDITING_kFileType_PNG)) {
-                 pSettings->FileType = M4VIDEOEDITING_kFileType_ARGB8888;
-            }
-
-            // Check if the file type is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                    !converted, "clip.fileType is invalid");
-        }
-
-        // Check if the file type could be retrieved.
-        if (*pResult)
-        {
-            // Set the begin cut time, in milliseconds.
-            pSettings->uiBeginCutTime =
-                (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.beginCutTime);
-
-            // Set the end cut time, in milliseconds.
-            pSettings->uiEndCutTime = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.endCutTime);
-
-            // Set the begin cut time, in percent of clip duration (only for 3GPP clip !).
-            pSettings->xVSS.uiBeginCutPercent =
-                (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.beginCutPercent);
-
-            // Set the end cut time, in percent of clip duration (only for 3GPP clip !).
-            pSettings->xVSS.uiEndCutPercent =
-                (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.endCutPercent);
-
-            // Set the duration of the clip, if different from 0,
-            // has priority on uiEndCutTime or uiEndCutPercent.
-            pSettings->xVSS.uiDuration = 0;
-
-            // Set whether or not the pan and zoom mode is enabled.
-            pSettings->xVSS.isPanZoom =
-                (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.panZoomEnabled);
-
-            // Set the pan and zoom start zoom percentage.
-            pSettings->xVSS.PanZoomXa        =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomPercentStart);
-
-            // Set the pan and zoom start x.
-            pSettings->xVSS.PanZoomTopleftXa =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftXStart);
-
-            // Set the pan and zoom start y.
-            pSettings->xVSS.PanZoomTopleftYa =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftYStart);
-
-            // Set the pan and zoom end zoom percentage.
-            pSettings->xVSS.PanZoomXb        =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomPercentEnd);
-
-            // Set the pan and zoom end x.
-            pSettings->xVSS.PanZoomTopleftXb =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftXEnd);
-
-            // Set the pan and zoom end y.
-            pSettings->xVSS.PanZoomTopleftYb =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.panZoomTopLeftYEnd);
-
-            // Set the media rendering mode, only used with JPEG to crop, resize,
-            // or render black borders.
-            pSettings->xVSS.MediaRendering =
-                (M4xVSS_MediaRendering)videoEditJava_getMediaRenderingJavaToC(
-                    &converted, pEnv->GetIntField(object,fieldIds.mediaRendering));
-
-            // Check if the media rendering is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
-                "clip.mediaRendering is invalid");
-
-             // Capture the rgb file width and height
-            pSettings->ClipProperties.uiStillPicWidth =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.rgbFileWidth);
-            pSettings->ClipProperties.uiStillPicHeight  =
-                (M4OSA_UInt16)pEnv->GetIntField(object, fieldIds.rgbFileHeight);
-
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", \
-                "getClipSettings-- rgbFileWidth %d ",
-                pSettings->ClipProperties.uiStillPicWidth);
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", \
-                "getClipSettings-- rgbFileHeight %d ",
-                pSettings->ClipProperties.uiStillPicHeight);
-
-            // Set the video rotation degree
-            pSettings->ClipProperties.videoRotationDegrees =
-                (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.rotationDegree);
-        }
-
-        // Check if settings could be set.
-        if (*pResult)
-        {
-            // Return the settings.
-            (*ppSettings) = pSettings;
-        }
-        else
-        {
-            // Free the settings.
-            videoEditClasses_freeClipSettings(&pSettings);
-        }
-    }
-}
-
-void
-videoEditClasses_createClipSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                M4VSS3GPP_ClipSettings*             pSettings,
-                jobject*                            pObject)
-{
-    VideoEditJava_ClipSettingsFieldIds fieldIds;
-    jclass                     clazz    = NULL;
-    jobject                    object   = NULL;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_ClipSettingsFieldIds));
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "videoEditClasses_createClipSettings()");
-
-        // Retrieve the class.
-        videoEditJava_getClipSettingsClass(pResult, pEnv, &clazz);
-
-        // Retrieve the field ids.
-        videoEditJava_getClipSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only create an object if the class and fields could be located.
-    if (*pResult)
-    {
-        // Allocate a new object.
-        object = pEnv->AllocObject(clazz);
-        if (NULL != object)
-        {
-            // Set the clipPath field.
-            pEnv->SetObjectField(object, fieldIds.clipPath, NULL);
-
-            // Set the fileType field.
-            pEnv->SetIntField(object, fieldIds.fileType, videoEditJava_getClipTypeCToJava(
-                                                                    pSettings->FileType));
-
-            // Set the beginCutTime field.
-            pEnv->SetIntField(object, fieldIds.beginCutTime, pSettings->uiBeginCutTime);
-
-            // Set the endCutTime field.
-            pEnv->SetIntField(object, fieldIds.endCutTime, pSettings->uiEndCutTime);
-
-            // Set the beginCutPercent field.
-            pEnv->SetIntField(object, fieldIds.beginCutPercent, pSettings->xVSS.uiBeginCutPercent);
-
-            // Set the endCutPercent field.
-            pEnv->SetIntField(object, fieldIds.endCutPercent, pSettings->xVSS.uiEndCutPercent);
-
-            // Set the panZoomEnabled field.
-            pEnv->SetBooleanField(object, fieldIds.panZoomEnabled, pSettings->xVSS.isPanZoom);
-
-            // Set the panZoomPercentStart field.
-            pEnv->SetIntField(object, fieldIds.panZoomPercentStart,
-                (1000 - pSettings->xVSS.PanZoomXa));
-
-            // Set the panZoomTopLeftXStart field.
-            pEnv->SetIntField(object, fieldIds.panZoomTopLeftXStart,
-                pSettings->xVSS.PanZoomTopleftXa);
-
-            // Set the panZoomTopLeftYStart field.
-            pEnv->SetIntField(object, fieldIds.panZoomTopLeftYStart,
-                pSettings->xVSS.PanZoomTopleftYa);
-
-            // Set the panZoomPercentEnd field.
-            pEnv->SetIntField(object, fieldIds.panZoomPercentEnd,
-                (1000 - pSettings->xVSS.PanZoomXb));
-
-            // Set the panZoomTopLeftXEnd field.
-            pEnv->SetIntField(object, fieldIds.panZoomTopLeftXEnd,
-                pSettings->xVSS.PanZoomTopleftXb);
-
-            // Set the panZoomTopLeftYEnd field.
-            pEnv->SetIntField(object, fieldIds.panZoomTopLeftYEnd,
-                pSettings->xVSS.PanZoomTopleftYb);
-
-            // Set the mediaRendering field.
-            pEnv->SetIntField(object, fieldIds.mediaRendering,
-                videoEditJava_getMediaRenderingCToJava(pSettings->xVSS.MediaRendering));
-
-            // Set the rgb file width and height
-            pEnv->SetIntField(object, fieldIds.rgbFileWidth,
-                pSettings->ClipProperties.uiStillPicWidth );
-
-            pEnv->SetIntField(object, fieldIds.rgbFileHeight,
-                pSettings->ClipProperties.uiStillPicHeight );
-
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "rgbFileWeight %d rgbFileHeight %d ",
-                pSettings->ClipProperties.uiStillPicWidth ,
-                pSettings->ClipProperties.uiStillPicHeight);
-
-            // Set the video rotation
-            pEnv->SetIntField(object, fieldIds.rotationDegree,
-                pSettings->ClipProperties.videoRotationDegrees);
-
-            // Return the object.
-            (*pObject) = object;
-        }
-    }
-}
-void
-videoEditPropClass_createProperties(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditPropClass_Properties*      pProperties,
-                jobject*                            pObject)
-{
-    VideoEditJava_PropertiesFieldIds fieldIds;
-    jclass                   clazz    = NULL;
-    jobject                  object   = NULL;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_PropertiesFieldIds));
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-                "videoEditPropClass_createProperties()");
-
-        // Retrieve the class.
-        videoEditJava_getPropertiesClass(pResult, pEnv, &clazz);
-
-        // Retrieve the field ids.
-        videoEditJava_getPropertiesFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only create an object if the class and fields could be located.
-    if (*pResult)
-    {
-        // Allocate a new object.
-        object = pEnv->AllocObject(clazz);
-        if (NULL != object)
-        {
-            // Set the duration field.
-            pEnv->SetIntField(object, fieldIds.duration, pProperties->uiClipDuration);
-
-            // Set the fileType field.
-            pEnv->SetIntField(object, fieldIds.fileType,
-                videoEditJava_getFileTypeCToJava(pProperties->FileType));
-
-            // Set the videoFormat field.
-            pEnv->SetIntField(object, fieldIds.videoFormat,
-                videoEditJava_getVideoFormatCToJava(pProperties->VideoStreamType));
-
-            // Set the videoDuration field.
-            pEnv->SetIntField(object, fieldIds.videoDuration, pProperties->uiClipVideoDuration);
-
-            // Set the videoBitrate field.
-            pEnv->SetIntField(object, fieldIds.videoBitrate, pProperties->uiVideoBitrate);
-
-            // Set the width field.
-            pEnv->SetIntField(object, fieldIds.width, pProperties->uiVideoWidth);
-
-            // Set the height field.
-            pEnv->SetIntField(object, fieldIds.height, pProperties->uiVideoHeight);
-
-            // Set the averageFrameRate field.
-            pEnv->SetFloatField(object, fieldIds.averageFrameRate, pProperties->fAverageFrameRate);
-
-            // Set the profile field.
-            pEnv->SetIntField(object, fieldIds.profile,
-                pProperties->uiVideoProfile);
-
-            // Set the level field.
-            pEnv->SetIntField(object, fieldIds.level,
-                pProperties->uiVideoLevel);
-
-            // Set whether profile supported
-            pEnv->SetBooleanField(object, fieldIds.profileSupported,
-                pProperties->bProfileSupported);
-
-            // Set whether level supported
-            pEnv->SetBooleanField(object, fieldIds.levelSupported,
-                pProperties->bLevelSupported);
-
-            // Set the audioFormat field.
-            pEnv->SetIntField(object, fieldIds.audioFormat,
-                videoEditJava_getAudioFormatCToJava(pProperties->AudioStreamType));
-
-            // Set the audioDuration field.
-            pEnv->SetIntField(object, fieldIds.audioDuration, pProperties->uiClipAudioDuration);
-
-            // Set the audioBitrate field.
-            pEnv->SetIntField(object, fieldIds.audioBitrate, pProperties->uiAudioBitrate);
-
-            // Set the audioChannels field.
-            pEnv->SetIntField(object, fieldIds.audioChannels, pProperties->uiNbChannels);
-
-            // Set the audioSamplingFrequency field.
-            pEnv->SetIntField(object, fieldIds.audioSamplingFrequency,
-                pProperties->uiSamplingFrequency);
-
-            // Set the video rotation field.
-            pEnv->SetIntField(object, fieldIds.videoRotation, pProperties->uiRotation);
-
-            // Return the object.
-            (*pObject) = object;
-        }
-    }
-}
-
-void
-videoEditClasses_freeClipSettings(
-                M4VSS3GPP_ClipSettings**            ppSettings)
-{
-    // Check if memory was allocated for the ClipSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "videoEditClasses_freeClipSettings()");
-
-        // Free the input file path.
-        videoEditOsal_free((*ppSettings)->pFile);
-        (*ppSettings)->pFile = M4OSA_NULL;
-        (*ppSettings)->filePathSize = 0;
-
-        // Free the clip settings.
-        M4xVSS_FreeClipSettings((*ppSettings));
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logClipSettings(
-                M4VSS3GPP_ClipSettings*             pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the ClipSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pFile:           %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->pFile) ? (char*)pSettings->pFile : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c FileType:        %s", indentation, ' ',
-            videoEditJava_getClipTypeString(pSettings->FileType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c filePathSize:    %u", indentation, ' ',
-            (unsigned int)pSettings->filePathSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c ClipProperties:",  indentation, ' ');
-        videoEditClasses_logClipProperties(&pSettings->ClipProperties,
-            indentation + VIDEOEDIT_LOG_INDENTATION);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiBeginCutTime:    %u ms", indentation, ' ',
-            (unsigned int)pSettings->uiBeginCutTime);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiEndCutTime:      %u ms", indentation, ' ',
-            (unsigned int)pSettings->uiEndCutTime);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiBeginCutPercent: %u %%", indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiBeginCutPercent);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiEndCutPercent:   %u %%", indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiEndCutPercent);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiDuration:        %u ms", indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c isPanZoom:         %s",    indentation, ' ',
-            pSettings->xVSS.isPanZoom ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomXa:         %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomXa);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomTopleftXa:  %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomTopleftXa);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomTopleftYa:  %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomTopleftYa);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomXb:         %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomXb);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomTopleftXb:  %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomTopleftXb);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PanZoomTopleftYb:  %d ms", indentation, ' ',
-            pSettings->xVSS.PanZoomTopleftYb);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c MediaRendering:    %s",    indentation, ' ',
-            videoEditJava_getMediaRenderingString(pSettings->xVSS.MediaRendering));
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_getEditSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_EditSettings**            ppSettings,
-                bool                                flag)
-{
-    VideoEditJava_EditSettingsFieldIds fieldIds;
-    jobjectArray               clipSettingsArray           = NULL;
-    jsize                      clipSettingsArraySize       = 0;
-    jobject                    clipSettings                = NULL;
-    jobjectArray               transitionSettingsArray     = NULL;
-    jsize                      transitionSettingsArraySize = 0;
-    jobject                    transitionSettings          = NULL;
-    jobjectArray               effectSettingsArray         = NULL;
-    jsize                      effectSettingsArraySize     = 0;
-    jobject                    effectSettings              = NULL;
-    jobject                    backgroundMusicSettings     = NULL;
-    int                        audioChannels               = 0;
-    M4VSS3GPP_EditSettings*    pSettings                   = M4OSA_NULL;
-    bool                       converted                   = true;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_EditSettingsFieldIds));
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "videoEditClasses_getEditSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getEditSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only retrieve the EditSettings if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the object is valid.
-        if (NULL != object)
-        {
-            // Retrieve the clipSettingsArray.
-            videoEditJava_getArray(pResult, pEnv, object,
-                           fieldIds.clipSettingsArray,
-                           &clipSettingsArray,
-                           &clipSettingsArraySize);
-
-            // Retrieve the transitionSettingsArray.
-            videoEditJava_getArray(pResult, pEnv, object,
-                           fieldIds.transitionSettingsArray,
-                           &transitionSettingsArray,
-                           &transitionSettingsArraySize);
-
-            // Retrieve the effectSettingsArray.
-            videoEditJava_getArray(pResult, pEnv, object,
-                           fieldIds.effectSettingsArray,
-                           &effectSettingsArray,
-                           &effectSettingsArraySize);
-
-            // Retrieve the backgroundMusicSettings.
-            videoEditJava_getObject(pResult, pEnv, object, fieldIds.backgroundMusicSettings,
-                    &backgroundMusicSettings);
-
-            // Check if the arrays and background music settings object could be retrieved.
-            if (*pResult)
-            {
-                // Retrieve the number of channels.
-                audioChannels = pEnv->GetIntField(object, fieldIds.audioChannels);
-            }
-        }
-    }
-
-    // Only validate the EditSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if there is at least one clip.
-        //videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-         //                                          (clipSettingsArraySize < 1),
-         //                                          "there should be at least one clip");
-        if(clipSettingsArraySize < 1) {
-            return;
-        }
-        if(flag)
-        {
-            // Check if there are clips.
-            if ((clipSettingsArraySize != 0) || (transitionSettingsArraySize != 0))
-            {
-                // The number of transitions must be equal to the number of clips - 1.
-                videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                         (clipSettingsArraySize != (transitionSettingsArraySize + 1)),
-                         "the number of transitions should be equal to the number of clips - 1");
-            }
-        }
-    }
-
-    // Only retrieve the EditSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the object is valid.
-        if (NULL != object)
-        {
-            // Allocate memory for the EditSettings.
-            pSettings = (M4VSS3GPP_EditSettings*)videoEditOsal_alloc(pResult, pEnv,
-                    sizeof(M4VSS3GPP_EditSettings), "EditSettings");
-
-            // Check if memory could be allocated for the EditSettings.
-            if (*pResult)
-            {
-                // Set the number of clips that will be edited.
-                pSettings->uiClipNumber = clipSettingsArraySize;
-
-                // Check if the clip settings array contains items.
-                if (clipSettingsArraySize > 0)
-                {
-                    // Allocate memory for the clip settings array.
-                    pSettings->pClipList = (M4VSS3GPP_ClipSettings **)videoEditOsal_alloc(pResult,
-                                pEnv,
-                                clipSettingsArraySize * sizeof(M4VSS3GPP_ClipSettings *),
-                                "ClipSettingsArray");
-                    if (*pResult)
-                    {
-                        // Loop over all clip settings objects.
-                        for (int i = 0; ((*pResult) && (i < clipSettingsArraySize)); i++)
-                        {
-                            // Get the clip settings object.
-                            clipSettings = pEnv->GetObjectArrayElement(clipSettingsArray, i);
-
-                            // Get the clip settings.
-                            videoEditClasses_getClipSettings(pResult, pEnv, clipSettings,
-                                &pSettings->pClipList[i]);
-
-                            // Free the local references to avoid memory leaks
-                            pEnv->DeleteLocalRef(clipSettings);
-                        }
-                    }
-                }
-
-                // Check if the transition settings array contains items.
-                if (transitionSettingsArraySize > 0)
-                {
-                    // Allocate memory for the transition settings array.
-                    pSettings->pTransitionList =
-                            (M4VSS3GPP_TransitionSettings **)videoEditOsal_alloc(pResult,
-                                pEnv, transitionSettingsArraySize * sizeof(M4VSS3GPP_TransitionSettings *),
-                                "TransitionSettingsArray");
-                    if (*pResult)
-                    {
-                        // Loop over all transition settings objects.
-                        for (int i = 0; ((*pResult) && (i < transitionSettingsArraySize)); i++)
-                        {
-                            // Get the transition settings object.
-                            transitionSettings =
-                                    pEnv->GetObjectArrayElement(transitionSettingsArray, i);
-
-                            // Get the transition settings.
-                            videoEditClasses_getTransitionSettings(pResult, pEnv,
-                                    transitionSettings, &pSettings->pTransitionList[i]);
-
-                            // Free the local references to avoid memory leaks
-                            pEnv->DeleteLocalRef(transitionSettings);
-                        }
-                    }
-                }
-
-                // Check if the effect settings array contains items.
-                if (effectSettingsArraySize > 0)
-                {
-                    // Allocate memory for the effect settings array.
-                    pSettings->Effects = (M4VSS3GPP_EffectSettings*)videoEditOsal_alloc(pResult,
-                                pEnv,
-                                effectSettingsArraySize * sizeof(M4VSS3GPP_EffectSettings),
-                                "EffectSettingsArray");
-                    if (*pResult)
-                    {
-                        // Loop over all effect settings objects.
-                        for (int i = 0; ((*pResult) && (i < effectSettingsArraySize)); i++)
-                        {
-                            // Get the effect settings object.
-                            effectSettings = pEnv->GetObjectArrayElement(effectSettingsArray, i);
-
-                            // Get the effect settings.
-                            videoEditClasses_getEffectSettings(pResult, pEnv, effectSettings,
-                                    &pSettings->Effects[i]);
-
-                            // Free the local references to avoid memory leaks
-                            pEnv->DeleteLocalRef(effectSettings);
-                        }
-                    }
-                }
-
-                // Check if the clips, transitions and effects could be set.
-                if (*pResult)
-                {
-                    // Set the number of effects in the clip.
-                    pSettings->nbEffects = (M4OSA_UInt8)effectSettingsArraySize;
-
-                    // Set the frame rate of the output video.
-                    pSettings->videoFrameRate =
-                        (M4VIDEOEDITING_VideoFramerate)videoEditJava_getVideoFrameRateJavaToC(
-                             &converted, pEnv->GetIntField(object, fieldIds.videoFrameRate));
-
-                    // Check if the frame rate is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        !converted, "editSettings.videoFrameRate is invalid");
-                }
-
-                // Check if the frame rate could be set.
-                if (*pResult)
-                {
-                    // Set the path of the output file.
-                    pSettings->pOutputFile = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
-                        object, fieldIds.outputFile, &pSettings->uiOutputPathSize);
-                }
-
-                // Check if path of the output file could be set.
-                if (*pResult)
-                {
-                    // Set the path of the temporary file produced when using
-                    // the constant memory 3gp writer.
-                    pSettings->pTemporaryFile = M4OSA_NULL;
-
-                    // Set the output video size.
-                    pSettings->xVSS.outputVideoSize =
-                        (M4VIDEOEDITING_VideoFrameSize)videoEditJava_getVideoFrameSizeJavaToC(
-                                &converted, pEnv->GetIntField(object, fieldIds.videoFrameSize));
-
-                    // Check if the output video size is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        !converted, "editSettings.videoFrameSize is invalid");
-                }
-
-                // Check if the output video size could be set.
-                if (*pResult)
-                {
-                    // Set the output video format.
-                    pSettings->xVSS.outputVideoFormat =
-                        (M4VIDEOEDITING_VideoFormat)videoEditJava_getVideoFormatJavaToC(
-                               &converted, pEnv->GetIntField(object, fieldIds.videoFormat));
-
-                    // Check if the output video format is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        !converted, "editSettings.videoFormat is invalid");
-                }
-
-                // Check if the output video format could be set.
-                if (*pResult)
-                {
-                    // Set the output audio format.
-                    pSettings->xVSS.outputAudioFormat =
-                            (M4VIDEOEDITING_AudioFormat)videoEditJava_getAudioFormatJavaToC(
-                                  &converted, pEnv->GetIntField(object, fieldIds.audioFormat));
-
-                    // Check if the output audio format is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                            !converted, "editSettings.audioFormat is invalid");
-                }
-
-                // Check if the output audio format could be set.
-                if (*pResult)
-                {
-                    // Set the output audio sampling frequency when not replacing the audio,
-                    // or replacing it with MP3 audio.
-                    pSettings->xVSS.outputAudioSamplFreq =
-                        (M4VIDEOEDITING_AudioSamplingFrequency)\
-                            videoEditJava_getAudioSamplingFrequencyJavaToC(
-                                &converted, pEnv->GetIntField(object, fieldIds.audioSamplingFreq));
-
-                    // Check if the output audio sampling frequency is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                            !converted, "editSettings.audioSamplingFreq is invalid");
-                }
-
-                // Check if the output audio sampling frequency could be set.
-                if (*pResult)
-                {
-                    // Check if the number of audio channels is valid.
-                    videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                        ((0 != audioChannels ) ||
-                        ((M4VIDEOEDITING_kNoneAudio != pSettings->xVSS.outputAudioFormat) &&
-                        (M4VIDEOEDITING_kNullAudio != pSettings->xVSS.outputAudioFormat) ) ) &&
-                        (1 != audioChannels ) &&
-                        (2 != audioChannels ),
-                        "editSettings.audioChannels must be set to 0, 1 or 2");
-                }
-
-                // Check if the number of audio channels is valid.
-                if (*pResult)
-                {
-                    // Set the maximum output file size (MMS usecase).
-                    pSettings->xVSS.outputFileSize = (M4OSA_UInt32)pEnv->GetIntField(object,
-                            fieldIds.maxFileSize);
-
-                    // Whether or not the audio is mono, only valid for AAC.
-                    pSettings->xVSS.bAudioMono = (M4OSA_Bool)(1 == audioChannels);
-
-                    // Set the output video bitrate.
-                    pSettings->xVSS.outputVideoBitrate = (M4OSA_UInt32)pEnv->GetIntField(object,
-                            fieldIds.videoBitrate);
-
-                    // Set the output video profile.
-                    pSettings->xVSS.outputVideoProfile = (M4OSA_UInt32)pEnv->GetIntField(object,
-                            fieldIds.videoProfile);
-
-                    // Set the output video level.
-                    pSettings->xVSS.outputVideoLevel = (M4OSA_UInt32)pEnv->GetIntField(object,
-                            fieldIds.videoLevel);
-
-                    // Set the output audio bitrate.
-                    pSettings->xVSS.outputAudioBitrate = (M4OSA_UInt32)pEnv->GetIntField(object,
-                            fieldIds.audioBitrate);
-
-                    // Set the background music settings.
-                    videoEditClasses_getBackgroundMusicSettings(pResult, pEnv,
-                            backgroundMusicSettings, &pSettings->xVSS.pBGMtrack);
-
-                    // Set the text rendering function (will be set elsewhere).
-                    pSettings->xVSS.pTextRenderingFct = M4OSA_NULL;
-                    pSettings->PTVolLevel =
-                            (M4OSA_Float)pEnv->GetIntField(object, fieldIds.primaryTrackVolume);
-                }
-            }
-
-            // Check if settings could be set.
-            if (*pResult)
-            {
-                // Return the settings.
-                (*ppSettings) = pSettings;
-            }
-            else
-            {
-                // Free the settings.
-                videoEditClasses_freeEditSettings(&pSettings);
-            }
-        }
-    }
-}
-
-void
-videoEditClasses_freeEditSettings(
-                M4VSS3GPP_EditSettings**            ppSettings)
-{
-    // Check if memory was allocated for the EditSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "videoEditClasses_freeEditSettings()");
-
-        // Free the background music settings.
-        videoEditClasses_freeBackgroundMusicSettings(&(*ppSettings)->xVSS.pBGMtrack);
-
-        // Free the path of the output file.
-        videoEditOsal_free((*ppSettings)->pOutputFile);
-        (*ppSettings)->pOutputFile = M4OSA_NULL;
-        (*ppSettings)->uiOutputPathSize = 0;
-
-        // Check if the EffectSettings should be freed.
-        if (M4OSA_NULL != (*ppSettings)->Effects)
-        {
-            // Loop over all effect settings.
-            for (int i = 0; i < (*ppSettings)->nbEffects; i++)
-            {
-                // Free the effect settings.
-                videoEditClasses_freeEffectSettings(&(*ppSettings)->Effects[i]);
-            }
-
-            // Free the memory for the effect settings array.
-            videoEditOsal_free((*ppSettings)->Effects);
-            (*ppSettings)->Effects = M4OSA_NULL;
-        }
-
-        // Reset the number of effects in the clip.
-        (*ppSettings)->nbEffects = 0;
-
-        // Check if there are clips.
-        if (0 < (*ppSettings)->uiClipNumber)
-        {
-            // Check if the TransitionSettings should be freed.
-            if (M4OSA_NULL != (*ppSettings)->pTransitionList)
-            {
-                // Loop over all transition settings.
-                for (int i = 0; i < ((*ppSettings)->uiClipNumber - 1); i++)
-                {
-                    // Free the transition settings.
-                    videoEditClasses_freeTransitionSettings(&(*ppSettings)->pTransitionList[i]);
-                }
-
-                // Free the memory for the transition settings array.
-                videoEditOsal_free((*ppSettings)->pTransitionList);
-                (*ppSettings)->pTransitionList = M4OSA_NULL;
-            }
-
-            // Check if the ClipSettings should be freed.
-            if (M4OSA_NULL != (*ppSettings)->pClipList)
-            {
-                // Loop over all clip settings.
-                for (int i = 0; i < (*ppSettings)->uiClipNumber; i++)
-                {
-                    // Free the clip settings.
-                    videoEditClasses_freeClipSettings(&(*ppSettings)->pClipList[i]);
-                }
-
-                // Free the memory for the clip settings array.
-                videoEditOsal_free((*ppSettings)->pClipList);
-                (*ppSettings)->pClipList = M4OSA_NULL;
-            }
-        }
-
-        // Reset the number of clips.
-        (*ppSettings)->uiClipNumber = 0;
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logEditSettings(
-                M4VSS3GPP_EditSettings*             pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the EditSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiClipNumber:         %d", indentation, ' ',
-            pSettings->uiClipNumber);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiMasterClip:         %d", indentation, ' ',
-            pSettings->uiMasterClip);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pClipList:            %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->pClipList) ? " " : "<null>");
-        if (M4OSA_NULL != pSettings->pClipList)
-        {
-            indentation += VIDEOEDIT_LOG_INDENTATION;
-            for (int i = 0; i < pSettings->uiClipNumber; i++)
-            {
-                VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "%*c pClipList[%d]:", indentation, ' ',
-                    i);
-                videoEditClasses_logClipSettings(pSettings->pClipList[i],
-                    indentation + VIDEOEDIT_LOG_INDENTATION);
-            }
-            indentation -= VIDEOEDIT_LOG_INDENTATION;
-        }
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pTransitionList:      %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->pTransitionList) ? " " : "<null>");
-        if (M4OSA_NULL != pSettings->pTransitionList)
-        {
-            indentation += VIDEOEDIT_LOG_INDENTATION;
-            for (int i = 0; i < (pSettings->uiClipNumber - 1); i++)
-            {
-                VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "%*c pTransitionList[%d]:", indentation, ' ', i);
-                videoEditClasses_logTransitionSettings(pSettings->pTransitionList[i],
-                    indentation + VIDEOEDIT_LOG_INDENTATION);
-            }
-            indentation -= VIDEOEDIT_LOG_INDENTATION;
-        }
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c Effects:              %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->Effects)   ? " " : "<null>");
-        if (M4OSA_NULL != pSettings->Effects)
-        {
-            indentation += VIDEOEDIT_LOG_INDENTATION;
-            for (int i = 0; i < pSettings->nbEffects; i++)
-            {
-                VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "%*c Effects[%d]:", indentation, ' ',  i);
-                videoEditClasses_logEffectSettings(&pSettings->Effects[i],
-                    indentation + VIDEOEDIT_LOG_INDENTATION);
-            }
-            indentation -= VIDEOEDIT_LOG_INDENTATION;
-        }
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c nbEffects:            %d", indentation, ' ',
-            pSettings->nbEffects);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c videoFrameRate:       %s", indentation, ' ',
-            videoEditJava_getVideoFrameRateString(pSettings->videoFrameRate));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pOutputFile:          %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->pOutputFile) ? (char*)pSettings->pOutputFile : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiOutputPathSize:     %u", indentation, ' ',
-            (unsigned int)pSettings->uiOutputPathSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pTemporaryFile:       %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->pTemporaryFile) ?\
-             (char*)pSettings->pTemporaryFile : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputVideoSize:      %s", indentation, ' ',
-            videoEditJava_getVideoFrameSizeString(pSettings->xVSS.outputVideoSize));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputVideoFormat:    %s", indentation, ' ',
-            videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoFormat));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputVideoProfile:    %u", indentation, ' ',
-            videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoProfile));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputVideoLevel:    %u", indentation, ' ',
-            videoEditJava_getVideoFormatString(pSettings->xVSS.outputVideoLevel));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputAudioFormat:    %s", indentation, ' ',
-            videoEditJava_getAudioFormatString(pSettings->xVSS.outputAudioFormat));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputAudioSamplFreq: %s", indentation, ' ',
-            videoEditJava_getAudioSamplingFrequencyString(pSettings->xVSS.outputAudioSamplFreq));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputFileSize:       %u", indentation, ' ',
-            (unsigned int)pSettings->xVSS.outputFileSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bAudioMono:           %s", indentation, ' ',
-            pSettings->xVSS.bAudioMono ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputVideoBitrate:   %s", indentation, ' ',
-            videoEditJava_getBitrateString(pSettings->xVSS.outputVideoBitrate));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c outputAudioBitrate:   %s", indentation, ' ',
-            videoEditJava_getBitrateString(pSettings->xVSS.outputAudioBitrate));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pBGMtrack:",               indentation, ' ');
-        videoEditClasses_logBackgroundMusicSettings(pSettings->xVSS.pBGMtrack,
-            indentation + VIDEOEDIT_LOG_INDENTATION);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pTextRenderingFct:    %s", indentation, ' ',
-            (M4OSA_NULL != pSettings->xVSS.pTextRenderingFct) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c PTVolLevel:       %u", indentation, ' ',
-            (unsigned int)pSettings->PTVolLevel);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_getEffectSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_EffectSettings*           pSettings)
-{
-
-    VideoEditJava_EffectSettingsFieldIds fieldIds;
-    bool                         converted = true;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_EffectSettingsFieldIds));
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-         "videoEditClasses_getEffectSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getEffectSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only validate the EffectSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the effect is set.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    "effect is null");
-    }
-
-    // Only retrieve the EffectSettings if the fields could be located and validated.
-    if (*pResult)
-    {
-        // Set the start time in milliseconds.
-        pSettings->uiStartTime = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.startTime);
-
-        // Set the duration in milliseconds.
-        pSettings->uiDuration = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.duration);
-
-        // Set the video effect type, None, FadeIn, FadeOut, etc.
-        pSettings->VideoEffectType =
-                (M4VSS3GPP_VideoEffectType)videoEditJava_getVideoEffectJavaToC(
-                              &converted, pEnv->GetIntField(object, fieldIds.videoEffectType));
-
-        // Check if the video effect type is valid.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                !converted, "effect.videoEffectType is invalid");
-    }
-
-    // Check if the video effect type could be set.
-    if (*pResult)
-    {
-        // Set the external effect function.
-        pSettings->ExtVideoEffectFct = M4OSA_NULL;
-
-        // Set the context given to the external effect function.
-        pSettings->pExtVideoEffectFctCtxt = M4OSA_NULL;
-
-        // Set the audio effect type, None, FadeIn, FadeOut.
-        pSettings->AudioEffectType =
-                (M4VSS3GPP_AudioEffectType)videoEditJava_getAudioEffectJavaToC(
-                        &converted, pEnv->GetIntField(object, fieldIds.audioEffectType));
-
-        // Check if the audio effect type is valid.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                !converted, "effect.audioEffectType is invalid");
-    }
-
-    // Check if the audio effect type could be set.
-    if (*pResult)
-    {
-        // Set the start in percentage of the cut clip duration.
-        pSettings->xVSS.uiStartPercent = (M4OSA_UInt32)pEnv->GetIntField(object,
-                fieldIds.startPercent);
-
-        // Set the duration in percentage of the ((clip duration) - (effect starttime)).
-        pSettings->xVSS.uiDurationPercent = (M4OSA_UInt32)pEnv->GetIntField(object,
-                fieldIds.durationPercent);
-
-        // Set the framing file path (GIF/PNG file).
-        pSettings->xVSS.pFramingFilePath = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
-                object, fieldIds.framingFile, M4OSA_NULL);
-
-        // Check if this is a framing effect.
-        if (M4xVSS_kVideoEffectType_Framing == (M4xVSS_VideoEffectType)pSettings->VideoEffectType)
-        {
-            // Check if the framing file path is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                    (M4OSA_NULL == pSettings->xVSS.pFramingFilePath), "effect.framingFile is null");
-        }
-    }
-
-    // Check if the framing file path could be retrieved.
-    if (*pResult)
-    {
-        // Set the Framing RGB565 buffer.
-        pSettings->xVSS.pFramingBuffer = M4OSA_NULL;
-
-        // Set the top-left X coordinate in the output picture
-        // where the added frame will be displayed.
-        pSettings->xVSS.topleft_x = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.topLeftX);
-
-        // Set the top-left Y coordinate in the output picture
-        // where the added frame will be displayed.
-        pSettings->xVSS.topleft_y = (M4OSA_UInt32)pEnv->GetIntField(object, fieldIds.topLeftY);
-
-        // Set whether or not the framing image is resized to output video size.
-        pSettings->xVSS.bResize =
-                (M4OSA_Bool)pEnv->GetBooleanField(object, fieldIds.framingResize);
-
-        // Set the new size to which framing buffer needs to be resized to
-        pSettings->xVSS.framingScaledSize =
-                (M4VIDEOEDITING_VideoFrameSize)pEnv->GetIntField(object, fieldIds.framingScaledSize);
-
-        // Set the text buffer.
-        pSettings->xVSS.pTextBuffer = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv, object,
-                fieldIds.text, &pSettings->xVSS.textBufferSize);
-    }
-
-    // Check if the text buffer could be retrieved.
-    if (*pResult)
-    {
-        // Set the data used by the font engine (size, color...).
-        pSettings->xVSS.pRenderingData = (M4OSA_Char*)videoEditJava_getString(pResult, pEnv,
-                object, fieldIds.textRenderingData, M4OSA_NULL);
-    }
-
-    // Check if the text rendering data could be retrieved.
-    if (*pResult)
-    {
-        // Set the text plane width.
-        pSettings->xVSS.uiTextBufferWidth = (M4OSA_UInt32)pEnv->GetIntField(object,
-                fieldIds.textBufferWidth);
-
-        // Set the text plane height.
-        pSettings->xVSS.uiTextBufferHeight = (M4OSA_UInt32)pEnv->GetIntField(object,
-                fieldIds.textBufferHeight);
-
-        // Set the processing rate of the effect added when using the Fifties effect.
-        pSettings->xVSS.uiFiftiesOutFrameRate = (M4OSA_UInt32)pEnv->GetIntField(object,
-                fieldIds.fiftiesFrameRate);
-
-        // Set the RGB16 input color of the effect added when using the rgb16 color effect.
-        pSettings->xVSS.uiRgb16InputColor = (M4OSA_UInt16)pEnv->GetIntField(object,
-                fieldIds.rgb16InputColor);
-
-        // Set the start percentage of Alpha blending.
-        pSettings->xVSS.uialphaBlendingStart = (M4OSA_UInt8)pEnv->GetIntField(object,
-                fieldIds.alphaBlendingStartPercent);
-
-        // Set the middle percentage of Alpha blending.
-        pSettings->xVSS.uialphaBlendingMiddle = (M4OSA_UInt8)pEnv->GetIntField(object,
-                fieldIds.alphaBlendingMiddlePercent);
-
-        // Set the end percentage of Alpha blending.
-        pSettings->xVSS.uialphaBlendingEnd = (M4OSA_UInt8)pEnv->GetIntField(object,
-                fieldIds.alphaBlendingEndPercent);
-
-        // Set the duration, in percentage of effect duration, of the FadeIn phase.
-        pSettings->xVSS.uialphaBlendingFadeInTime = (M4OSA_UInt8)pEnv->GetIntField(object,
-                fieldIds.alphaBlendingFadeInTimePercent);
-
-        // Set the duration, in percentage of effect duration, of the FadeOut phase.
-        pSettings->xVSS.uialphaBlendingFadeOutTime = (M4OSA_UInt8)pEnv->GetIntField(object,
-                fieldIds.alphaBlendingFadeOutTimePercent);
-
-        if (pSettings->xVSS.pFramingFilePath != M4OSA_NULL)
-        {
-            pSettings->xVSS.pFramingBuffer =
-                (M4VIFI_ImagePlane *)M4OSA_32bitAlignedMalloc(sizeof(M4VIFI_ImagePlane),
-                0x00,(M4OSA_Char *)"framing buffer");
-        }
-
-        if (pSettings->xVSS.pFramingBuffer != M4OSA_NULL)
-        {
-             // OverFrame height and width
-            pSettings->xVSS.pFramingBuffer->u_width = pEnv->GetIntField(object,
-             fieldIds.width);
-
-            pSettings->xVSS.pFramingBuffer->u_height = pEnv->GetIntField(object,
-             fieldIds.height);
-
-            pSettings->xVSS.width = pSettings->xVSS.pFramingBuffer->u_width;
-            pSettings->xVSS.height = pSettings->xVSS.pFramingBuffer->u_height;
-            pSettings->xVSS.rgbType = M4VSS3GPP_kRGB565;
-
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "pFramingBuffer u_width %d ", pSettings->xVSS.pFramingBuffer->u_width);
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                    "pFramingBuffer u_height %d", pSettings->xVSS.pFramingBuffer->u_height);
-
-        }
-
-        // Check if settings could be set.
-        if (!(*pResult))
-        {
-            // Free the settings.
-            videoEditClasses_freeEffectSettings(pSettings);
-        }
-    }
-}
-
-void
-videoEditClasses_freeEffectSettings(
-                M4VSS3GPP_EffectSettings*           pSettings)
-{
-    // Check if memory was allocated for the EffectSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "videoEditClasses_freeEffectSettings()");
-
-        // Free the data used by the font engine (size, color...).
-        videoEditOsal_free(pSettings->xVSS.pRenderingData);
-        pSettings->xVSS.pRenderingData = M4OSA_NULL;
-
-        // Free the text buffer.
-        videoEditOsal_free(pSettings->xVSS.pTextBuffer);
-        pSettings->xVSS.pTextBuffer = M4OSA_NULL;
-        pSettings->xVSS.textBufferSize = 0;
-
-        // Free the framing file path.
-        videoEditOsal_free(pSettings->xVSS.pFramingFilePath);
-        pSettings->xVSS.pFramingFilePath = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logEffectSettings(
-                M4VSS3GPP_EffectSettings*           pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the EffectSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiStartTime:                %u ms", indentation, ' ',
-            (unsigned int)pSettings->uiStartTime);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiDuration:                 %u ms", indentation, ' ',
-            (unsigned int)pSettings->uiDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c VideoEffectType:            %s",    indentation, ' ',
-            videoEditJava_getVideoEffectString(pSettings->VideoEffectType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-             "%*c ExtVideoEffectFct:          %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->ExtVideoEffectFct) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pExtVideoEffectFctCtxt:     %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->pExtVideoEffectFctCtxt) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c AudioEffectType:            %s",    indentation, ' ',
-            videoEditJava_getAudioEffectString(pSettings->AudioEffectType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiStartPercent:             %u %%", indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiStartPercent);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiDurationPercent:          %u %%", indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiDurationPercent);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pFramingFilePath:           %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->xVSS.pFramingFilePath) ?\
-             (char*)pSettings->xVSS.pFramingFilePath : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pFramingBuffer:             %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->xVSS.pFramingBuffer) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c topleft_x:                  %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.topleft_x);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c topleft_y:                  %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.topleft_y);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c bResize:                    %s",    indentation, ' ',
-            pSettings->xVSS.bResize ? "true" : "false");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pTextBuffer:                %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->xVSS.pTextBuffer) ?\
-             (char*)pSettings->xVSS.pTextBuffer : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c textBufferSize:             %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.textBufferSize);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c pRenderingData:             %s",    indentation, ' ',
-            (M4OSA_NULL != pSettings->xVSS.pRenderingData) ?\
-             (char*)pSettings->xVSS.pRenderingData : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiTextBufferWidth:          %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiTextBufferWidth);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-             "%*c uiTextBufferHeight:         %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiTextBufferHeight);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiFiftiesOutFrameRate:      %u",    indentation, ' ',
-            (unsigned int)pSettings->xVSS.uiFiftiesOutFrameRate);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uiRgb16InputColor:          %d",    indentation, ' ',
-            pSettings->xVSS.uiRgb16InputColor);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uialphaBlendingStart:       %d %%", indentation, ' ',
-            pSettings->xVSS.uialphaBlendingStart);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uialphaBlendingMiddle:      %d %%", indentation, ' ',
-            pSettings->xVSS.uialphaBlendingMiddle);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uialphaBlendingEnd:         %d %%", indentation, ' ',
-            pSettings->xVSS.uialphaBlendingEnd);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uialphaBlendingFadeInTime:  %d %%", indentation, ' ',
-            pSettings->xVSS.uialphaBlendingFadeInTime);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c uialphaBlendingFadeOutTime: %d %%", indentation, ' ',
-            pSettings->xVSS.uialphaBlendingFadeOutTime);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_getSlideTransitionSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_SlideTransitionSettings**    ppSettings)
-{
-    VideoEditJava_SlideTransitionSettingsFieldIds fieldIds  = {NULL};
-    M4xVSS_SlideTransitionSettings*       pSettings = M4OSA_NULL;
-    bool                                  converted = true;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "videoEditClasses_getSlideTransitionSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getSlideTransitionSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-
-    // Only validate the SlideTransitionSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the clip is set.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    "slideSettings is null");
-    }
-
-    // Only retrieve the SlideTransitionSettings if the fields could be located and validated.
-    if (*pResult)
-    {
-        // Allocate memory for the SlideTransitionSettings.
-        pSettings = (M4xVSS_SlideTransitionSettings*)videoEditOsal_alloc(pResult, pEnv,
-                sizeof(M4xVSS_SlideTransitionSettings), "SlideTransitionSettings");
-
-        // Check if memory could be allocated for the SlideTransitionSettings.
-        if (*pResult)
-        {
-            // Set the direction of the slide.
-            pSettings->direction =
-                    (M4xVSS_SlideTransition_Direction)videoEditJava_getSlideDirectionJavaToC(
-                            &converted, pEnv->GetIntField(object, fieldIds.direction));
-
-            // Check if the direction is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                    !converted, "slideSettings.direction is invalid");
-        }
-
-        // Check if settings could be set.
-        if (*pResult)
-        {
-            // Return the settings.
-            (*ppSettings) = pSettings;
-        }
-        else
-        {
-            // Free the settings.
-            videoEditClasses_freeSlideTransitionSettings(&pSettings);
-        }
-    }
-}
-
-void
-videoEditClasses_freeSlideTransitionSettings(
-                M4xVSS_SlideTransitionSettings**    ppSettings)
-{
-    // Check if memory was allocated for the SlideTransitionSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                "videoEditClasses_freeSlideTransitionSettings()");
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logSlideTransitionSettings(
-                M4xVSS_SlideTransitionSettings*     pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the SlideTransitionSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c direction: %s", indentation, ' ',
-            videoEditJava_getSlideDirectionString(pSettings->direction));
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_getTransitionSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_TransitionSettings**      ppSettings)
-{
-
-    VideoEditJava_TransitionSettingsFieldIds fieldIds;
-    jobject                          alphaSettings = NULL;
-    jobject                          slideSettings = NULL;
-    M4VSS3GPP_TransitionSettings*    pSettings     = M4OSA_NULL;
-    bool                             converted     = true;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_TransitionSettingsFieldIds));
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-               "videoEditClasses_getTransitionSettings()");
-
-        // Retrieve the field ids.
-        videoEditJava_getTransitionSettingsFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only validate the TransitionSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Check if the transition is set.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    "transition is null");
-    }
-
-    // Check if the field ids could be located and validated.
-    if (*pResult)
-    {
-        // Retrieve the alphaSettings.
-        videoEditJava_getObject(pResult, pEnv, object, fieldIds.alphaSettings, &alphaSettings);
-
-        // Retrieve the slideSettings.
-        videoEditJava_getObject(pResult, pEnv, object, fieldIds.slideSettings, &slideSettings);
-    }
-
-    // Only retrieve the TransitionSettings if the fields could be located.
-    if (*pResult)
-    {
-        // Allocate memory for the TransitionSettings.
-        pSettings = (M4VSS3GPP_TransitionSettings*)videoEditOsal_alloc(pResult,
-                pEnv, sizeof(M4VSS3GPP_TransitionSettings), "TransitionSettings");
-
-        // Check if memory could be allocated for the TransitionSettings.
-        if (*pResult)
-        {
-            // Set the duration of the transition, in milliseconds (set to 0 to get no transition).
-            pSettings->uiTransitionDuration = (M4OSA_UInt32)pEnv->GetIntField(object,
-                    fieldIds.duration);
-
-            // Set the type of the video transition.
-            pSettings->VideoTransitionType =
-                    (M4VSS3GPP_VideoTransitionType)videoEditJava_getVideoTransitionJavaToC(
-                             &converted, pEnv->GetIntField(object, fieldIds.videoTransitionType));
-
-            // Check if the video transition type is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
-                            "transition.videoTransitionType is invalid");
-        }
-
-        // Check if the video transition type could be set.
-        if (*pResult)
-        {
-            // Set the external transition video effect function.
-            pSettings->ExtVideoTransitionFct = M4OSA_NULL;
-
-            // Set the context of the external transition video effect function.
-            pSettings->pExtVideoTransitionFctCtxt = M4OSA_NULL;
-
-            // Set the type of the audio transition.
-            pSettings->AudioTransitionType =
-                    (M4VSS3GPP_AudioTransitionType)videoEditJava_getAudioTransitionJavaToC(
-                            &converted, pEnv->GetIntField(object, fieldIds.audioTransitionType));
-
-            // Check if the audio transition type is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
-                             "transition.audioTransitionType is invalid");
-        }
-
-        // Check if the audio transition type could be set.
-        if (*pResult)
-        {
-            // Set the transition behaviour.
-            pSettings->TransitionBehaviour =
-                    (M4VSS3GPP_TransitionBehaviour)videoEditJava_getTransitionBehaviourJavaToC(
-                            &converted, pEnv->GetIntField(object, fieldIds.transitionBehaviour));
-
-            // Check if the transition behaviour is valid.
-            videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, !converted,
-                                                    "transition.transitionBehaviour is invalid");
-        }
-
-        // Check if the audio transition behaviour could be set.
-        if (*pResult)
-        {
-            // Check if a slide transition or alpha magic setting object is expected.
-            if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
-            {
-                // Set the slide transition settings.
-                videoEditClasses_getSlideTransitionSettings(pResult, pEnv, slideSettings,
-                                     &pSettings->xVSS.transitionSpecific.pSlideTransitionSettings);
-            }
-            else if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_AlphaMagic)
-            {
-                // Set the alpha magic settings.
-                videoEditClasses_getAlphaMagicSettings(pResult, pEnv, alphaSettings,
-                                  &pSettings->xVSS.transitionSpecific.pAlphaMagicSettings);
-            }
-        }
-
-        // Check if settings could be set.
-        if (*pResult)
-        {
-            // Return the settings.
-            (*ppSettings) = pSettings;
-        }
-        else
-        {
-            // Free the settings.
-            videoEditClasses_freeTransitionSettings(&pSettings);
-        }
-    }
-}
-
-void
-videoEditClasses_freeTransitionSettings(
-                M4VSS3GPP_TransitionSettings**      ppSettings)
-{
-    // Check if memory was allocated for the TransitionSettings.
-    if (M4OSA_NULL != (*ppSettings))
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "videoEditClasses_freeTransitionSettings()");
-
-        // Check if a slide transition or alpha magic setting structure is expected.
-        if ((int)(*ppSettings)->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
-        {
-            // Free the slide transition settings.
-            videoEditClasses_freeSlideTransitionSettings(
-                               &(*ppSettings)->xVSS.transitionSpecific.pSlideTransitionSettings);
-        }
-        else
-        {
-            // Free the alpha magic settings.
-            videoEditClasses_freeAlphaMagicSettings(
-                              &(*ppSettings)->xVSS.transitionSpecific.pAlphaMagicSettings);
-        }
-
-        // Free the settings structure.
-        videoEditOsal_free((*ppSettings));
-        (*ppSettings) = M4OSA_NULL;
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logTransitionSettings(
-                M4VSS3GPP_TransitionSettings*       pSettings,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the TransitionSettings.
-    if (M4OSA_NULL != pSettings)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "%*c uiTransitionDuration:       %u ms", indentation, ' ',
-                                  (unsigned int)pSettings->uiTransitionDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                           "%*c VideoTransitionType:        %s",    indentation, ' ',
-                           videoEditJava_getVideoTransitionString(pSettings->VideoTransitionType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                              "%*c ExtVideoTransitionFct:      %s",    indentation, ' ',
-                              (M4OSA_NULL != pSettings->ExtVideoTransitionFct) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                         "%*c pExtVideoTransitionFctCtxt: %s",    indentation, ' ',
-                         (M4OSA_NULL != pSettings->pExtVideoTransitionFctCtxt) ? "set" : "<null>");
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                         "%*c AudioTransitionType:        %s",    indentation, ' ',
-                          videoEditJava_getAudioTransitionString(pSettings->AudioTransitionType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                      "%*c TransitionBehaviour:        %s",    indentation, ' ',
-                      videoEditJava_getTransitionBehaviourString(pSettings->TransitionBehaviour));
-
-        // Check if a slide transition or alpha magic setting structure is expected.
-        if ((int)pSettings->VideoTransitionType == M4xVSS_kVideoTransitionType_SlideTransition)
-        {
-            // Log the slide transition settings.
-            VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                                   "%*c pSlideTransitionSettings:", indentation, ' ');
-            videoEditClasses_logSlideTransitionSettings\
-            (pSettings->xVSS.transitionSpecific.pSlideTransitionSettings,
-            indentation + VIDEOEDIT_LOG_INDENTATION);
-        }
-        else
-        {
-            // Log the alpha magic settings.
-            VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                                   "%*c pAlphaMagicSettings:", indentation, ' ');
-            videoEditClasses_logAlphaMagicSettings\
-            (pSettings->xVSS.transitionSpecific.pAlphaMagicSettings,
-            indentation + VIDEOEDIT_LOG_INDENTATION);
-        }
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditPropClass_logProperties(
-                VideoEditPropClass_Properties*                   pProperties,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the Properties.
-    if (M4OSA_NULL != pProperties)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiClipDuration:                   %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipDuration);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c FileType:                         %s",       indentation, ' ',
-            videoEditJava_getFileTypeString(pProperties->FileType));
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c VideoStreamType:                  %s",       indentation, ' ',
-            videoEditJava_getVideoFormatString(pProperties->VideoStreamType));
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiClipVideoDuration:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipVideoDuration);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiVideoBitrate:                   %s",       indentation, ' ',
-            videoEditJava_getBitrateString(pProperties->uiVideoBitrate));
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiVideoWidth:                     %u",       indentation, ' ',
-            (unsigned int)pProperties->uiVideoWidth);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiVideoHeight:                    %u",       indentation, ' ',
-            (unsigned int)(unsigned int)pProperties->uiVideoHeight);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c fAverageFrameRate:                %.3f",     indentation, ' ',
-            pProperties->fAverageFrameRate);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c AudioStreamType:                  %s",       indentation, ' ',
-            videoEditJava_getAudioFormatString(pProperties->AudioStreamType));
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiClipAudioDuration:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiClipAudioDuration);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiAudioBitrate:                   %s",       indentation, ' ',
-            videoEditJava_getBitrateString(pProperties->uiAudioBitrate));
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c uiNbChannels:                     %u",       indentation, ' ',
-            (unsigned int)pProperties->uiNbChannels);
-
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-             "%*c uiSamplingFrequency:              %u",       indentation, ' ',
-            (unsigned int)pProperties->uiSamplingFrequency);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_PROP_CLASSES",
-            "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void
-videoEditClasses_createVersion(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                M4_VersionInfo*                     pVersionInfo,
-                jobject*                            pObject)
-{
-
-    VideoEditJava_VersionFieldIds fieldIds;
-    jclass                clazz    = NULL;
-    jobject               object   = NULL;
-    memset(&fieldIds, 0, sizeof(VideoEditJava_VersionFieldIds));
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "videoEditClasses_createVersion()");
-
-        // Retrieve the class.
-        videoEditJava_getVersionClass(pResult, pEnv, &clazz);
-
-        // Retrieve the field ids.
-        videoEditJava_getVersionFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Only create an object if the class and fields could be located.
-    if (*pResult)
-    {
-        // Allocate a new object.
-        object = pEnv->AllocObject(clazz);
-
-        // check if alloc is done
-        videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
-                                                    (NULL == object),
-                                                    M4ERR_ALLOC);
-        if (NULL != object)
-        {
-            // Set the major field.
-            pEnv->SetIntField(object, fieldIds.major, pVersionInfo->m_major);
-
-            // Set the minor field.
-            pEnv->SetIntField(object, fieldIds.minor, pVersionInfo->m_minor);
-
-            // Set the revision field.
-            pEnv->SetIntField(object, fieldIds.revision, pVersionInfo->m_revision);
-
-            // Return the object.
-            (*pObject) = object;
-        }
-    }
-}
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-void
-videoEditClasses_logVersion(
-                M4_VersionInfo*                     pVersionInfo,
-                int                                 indentation)
-{
-    // Check if memory was allocated for the Version.
-    if (M4OSA_NULL != pVersionInfo)
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                             "%*c major:    %u ms", indentation, ' ',
-                             (unsigned int)pVersionInfo->m_major);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                              "%*c minor:    %u",    indentation, ' ',
-                              (unsigned int)pVersionInfo->m_minor);
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                             "%*c revision: %u",    indentation, ' ',
-                             (unsigned int)pVersionInfo->m_revision);
-    }
-    else
-    {
-        VIDEOEDIT_LOG_SETTING(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                              "%*c <null>", indentation, ' ');
-    }
-}
-#endif
-
-
-void*
-videoEditClasses_getContext(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object)
-{
-    void*                pContext = M4OSA_NULL;
-    jclass               clazz    = NULL;
-    VideoEditJava_EngineFieldIds fieldIds = {NULL};
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "videoEditClasses_getContext()");
-
-        // Retrieve the class.
-        videoEditJava_getEngineClass(pResult, pEnv, &clazz);
-
-        // Retrieve the field ids.
-        videoEditJava_getEngineFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Check if the class and field ids could be located.
-    if (*pResult)
-    {
-        // Retrieve the context pointer.
-        pContext = (void *)pEnv->GetLongField(object, fieldIds.context);
-    }
-
-    // Return the context pointer.
-    return(pContext);
-}
-
-void
-videoEditClasses_setContext(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                void*                               pContext)
-{
-    jclass               clazz    = NULL;
-    VideoEditJava_EngineFieldIds fieldIds = {NULL};
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                               "videoEditClasses_setContext()");
-
-        // Retrieve the class.
-        videoEditJava_getEngineClass(pResult, pEnv, &clazz);
-
-        // Retrieve the field ids.
-        videoEditJava_getEngineFieldIds(pResult, pEnv, &fieldIds);
-    }
-
-    // Check if the class and field ids could be located.
-    if (*pResult)
-    {
-        // Set the context field.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                        "The context value from JAVA before setting is = %p",
-                        (void *)pEnv->GetLongField(object, fieldIds.context));
-
-        pEnv->SetLongField(object, fieldIds.context, (jlong)pContext);
-        M4OSA_TRACE1_1("The context value in JNI is = %p",pContext);
-
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_CLASSES",
-                         "The context value from JAVA after setting is = %p",
-                         (void *)pEnv->GetLongField(object, fieldIds.context));
-    }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorClasses.h b/media/jni/mediaeditor/VideoEditorClasses.h
deleted file mode 100644
index a4c82a8..0000000
--- a/media/jni/mediaeditor/VideoEditorClasses.h
+++ /dev/null
@@ -1,603 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_CLASSES_H
-#define VIDEO_EDITOR_CLASSES_H
-
-#include <VideoEditorJava.h>
-#include <VideoEditorClasses.h>
-/**
- ************************************************************************
- * @file        VideoEditorClasses.h
- * @brief       Interface for JNI methods/defines that have specific
- *              access to class, objects and method Ids defined in Java layer
- ************************************************************************
-*/
-
-
-extern "C" {
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-};
-
-/*
- * Java layer class/object name strings
- */
-#define PACKAGE_NAME                           "android/media/videoeditor"
-
-#define MANUAL_EDIT_ENGINE_CLASS_NAME          PACKAGE_NAME"/MediaArtistNativeHelper"
-#define MEDIA_PROPERTIES_ENGINE_CLASS_NAME     PACKAGE_NAME"/MediaArtistNativeHelper"
-
-#define AUDIO_FORMAT_CLASS_NAME                MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioFormat"
-#define RESULTS_CLASS_NAME                     MANUAL_EDIT_ENGINE_CLASS_NAME"$Results"
-#define VERSION_CLASS_NAME                     MANUAL_EDIT_ENGINE_CLASS_NAME"$Version"
-#define AUDIO_SAMPLING_FREQUENCY_CLASS_NAME    MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioSamplingFrequency"
-#define BITRATE_CLASS_NAME                     MANUAL_EDIT_ENGINE_CLASS_NAME"$Bitrate"
-#define ERROR_CLASS_NAME                       MANUAL_EDIT_ENGINE_CLASS_NAME"$Result"
-#define FILE_TYPE_CLASS_NAME                   MANUAL_EDIT_ENGINE_CLASS_NAME"$FileType"
-#define MEDIA_RENDERING_CLASS_NAME             MANUAL_EDIT_ENGINE_CLASS_NAME"$MediaRendering"
-#define VIDEO_FORMAT_CLASS_NAME                MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFormat"
-#define VIDEO_FRAME_RATE_CLASS_NAME            MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFrameRate"
-#define VIDEO_FRAME_SIZE_CLASS_NAME            MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoFrameSize"
-#define VIDEO_PROFILE_CLASS_NAME               MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoProfile"
-#define ALPHA_MAGIC_SETTINGS_CLASS_NAME        MANUAL_EDIT_ENGINE_CLASS_NAME"$AlphaMagicSettings"
-#define AUDIO_EFFECT_CLASS_NAME                MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioEffect"
-#define AUDIO_TRANSITION_CLASS_NAME            MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioTransition"
-#define BACKGROUND_MUSIC_SETTINGS_CLASS_NAME   MANUAL_EDIT_ENGINE_CLASS_NAME"$BackgroundMusicSettings"
-#define CLIP_SETTINGS_CLASS_NAME               MANUAL_EDIT_ENGINE_CLASS_NAME"$ClipSettings"
-#define EDIT_SETTINGS_CLASS_NAME               MANUAL_EDIT_ENGINE_CLASS_NAME"$EditSettings"
-#define EFFECT_SETTINGS_CLASS_NAME             MANUAL_EDIT_ENGINE_CLASS_NAME"$EffectSettings"
-#define SLIDE_DIRECTION_CLASS_NAME             MANUAL_EDIT_ENGINE_CLASS_NAME"$SlideDirection"
-#define SLIDE_TRANSITION_SETTINGS_CLASS_NAME   MANUAL_EDIT_ENGINE_CLASS_NAME"$SlideTransitionSettings"
-#define TRANSITION_BEHAVIOUR_CLASS_NAME        MANUAL_EDIT_ENGINE_CLASS_NAME"$TransitionBehaviour"
-#define TRANSITION_SETTINGS_CLASS_NAME         MANUAL_EDIT_ENGINE_CLASS_NAME"$TransitionSettings"
-#define VIDEO_EFFECT_CLASS_NAME                MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoEffect"
-#define VIDEO_TRANSITION_CLASS_NAME            MANUAL_EDIT_ENGINE_CLASS_NAME"$VideoTransition"
-#define PREVIEW_CLIPS_CLASS_NAME               MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewClips"
-#define PREVIEW_SETTING_CLASS_NAME             MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewSettings"
-#define PREVIEW_PROPERTIES_CLASS_NAME          MANUAL_EDIT_ENGINE_CLASS_NAME"$PreviewClipProperties"
-#define AUDIO_SETTINGS_CLASS_NAME              MANUAL_EDIT_ENGINE_CLASS_NAME"$AudioSettings"
-#define PROPERTIES_CLASS_NAME                  MANUAL_EDIT_ENGINE_CLASS_NAME"$Properties"
-
-#define TASK_IDLE                                   0
-#define TASK_LOADING_SETTINGS                       1
-#define TASK_ENCODING                               2
-
-/*
- * File type enum
- */
-typedef enum
-{
-    VideoEditClasses_kFileType_3GPP,
-    VideoEditClasses_kFileType_MP4,
-    VideoEditClasses_kFileType_AMR,
-    VideoEditClasses_kFileType_MP3,
-    VideoEditClasses_kFileType_PCM,
-    VideoEditClasses_kFileType_JPG,
-    VideoEditClasses_kFileType_BMP,
-    VideoEditClasses_kFileType_GIF,
-    VideoEditClasses_kFileType_PNG,
-    VideoEditClasses_kFileType_ARGB8888,
-    VideoEditClasses_kFileType_M4V,
-    VideoEditClasses_kFileType_Unsupported
-} VideoEditClasses_FileType;
-
-/*
- * Alpha magic transition structure
- */
-typedef struct
-{
-    jfieldID file;
-    jfieldID blendingPercent;
-    jfieldID invertRotation;
-    jfieldID rgbWidth;
-    jfieldID rgbHeight;
-} VideoEditJava_AlphaMagicFieldIds;
-
-typedef struct
-{
-    jfieldID file;
-    jfieldID fileType;
-    jfieldID insertionTime;
-    jfieldID volumePercent;
-    jfieldID beginLoop;
-    jfieldID endLoop;
-    jfieldID enableDucking;
-    jfieldID duckingThreshold;
-    jfieldID lowVolume;
-    jfieldID isLooping;
-} VideoEditJava_BackgroundMusicFieldIds;
-/*
- * Structure to hold media properties from native layer
- */
-typedef struct {
-    M4OSA_UInt32 uiClipDuration;
-    VideoEditClasses_FileType  FileType;
-    M4VIDEOEDITING_VideoFormat VideoStreamType;
-    M4OSA_UInt32 uiClipVideoDuration;
-    M4OSA_UInt32 uiVideoBitrate;
-    M4OSA_UInt32 uiVideoWidth;
-    M4OSA_UInt32 uiVideoHeight;
-    M4OSA_Float  fAverageFrameRate;
-    M4OSA_UInt32 uiVideoProfile; /**< H263 or MPEG-4 or H264 profile(from core decoder) */
-    M4OSA_UInt32 uiVideoLevel;   /**< H263 or MPEG-4 or H264 level*/
-    M4OSA_Bool bProfileSupported;
-    M4OSA_Bool bLevelSupported;
-    M4VIDEOEDITING_AudioFormat AudioStreamType;
-    M4OSA_UInt32 uiClipAudioDuration;
-    M4OSA_UInt32 uiAudioBitrate;
-    M4OSA_UInt32 uiNbChannels;
-    M4OSA_UInt32 uiSamplingFrequency;
-    M4OSA_UInt32 uiRotation;
-} VideoEditPropClass_Properties;
-
-typedef struct
-{
-    jfieldID duration;
-    jfieldID fileType;
-    jfieldID videoFormat;
-    jfieldID videoDuration;
-    jfieldID videoBitrate;
-    jfieldID width;
-    jfieldID height;
-    jfieldID averageFrameRate;
-    jfieldID profile;
-    jfieldID level;
-    jfieldID profileSupported;
-    jfieldID levelSupported;
-    jfieldID audioFormat;
-    jfieldID audioDuration;
-    jfieldID audioBitrate;
-    jfieldID audioChannels;
-    jfieldID audioSamplingFrequency;
-    jfieldID videoRotation;
-} VideoEditJava_PropertiesFieldIds;
-
-
-typedef struct
-{
-    jfieldID clipPath;
-    jfieldID fileType;
-    jfieldID beginCutTime;
-    jfieldID endCutTime;
-    jfieldID beginCutPercent;
-    jfieldID endCutPercent;
-    jfieldID panZoomEnabled;
-    jfieldID panZoomPercentStart;
-    jfieldID panZoomTopLeftXStart;
-    jfieldID panZoomTopLeftYStart;
-    jfieldID panZoomPercentEnd;
-    jfieldID panZoomTopLeftXEnd;
-    jfieldID panZoomTopLeftYEnd;
-    jfieldID mediaRendering;
-    jfieldID rgbFileWidth;
-    jfieldID rgbFileHeight;
-    jfieldID rotationDegree;
-} VideoEditJava_ClipSettingsFieldIds;
-
-typedef struct
-{
-    jfieldID clipSettingsArray;
-    jfieldID transitionSettingsArray;
-    jfieldID effectSettingsArray;
-    jfieldID videoFrameRate;
-    jfieldID outputFile;
-    jfieldID videoFrameSize;
-    jfieldID videoFormat;
-    jfieldID videoProfile;
-    jfieldID videoLevel;
-    jfieldID audioFormat;
-    jfieldID audioSamplingFreq;
-    jfieldID maxFileSize;
-    jfieldID audioChannels;
-    jfieldID videoBitrate;
-    jfieldID audioBitrate;
-    jfieldID backgroundMusicSettings;
-    jfieldID primaryTrackVolume;
-} VideoEditJava_EditSettingsFieldIds;
-
-
-typedef struct
-{
-    jfieldID startTime;
-    jfieldID duration;
-    jfieldID videoEffectType;
-    jfieldID audioEffectType;
-    jfieldID startPercent;
-    jfieldID durationPercent;
-    jfieldID framingFile;
-    jfieldID framingBuffer;
-    jfieldID bitmapType;
-    jfieldID width;
-    jfieldID height;
-    jfieldID topLeftX;
-    jfieldID topLeftY;
-    jfieldID framingResize;
-    jfieldID framingScaledSize;
-    jfieldID text;
-    jfieldID textRenderingData;
-    jfieldID textBufferWidth;
-    jfieldID textBufferHeight;
-    jfieldID fiftiesFrameRate;
-    jfieldID rgb16InputColor;
-    jfieldID alphaBlendingStartPercent;
-    jfieldID alphaBlendingMiddlePercent;
-    jfieldID alphaBlendingEndPercent;
-    jfieldID alphaBlendingFadeInTimePercent;
-    jfieldID alphaBlendingFadeOutTimePercent;
-} VideoEditJava_EffectSettingsFieldIds;
-
-typedef struct
-{
-    jfieldID context;
-} VideoEditJava_EngineFieldIds;
-
-typedef struct
-{
-    jfieldID direction;
-} VideoEditJava_SlideTransitionSettingsFieldIds;
-
-typedef struct
-{
-    jfieldID duration;
-    jfieldID videoTransitionType;
-    jfieldID audioTransitionType;
-    jfieldID transitionBehaviour;
-    jfieldID alphaSettings;
-    jfieldID slideSettings;
-} VideoEditJava_TransitionSettingsFieldIds;
-
-typedef struct
-{
-    jfieldID major;
-    jfieldID minor;
-    jfieldID revision;
-} VideoEditJava_VersionFieldIds;
-
-
-typedef struct
-{
-    jmethodID onProgressUpdate;
-} VideoEditJava_EngineMethodIds;
-
-
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioEffect           )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioFormat           )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioSamplingFrequency)
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(AudioTransition       )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Bitrate               )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Engine                )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(Error                 )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(FileType              )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(MediaRendering        )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(SlideDirection        )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(TransitionBehaviour   )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoEffect           )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFormat           )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFrameRate        )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoFrameSize        )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoProfile          )
-VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(VideoTransition       )
-
-
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(AlphaMagic               )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(BackgroundMusic          )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(ClipSettings             )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(ClipSettings             )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(EditSettings             )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(EffectSettings           )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(Engine                   )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(SlideTransitionSettings  )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(TransitionSettings       )
-VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(Version                  )
-
-VIDEOEDIT_JAVA_DECLARE_METHOD_CLASS(Engine                  )
-
-/*
- * Init all Edit settings related structures
- */
-void
-videoEditClasses_init(
-                bool*                               pResult,
-                JNIEnv*                             pEnv);
-/**
- ************************************************************************
- * @brief    Media Properties init function.
- * @param    pResult    (OUT) Pointer to hold result
- * @param    pEnv       (IN)  JVM Interface pointer
- ************************************************************************
-*/
-void
-videoEditPropClass_init(
-                bool*                               pResult,
-                JNIEnv*                             pEnv);
-/**
- ************************************************************************
- * @brief    Interface to populate Media Properties.
- * @param    pResult        (IN/OUT)    Pointer to hold result
- * @param    pEnv           (IN)        JVM Interface pointer
- * @param    pProperties    (IN)        Media propeties structure pointer
- * @param    pObject        (OUT)       Java object to hold media
- *                                      properties for java layer.
- ************************************************************************
-*/
-void
-videoEditPropClass_createProperties(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditPropClass_Properties*      pProperties,
-                jobject*                            pObject);
-
-/**
- ************************************************************************
- * @brief    Interface to log/display media properties.
- * @param    pProperties    (IN) Pointer holding media properties
- * @param    indentation    (IN) Indentation to follow in display
- ************************************************************************
-*/
-void
-videoEditPropClass_logProperties(
-                VideoEditPropClass_Properties*      pProperties,
-                int                                 indentation);
-
-/*
- * Get alpha magic transition settings
- */
-void
-videoEditClasses_getAlphaMagicSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_AlphaMagicSettings**         ppSettings);
-
-/*
- * Free alpha magic transition settings structure
- */
-void
-videoEditClasses_freeAlphaMagicSettings(
-                M4xVSS_AlphaMagicSettings**         ppSettings);
-
-/*
- * Log alpha magic transition settings
- */
-void
-videoEditClasses_logAlphaMagicSettings(
-                M4xVSS_AlphaMagicSettings*          pSettings,
-                int                                 indentation);
-
-/*
- * Get Background Track settings
- */
-void
-videoEditClasses_getBackgroundMusicSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_BGMSettings**                ppSettings);
-
-/*
- * Free Background Track settings structure
- */
-void
-videoEditClasses_freeBackgroundMusicSettings(
-                M4xVSS_BGMSettings**                ppSettings);
-
-/*
- * Log Background Track settings
- */
-void
-videoEditClasses_logBackgroundMusicSettings(
-                M4xVSS_BGMSettings*                 pSettings,
-                int                                 indentation);
-
-/*
- * Log clip properties
- */
-void
-videoEditClasses_logClipProperties(
-                M4VIDEOEDITING_ClipProperties*      pProperties,
-                int                                 indentation);
-
-/*
- * Get clip settings from Java
- */
-void
-videoEditClasses_getClipSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_ClipSettings**            ppSettings);
-/**
- ************************************************************************
- * @brief   Interface function to retrieve media properties for a given
- *          file.
- * @param   pEnv    (IN)    Pointer holding media properties
- * @param   thiz    (IN)    Indentation to follow in display
- * @param   file    (IN)    File path for which media properties has
- *                          to be retrieved.
- ************************************************************************
-*/
-jobject
-videoEditProp_getProperties(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             file);
-
-/*
- * Create/Set the clip settings to java Object
- */
-void
-videoEditClasses_createClipSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                M4VSS3GPP_ClipSettings*             pSettings,
-                jobject*                            pObject);
-
-/*
- * Free clip settings structure
- */
-void
-videoEditClasses_freeClipSettings(
-                M4VSS3GPP_ClipSettings**            ppSettings);
-
-/*
- * Log clip settings structure
- */
-void
-videoEditClasses_logClipSettings(
-                M4VSS3GPP_ClipSettings*             pSettings,
-                int                                 indentation);
-
-/*
- * Get Edit settings from Java
- */
-void
-videoEditClasses_getEditSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_EditSettings**            ppSettings,
-                bool                                flag);
-
-/*
- * Free Edit Settings structure
- */
-void
-videoEditClasses_freeEditSettings(
-                M4VSS3GPP_EditSettings**            ppSettings);
-
-/*
- * Log Edit settings structure
- */
-void
-videoEditClasses_logEditSettings(
-                M4VSS3GPP_EditSettings*             pSettings,
-                int                                 indentation);
-
-/*
- * Get Effect settings from Java
- */
-void
-videoEditClasses_getEffectSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_EffectSettings*           pSettings);
-
-/*
- * Free Effect settings structure
- */
-void
-videoEditClasses_freeEffectSettings(
-                M4VSS3GPP_EffectSettings*           pSettings);
-
-/*
- * Log Effect settings
- */
-void
-videoEditClasses_logEffectSettings(
-                M4VSS3GPP_EffectSettings*           pSettings,
-                int                                 indentation);
-
-/*
- * Get Transition-Sliding settings from Java
- */
-void
-videoEditClasses_getSlideTransitionSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4xVSS_SlideTransitionSettings**    ppSettings);
-
-/*
- * Free Transition-Sliding structure
- */
-void
-videoEditClasses_freeSlideTransitionSettings(
-                M4xVSS_SlideTransitionSettings**    ppSettings);
-
-/*
- * Free Transition-Sliding structure
- */
-void
-videoEditClasses_logSlideTransitionSettings(
-                M4xVSS_SlideTransitionSettings*     pSettings,
-                int                                 indentation);
-
-/*
- * Get Transition settings from Java
- */
-void
-videoEditClasses_getTransitionSettings(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                M4VSS3GPP_TransitionSettings**      ppSettings);
-
-/*
- * Free Transition settings structure
- */
-void
-videoEditClasses_freeTransitionSettings(
-                M4VSS3GPP_TransitionSettings**      ppSettings);
-
-/*
- * Log Transition settings
- */
-void
-videoEditClasses_logTransitionSettings(
-                M4VSS3GPP_TransitionSettings*       pSettings,
-                int                                 indentation);
-
-/*
- * Set version information to Java object
- */
-void
-videoEditClasses_createVersion(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                M4_VersionInfo*                     pVersionInfo,
-                jobject*                            pObject);
-
-/*
- * Log Version information
- */
-void
-videoEditClasses_logVersion(
-                M4_VersionInfo*                     pVersionInfo,
-                int                                 indentation);
-
-
-void*
-videoEditClasses_getContext(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object);
-
-void
-videoEditClasses_setContext(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                void*                               pContext);
-
-
-#endif // VIDEO_EDITOR_CLASSES_H
-
diff --git a/media/jni/mediaeditor/VideoEditorJava.cpp b/media/jni/mediaeditor/VideoEditorJava.cpp
deleted file mode 100644
index fde0fb5..0000000
--- a/media/jni/mediaeditor/VideoEditorJava.cpp
+++ /dev/null
@@ -1,901 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorJava"
-
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_CharStar.h>
-};
-
-
-void
-videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                const char*                         pMessage,
-                const char*                         pFile,
-                int                                 lineNo)
-{
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the condition is true.
-        if (condition)
-        {
-            // Log the exception.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",\
-                    "videoEditJava_checkAndThrowIllegalArgumentException, %s (%s:%d)",
-                    pMessage, pFile, lineNo);
-
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/IllegalArgumentException", pMessage);
-        }
-    }
-}
-
-void
-videoEditJava_checkAndThrowRuntimeExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                M4OSA_ERR                           result,
-                const char*                         pFile,
-                int                                 lineNo
-                )
-{
-    const char* pMessage = NULL;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the condition is true.
-        if (condition)
-        {
-            // Get the error string.
-            pMessage = videoEditJava_getErrorName(result);
-
-            // Log the exception.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_checkAndThrowRuntimeException, %s (%s:%d)",
-                    pMessage, pFile, lineNo);
-
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-        }
-    }
-}
-
-void
-videoEditJava_checkAndThrowIllegalStateExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                const char*                         pMessage,
-                const char*                         pFile,
-                int                                 lineNo
-                )
-{
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the condition is true.
-        if (condition)
-        {
-            // Log the exception.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_checkAndThrowIllegalStateException, %s (%s:%d)",
-                    pMessage, pFile, lineNo);
-
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/IllegalStateException", pMessage);
-        }
-    }
-}
-
-void
-videoEditJava_getClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const char*                         pName,
-                jclass*                             pClazz)
-{
-    // Only look for the class if locating the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_getClass(%s)", pName);
-
-        // Look up the class.
-        jclass clazz = pEnv->FindClass(pName);
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-
-        // Check if the class could be located.
-        if (NULL != clazz)
-        {
-            // Return the class.
-            (*pClazz) = clazz;
-        }
-        else
-        {
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Log the error.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_getClass, error: unable to locate class %s", pName);
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/ClassNotFoundException",
-                    "unable to locate class");
-        }
-    }
-}
-
-void
-videoEditJava_getMethodId(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jclass                              clazz,
-                const char*                         pName,
-                const char*                         pType,
-                jmethodID*                          pMethodId)
-{
-    // Only look for the class if locating the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_getMethodId(%s,%s)", pName, pType);
-
-        // Look up the method id.
-        jmethodID methodId = pEnv->GetMethodID(clazz, pName, pType);
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-
-        // Check if the method could be located.
-        if (NULL != methodId)
-        {
-            // Return the method id.
-            (*pMethodId) = methodId;
-        }
-        else
-        {
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Log the error.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_getMethodId, error: unable to locate method %s with type %s",
-                    pName, pType);
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/NoSuchMethodException", "unable to locate method");
-        }
-    }
-}
-
-void
-videoEditJava_getFieldId(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jclass                              clazz,
-                const char*                         pName,
-                const char*                         pType,
-                jfieldID*                           pFieldId)
-{
-    // Only look for the class if locating the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_getFieldId(%s,%s)", pName, pType);
-
-        // Look up the field id.
-        jfieldID fieldId = pEnv->GetFieldID(clazz, pName, pType);
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-
-        // Check if the field could be located.
-        if (NULL != fieldId)
-        {
-            // Return the field id.
-            (*pFieldId) = fieldId;
-        }
-        else
-        {
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Log the error.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_getFieldId, error: unable to locate field %s with type %s",
-                    pName, pType);
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/NoSuchFieldException", "unable to locate field");
-        }
-    }
-}
-
-void
-videoEditJava_getObject(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            objectFieldId,
-                jobject*                            pObject)
-{
-    // Only retrieve the array object and size if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-            "videoEditJava_getObject()");
-
-        // Retrieve the object.
-        (*pObject) = pEnv->GetObjectField(object, objectFieldId);
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-    }
-}
-
-void
-videoEditJava_getArray(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            arrayFieldId,
-                jobjectArray*                       pArray,
-                jsize*                              pArraySize)
-{
-    // Only retrieve the array object and size if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getArray()");
-
-        // Retrieve the array object.
-        jobjectArray array     = (jobjectArray)pEnv->GetObjectField(object, arrayFieldId);
-        jsize        arraySize = 0;
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-
-        // Check if the array could be retrieved.
-        if (NULL != array)
-        {
-            // Retrieve the array size.
-            arraySize = pEnv->GetArrayLength(array);
-        }
-
-        // Return the array and its size.
-        (*pArray)     = array;
-        (*pArraySize) = arraySize;
-    }
-}
-
-void*
-videoEditJava_getString(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            stringFieldId,
-                M4OSA_UInt32*                       pLength)
-{
-    void*        pString = M4OSA_NULL;
-    jstring      string  = NULL;
-    M4OSA_UInt32 length  = 0;
-    M4OSA_Char*  pLocal  = M4OSA_NULL;
-    M4OSA_ERR    result  = M4NO_ERROR;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA", "videoEditJava_getString()");
-
-        // Check if an object containing a string was specified.
-        if (NULL != stringFieldId)
-        {
-            // Retrieve the string object.
-            string = (jstring)pEnv->GetObjectField(object, stringFieldId);
-
-            // Clear any resulting exceptions.
-            pEnv->ExceptionClear();
-        }
-        else
-        {
-            // The string itself was specified.
-            string = (jstring)object;
-        }
-
-        // Check if the string could be retrieved.
-        if (NULL != string)
-        {
-            // Get a local copy of the string.
-            pLocal = (M4OSA_Char*)pEnv->GetStringUTFChars(string, M4OSA_NULL);
-            if (M4OSA_NULL != pLocal)
-            {
-                // Determine the length of the path
-                // (add one extra character for the zero terminator).
-                length = strlen((const char *)pLocal) + 1;
-
-                // Allocate memory for the string.
-                pString = videoEditOsal_alloc(pResult, pEnv, length, "String");
-                if (*pResult)
-                {
-                    // Copy the string.
-                    result = M4OSA_chrNCopy((M4OSA_Char*)pString, pLocal, length);
-
-                    // Check if the copy succeeded.
-                    videoEditJava_checkAndThrowRuntimeException(pResult, pEnv,
-                     (M4NO_ERROR != result), result);
-
-                    // Check if the string could not be copied.
-                    if (!(*pResult))
-                    {
-                        // Free the allocated memory.
-                        videoEditOsal_free(pString);
-                        pString = M4OSA_NULL;
-                    }
-                }
-
-                // Release the local copy of the string.
-                pEnv->ReleaseStringUTFChars(string, (const char *)pLocal);
-            }
-        }
-
-        // Check if the string was empty or could be copied.
-        if (*pResult)
-        {
-            // Check if the length was requested.
-            if (M4OSA_NULL != pLength)
-            {
-                // Return the length.
-                (*pLength) = length;
-            }
-        }
-
-        // Delete local references to avoid memory leaks
-        pEnv->DeleteLocalRef(string);
-    }
-
-    // Return the string.
-    return(pString);
-}
-
-void
-videoEditJava_getStaticIntField(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jclass                              clazz,
-                const char*                         pName,
-                int*                                pValue)
-{
-    // Only look for the class if locating the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_getStaticIntField(%s)", pName);
-
-        // Look up the field id.
-        jfieldID fieldId = pEnv->GetStaticFieldID(clazz, pName, "I");
-
-        // Clear any resulting exceptions.
-        pEnv->ExceptionClear();
-
-        // Check if the field could be located.
-        if (NULL != fieldId)
-        {
-            // Retrieve the field value.
-            (*pValue) = pEnv->GetStaticIntField(clazz, fieldId);
-
-            // Log the value.
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_getStaticIntField, %s = %d", pName, (*pValue));
-        }
-        else
-        {
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Log the error.
-            VIDEOEDIT_LOG_EXCEPTION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_JAVA",
-                    "videoEditJava_getStaticIntField, error: unable to locate field %s", pName);
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/NoSuchFieldException",
-                    "unable to locate static field");
-        }
-    }
-}
-
-void
-videoEditJava_initConstantClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_ConstantsClass*               pClass)
-{
-    bool   gotten = true;
-    jclass clazz  = NULL;
-    int    index  = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_initConstantClass(%s)", pClass->pName);
-
-        // Only initialize the class once.
-        if (!pClass->initialized)
-        {
-            // Look up the class.
-            videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
-            // Loop over the constants.
-            for (index = 0; index < pClass->count; index++)
-            {
-                // Look up the constant.
-                videoEditJava_getStaticIntField(pResult, pEnv, clazz,
-                                        pClass->pConstants[index].pName,
-                                        &pClass->pConstants[index].java);
-            }
-
-            // Check if all constants could be located.
-            if (*pResult)
-            {
-                // Set the initialized flag.
-                pClass->initialized = true;
-            }
-        }
-    }
-}
-
-const char*
-videoEditJava_getConstantClassName(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                VideoEditJava_UnknownConstant               unknown)
-{
-    const char* pName = M4OSA_NULL;
-    int         index = 0;
-
-    // Loop over the list with constants.
-    for (index = 0;
-         ((M4OSA_NULL == pName) && (index < pClass->count));
-         index++)
-    {
-        // Check if the specified value matches the c value of the constant.
-        if (value == pClass->pConstants[index].c)
-        {
-            // Set the name.
-            pName = pClass->pConstants[index].pName;
-        }
-    }
-
-    // Check if no constant was found.
-    if (M4OSA_NULL == pName)
-    {
-        // Check if a function was specified to handle this case.
-        if (M4OSA_NULL != unknown)
-        {
-            // Pass the constant to the specified unknown function.
-            pName = unknown(value);
-        }
-        else
-        {
-            // Set the description to a default value.
-            pName = "<unknown>";
-        }
-    }
-
-    // Return the result.
-    return(pName);
-}
-
-const char*
-videoEditJava_getConstantClassString(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                VideoEditJava_UnknownConstant               unknown)
-{
-    const char* pString = M4OSA_NULL;
-    int         index   = 0;
-
-    // Loop over the list with constants.
-    for (index = 0;
-         ((M4OSA_NULL == pString) && (index < pClass->count));
-         index++)
-    {
-        // Check if the specified value matches the c value of the constant.
-        if (value == pClass->pConstants[index].c)
-        {
-            // Set the description.
-            pString = pClass->pConstants[index].pDescription;
-        }
-    }
-
-    // Check if no constant was found.
-    if (M4OSA_NULL == pString)
-    {
-        // Check if a function was specified to handle this case.
-        if (M4OSA_NULL != unknown)
-        {
-            // Pass the constant to the specified unknown function.
-            pString = unknown(value);
-        }
-        else
-        {
-            // Set the description to a default value.
-            pString = "<unknown>";
-        }
-    }
-
-    // Return the result.
-    return(pString);
-}
-
-int
-videoEditJava_getConstantClassJavaToC(
-                bool*                               pResult,
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value)
-{
-    bool gotten = false;
-    int  index  = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Loop over the list with constants.
-        for (index = 0; ((!gotten) && (index < pClass->count)); index++)
-        {
-            // Check if the specified value matches the java value of the constant.
-            if (value == pClass->pConstants[index].java)
-            {
-                // Set the value to the c value.
-                value = pClass->pConstants[index].c;
-
-                // Set the gotten flag.
-                gotten = true;
-            }
-        }
-
-        // Check if the value was not found.
-        if (!gotten)
-        {
-            (*pResult) = false;
-        }
-    }
-
-    // Return the translated value.
-    return(value);
-}
-
-int
-videoEditJava_getConstantClassJavaToC(
-                bool*                               pResult,
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                int                                 unknown)
-{
-    bool gotten = false;
-    int  index  = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Loop over the list with constants.
-        for (index = 0; ((!gotten) && (index < pClass->count)); index++)
-        {
-            // Check if the specified value matches the java value of the constant.
-            if (value == pClass->pConstants[index].java)
-            {
-                // Set the value to the c value.
-                value = pClass->pConstants[index].c;
-
-                // Set the gotten flag.
-                gotten = true;
-            }
-        }
-
-        // If the constant was not found, look for the specified unknown.
-        if (!gotten)
-        {
-            // Set the value to the c value.
-            value = unknown;
-        }
-    }
-
-    // Return the translated value.
-    return(value);
-}
-
-int
-videoEditJava_getConstantClassCToJava(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value)
-{
-    bool gotten = false;
-    int  index  = 0;
-
-    // Loop over the list with constants.
-    for (index = 0; ((!gotten) && (index < pClass->count)); index++)
-    {
-        // Check if the specified value matches the c value of the constant.
-        if (value == pClass->pConstants[index].c)
-        {
-            // Set the value to the java value.
-            value = pClass->pConstants[index].java;
-
-            // Set the gotten flag.
-            gotten = true;
-        }
-    }
-
-    // Return the translated value.
-    return(value);
-}
-
-int
-videoEditJava_getConstantClassCToJava(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                int                                 unknown)
-{
-    bool gotten = false;
-    int  index  = 0;
-
-    // Loop over the list with constants.
-    for (index = 0; ((!gotten) && (index < pClass->count)); index++)
-    {
-        // Check if the specified value matches the c value of the constant.
-        if (value == pClass->pConstants[index].c)
-        {
-            // Set the value to the java value.
-            value = pClass->pConstants[index].java;
-
-            // Set the gotten flag.
-            gotten = true;
-        }
-    }
-
-    // If the constant was not found, look for the specified unknown.
-    if (!gotten)
-    {
-        // Loop over the list with constants.
-        for (index = 0; ((!gotten) && (index < pClass->count)); index++)
-        {
-            // Check if the specified value matches the java value of the constant.
-            if (unknown == pClass->pConstants[index].c)
-            {
-                // Set the value to the c value.
-                value = pClass->pConstants[index].java;
-
-                // Set the gotten flag.
-                gotten = true;
-            }
-        }
-    }
-
-    // Return the translated value.
-    return(value);
-}
-
-void
-videoEditJava_initFieldClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_FieldsClass*                  pClass)
-{
-    bool   gotten = true;
-    jclass clazz  = NULL;
-    int    index  = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_initFieldClass(%s)", pClass->pName);
-
-        // Only initialize the class once.
-        if (!pClass->initialized)
-        {
-            // Look up the class.
-            videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
-            // Loop over the fields.
-            for (index = 0; index < pClass->count; index++)
-            {
-                // Look up the field id.
-                videoEditJava_getFieldId(
-                        pResult,
-                        pEnv,
-                        clazz,
-                        pClass->pFields[index].pName,
-                        pClass->pFields[index].pType,
-                        &pClass->pFields[index].fieldId);
-            }
-
-            // Check if all fields could be located.
-            if (*pResult)
-            {
-                // Set the initialized flag.
-                pClass->initialized = true;
-            }
-        }
-    }
-}
-
-void
-videoEditJava_fieldClassClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_FieldsClass*            pClass,
-                jclass*                             pClazz)
-{
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the class is initialized.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
-                "field class not initialized");
-
-        // Get the class.
-        videoEditJava_getClass(pResult, pEnv, pClass->pName, pClazz);
-    }
-}
-
-void
-videoEditJava_fieldClassFieldIds(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_FieldsClass*            pClass,
-                int                                 count,
-                VideoEditJava_FieldIds*                     pIds)
-{
-    int index = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the class is initialized.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
-                "field class not initialized");
-
-        // Check if the number of fields matches.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,
-                (pClass->count != count),
-                "field class type mismatch");
-
-        // Check if the class and object are valid.
-        if (*pResult)
-        {
-            // Loop over the class fields.
-            for (index = 0; index < count; index++)
-            {
-                // Copy the field ids.
-                pIds->fieldIds[index] = pClass->pFields[index].fieldId;
-            }
-        }
-    }
-}
-
-void
-videoEditJava_initMethodClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_MethodsClass*                 pClass)
-{
-    bool   gotten = true;
-    jclass clazz  = NULL;
-    int    index  = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Log the function call.
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_JAVA",
-                "videoEditJava_initMethodClass(%s)", pClass->pName);
-
-        // Only initialize the class once.
-        if (!pClass->initialized)
-        {
-            // Look up the class.
-            videoEditJava_getClass(pResult, pEnv, pClass->pName, &clazz);
-
-            // Loop over the methods.
-            for (index = 0; index < pClass->count; index++)
-            {
-                // Look up the method id.
-                videoEditJava_getMethodId(
-                        pResult,
-                        pEnv,
-                        clazz,
-                        pClass->pMethods[index].pName,
-                        pClass->pMethods[index].pType,
-                        &pClass->pMethods[index].methodId);
-            }
-
-            // Check if all methods could be located.
-            if (*pResult)
-            {
-                // Set the initialized flag.
-                pClass->initialized = true;
-            }
-        }
-    }
-}
-
-void
-videoEditJava_methodClassMethodIds(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_MethodsClass*   pClass,
-                int                                 count,
-                VideoEditJava_MethodIds*            pIds)
-{
-    int index = 0;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Check if the class is initialized.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv, (!pClass->initialized),
-                    "method class not initialized");
-
-        // Check if the number of methods matches.
-        videoEditJava_checkAndThrowIllegalArgumentException(pResult, pEnv,\
-                    (pClass->count != count),
-                    "method class type mismatch");
-
-        // Check if the class and object are valid.
-        if (*pResult)
-        {
-            // Loop over the class methods.
-            for (index = 0; index < count; index++)
-            {
-                // Copy the method ids.
-                pIds->methodIds[index] = pClass->pMethods[index].methodId;
-            }
-        }
-    }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorJava.h b/media/jni/mediaeditor/VideoEditorJava.h
deleted file mode 100644
index 0a2db08..0000000
--- a/media/jni/mediaeditor/VideoEditorJava.h
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDiTOR_JAVA_H
-#define VIDEO_EDiTOR_JAVA_H
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-/**
- ************************************************************************
- * @file        VideoEditorJava.h
- * @brief       Interface for JNI methods that have specific access to
- *              class, objects and method Ids defined in Java layer
- ************************************************************************
-*/
-
-extern "C" {
-#include <M4OSA_Types.h>
-#include <M4OSA_Error.h>
-}
-
-#define VIDEOEDIT_JAVA_CONSTANT_INIT(m_name, m_c)                           \
-            { m_name,                                                       \
-              0,                                                            \
-              m_c,                                                          \
-              #m_c }
-
-#define VIDEOEDIT_JAVA_DEFINE_CONSTANTS(m_class)                            \
-static                                                                      \
-VideoEditJava_Constant g##m_class##Constants [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_CONSTANT_CLASS(                               \
-                m_class,                                                    \
-                m_name,                                                     \
-                m_unknownName,                                              \
-                m_unknownString)                                            \
-                                                                            \
-static VideoEditJava_ConstantsClass g##m_class##ConstantsClass =            \
-{       m_name,                                                             \
-        &g##m_class##Constants[0],                                          \
-        (sizeof(g##m_class##Constants) / sizeof(VideoEditJava_Constant)),   \
-        false                                                               \
-};                                                                          \
-                                                                            \
-                                                                            \
-void videoEditJava_init##m_class##Constants(                                \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv)                   \
-{                                                                           \
-    videoEditJava_initConstantClass(                                        \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##ConstantsClass);                               \
-}                                                                           \
-                                                                            \
-const char* videoEditJava_get##m_class##Name(                               \
-                int                                 value)                  \
-{                                                                           \
-    return(videoEditJava_getConstantClassName(                              \
-                &g##m_class##ConstantsClass,                                \
-                value,                                                      \
-                m_unknownName));                                            \
-}                                                                           \
-                                                                            \
-const char* videoEditJava_get##m_class##String(                             \
-                int                                 value)                  \
-{                                                                           \
-    return(videoEditJava_getConstantClassString(                            \
-                &g##m_class##ConstantsClass,                                \
-                value,                                                      \
-                m_unknownString));                                          \
-}                                                                           \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##JavaToC(                                        \
-                bool*                               pResult,                \
-                int                                 value)                  \
-{                                                                           \
-    return(videoEditJava_getConstantClassJavaToC(                           \
-                pResult,                                                    \
-                &g##m_class##ConstantsClass,                                \
-                value));                                                    \
-}                                                                           \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##JavaToC(                                        \
-                bool*                               pResult,                \
-                int                                 value,                  \
-                int                                 unknown)                \
-{                                                                           \
-    return(videoEditJava_getConstantClassJavaToC(                           \
-                pResult,                                                    \
-                &g##m_class##ConstantsClass,                                \
-                value,                                                      \
-                unknown));                                                  \
-}                                                                           \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##CToJava(                                        \
-                        int                                 value)          \
-{                                                                           \
-    return(videoEditJava_getConstantClassCToJava(                           \
-                &g##m_class##ConstantsClass,                                \
-                value));                                                    \
-}                                                                           \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##CToJava(                                        \
-                int                                 value,                  \
-                int                                 unknown)                \
-{                                                                           \
-    return(videoEditJava_getConstantClassCToJava(                           \
-                &g##m_class##ConstantsClass,                                \
-                value,                                                      \
-                unknown));                                                  \
-}
-
-
-#define VIDEOEDIT_JAVA_DECLARE_CONSTANT_CLASS(m_class)                       \
-void                                                                        \
-videoEditJava_init##m_class##Constants(                                     \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv);                  \
-                                                                            \
-const char*                                                                 \
-videoEditJava_get##m_class##Name(                                           \
-                int                                 value);                 \
-                                                                            \
-const char*                                                                 \
-videoEditJava_get##m_class##String(                                         \
-                int                                 value);                 \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##JavaToC(                                        \
-                bool*                               pResult,                \
-                int                                 value,                  \
-                int                                 unknown);               \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##JavaToC(                                        \
-                bool*                               pResult,                \
-                int                                 value);                 \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##CToJava(                                        \
-                int                                 value);                 \
-                                                                            \
-int                                                                         \
-videoEditJava_get##m_class##CToJava(                                        \
-                int                                 value,                  \
-                int                                 unknown);
-
-#define VIDEOEDIT_JAVA_FIELD_INIT(m_name, m_type)                           \
-    { m_name,                                                               \
-      m_type,                                                               \
-      NULL }
-
-#define VIDEOEDIT_JAVA_DEFINE_FIELDS(m_class)                               \
-static                                                                      \
-VideoEditJava_Field g##m_class##Fields [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_FIELD_CLASS(m_class, m_name)                  \
-static VideoEditJava_FieldsClass g##m_class##FieldsClass =                  \
-    { m_name,                                                               \
-      &g##m_class##Fields[0],                                               \
-      (sizeof(g##m_class##Fields) / sizeof(VideoEditJava_Field)),           \
-      false };                                                              \
-                                                                            \
-void                                                                        \
-videoEditJava_init##m_class##Fields(                                        \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv)                   \
-{                                                                           \
-    videoEditJava_initFieldClass(                                           \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##FieldsClass);                                  \
-}                                                                           \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##Class(                                          \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                jclass*                             pClazz)                 \
-{                                                                           \
-    videoEditJava_fieldClassClass(                                          \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##FieldsClass,                                   \
-                pClazz);                                                    \
-}                                                                           \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##FieldIds(                                       \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                VideoEditJava_##m_class##FieldIds*          pIds)           \
-{                                                                           \
-    videoEditJava_fieldClassFieldIds(                                       \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##FieldsClass,                                   \
-                (sizeof(VideoEditJava_##m_class##FieldIds) /                \
-                 sizeof(jfieldID)),                                         \
-                (VideoEditJava_FieldIds*)pIds);                             \
-}
-
-#define VIDEOEDIT_JAVA_DECLARE_FIELD_CLASS(m_class)                         \
-void                                                                        \
-videoEditJava_init##m_class##Fields(                                        \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv);                  \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##Class(                                          \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                jclass*                             pClazz);                \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##FieldIds(                                       \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                VideoEditJava_##m_class##FieldIds*          pIds);
-
-
-#define VIDEOEDIT_JAVA_METHOD_INIT(m_name, m_type)                          \
-    { m_name,                                                               \
-      m_type,                                                               \
-      NULL }
-
-#define VIDEOEDIT_JAVA_DEFINE_METHODS(m_class)                              \
-static                                                                      \
-VideoEditJava_Method g##m_class##Methods [] =
-
-#define VIDEOEDIT_JAVA_DEFINE_METHOD_CLASS(m_class, m_name)                 \
-static VideoEditJava_MethodsClass g##m_class##MethodsClass =                \
-    { m_name,                                                               \
-      &g##m_class##Methods[0],                                              \
-      (sizeof(g##m_class##Methods) / sizeof(VideoEditJava_Method)),         \
-      false };                                                              \
-                                                                            \
-void                                                                        \
-videoEditJava_init##m_class##Methods(                                       \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv)                   \
-{                                                                           \
-    videoEditJava_initMethodClass(                                          \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##MethodsClass);                                 \
-}                                                                           \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##MethodIds(                                      \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                VideoEditJava_##m_class##MethodIds*         pIds)           \
-{                                                                           \
-    videoEditJava_methodClassMethodIds(                                     \
-                pResult,                                                    \
-                pEnv,                                                       \
-                &g##m_class##MethodsClass,                                  \
-                (sizeof(VideoEditJava_##m_class##MethodIds) /               \
-                 sizeof(jmethodID)),                                        \
-                (VideoEditJava_MethodIds*)pIds);                            \
-}
-
-#define VIDEOEDIT_JAVA_DECLARE_METHOD_CLASS(m_class)                        \
-void                                                                        \
-videoEditJava_init##m_class##Methods(                                       \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv);                  \
-                                                                            \
-void                                                                        \
-videoEditJava_get##m_class##MethodIds(                                      \
-                bool*                               pResult,                \
-                JNIEnv*                             pEnv,                   \
-                VideoEditJava_##m_class##MethodIds*         pIds);
-
-
-typedef struct
-{
-    const char*     pName;
-    int             java;
-    int             c;
-    const char*     pDescription;
-} VideoEditJava_Constant;
-
-typedef struct
-{
-    const char*             pName;
-    VideoEditJava_Constant* pConstants;
-    int                     count;
-    bool                    initialized;
-} VideoEditJava_ConstantsClass;
-
-typedef const char* (*VideoEditJava_UnknownConstant)(int constant);
-
-typedef struct
-{
-    const char*             pName;
-    const char*             pType;
-    jfieldID                fieldId;
-} VideoEditJava_Field;
-
-typedef struct
-{
-    const char*             pName;
-    VideoEditJava_Field*    pFields;
-    int                     count;
-    bool                    initialized;
-} VideoEditJava_FieldsClass;
-
-typedef struct
-{
-    jfieldID fieldIds[];
-} VideoEditJava_FieldIds;
-
-typedef struct
-{
-    const char*             pName;
-    const char*             pType;
-    jmethodID               methodId;
-} VideoEditJava_Method;
-
-typedef struct
-{
-    const char*             pName;
-    VideoEditJava_Method*   pMethods;
-    int                     count;
-    bool                    initialized;
-} VideoEditJava_MethodsClass;
-
-typedef struct
-{
-    jmethodID methodIds[];
-} VideoEditJava_MethodIds;
-
-#define videoEditJava_checkAndThrowIllegalArgumentException(\
-    a, b, c, d) videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(\
-    a, b, c, d, __FILE__, __LINE__)
-
-#define videoEditJava_checkAndThrowRuntimeException(\
-    a, b, c, d) videoEditJava_checkAndThrowRuntimeExceptionFunc(\
-    a, b, c, d, __FILE__, __LINE__)
-
-#define videoEditJava_checkAndThrowIllegalStateException(\
-    a, b, c, d) videoEditJava_checkAndThrowIllegalStateExceptionFunc(\
-    a, b, c, d, __FILE__, __LINE__)
-
-void
-videoEditJava_checkAndThrowIllegalArgumentExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                const char*                         pMessage,
-                const char*                         pFile,
-                int                                 lineNo
-                );
-
-void
-videoEditJava_checkAndThrowRuntimeExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                M4OSA_ERR                           result,
-                const char*                         pFile,
-                int                                 lineNo
-                );
-
-void
-videoEditJava_checkAndThrowIllegalStateExceptionFunc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                bool                                condition,
-                const char*                         pMessage,
-                const char*                         pFile,
-                int                                 lineNo
-                );
-
-void
-videoEditJava_getClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const char*                         pName,
-                jclass*                             pClazz);
-
-void
-videoEditJava_getMethodId(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jclass                              clazz,
-                const char*                         pName,
-                const char*                         pType,
-                jmethodID*                          pMethodId);
-
-void videoEditJava_getFieldId(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jclass                              clazz,
-                const char*                         pName,
-                const char*                         pType,
-                jfieldID*                           pFieldId);
-
-void videoEditJava_getObject(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            objectFieldId,
-                jobject*                            pObject);
-
-void videoEditJava_getArray(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            arrayFieldId,
-                jobjectArray*                       pArray,
-                jsize*                              pArraySize);
-
-void* videoEditJava_getString(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                jobject                             object,
-                jfieldID                            stringFieldId,
-                M4OSA_UInt32*                       pLength);
-
-void videoEditJava_getStaticIntField(
-                bool*                               pResult,
-                JNIEnv*                             env,
-                jclass                              clazz,
-                const char*                         pName,
-                int*                                pValue);
-
-void
-videoEditJava_initConstantClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_ConstantsClass*               pClass);
-
-const char*
-videoEditJava_getConstantClassName(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                VideoEditJava_UnknownConstant               unknown);
-
-const char*
-videoEditJava_getConstantClassString(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                VideoEditJava_UnknownConstant               unknown);
-
-int
-videoEditJava_getConstantClassJavaToC(
-                bool*                               pResult,
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value);
-
-int
-videoEditJava_getConstantClassJavaToC(
-                bool*                               pResult,
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                int                                 unknown);
-
-int
-videoEditJava_getConstantClassCToJava(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value);
-
-int
-videoEditJava_getConstantClassCToJava(
-                const VideoEditJava_ConstantsClass*         pClass,
-                int                                 value,
-                int                                 unknown);
-
-void
-videoEditJava_initFieldClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_FieldsClass*                  pClass);
-
-void
-videoEditJava_fieldClassClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_FieldsClass*            pClass,
-                jclass*                             pClazz);
-
-void
-videoEditJava_fieldClassFieldIds(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_FieldsClass*            pClass,
-                int                                 count,
-                VideoEditJava_FieldIds*                     pIds);
-
-void
-videoEditJava_initMethodClass(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                VideoEditJava_MethodsClass*                 pClass);
-
-void
-videoEditJava_methodClassMethodIds(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                const VideoEditJava_MethodsClass*           pClass,
-                int                                 count,
-                VideoEditJava_MethodIds*                    pIds);
-
-#endif // VIDEO_EDiTOR_JAVA_H
-
diff --git a/media/jni/mediaeditor/VideoEditorLogging.h b/media/jni/mediaeditor/VideoEditorLogging.h
deleted file mode 100644
index 1f1228a..0000000
--- a/media/jni/mediaeditor/VideoEditorLogging.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_LOGGING_H
-#define VIDEO_EDITOR_LOGGING_H
-
-#ifndef LOG_TAG
-#error "No LOG_TAG defined!"
-#endif
-
-/*
- * This file is used as a proxy for cutils/log.h.  Include cutils/log.h here to
- * avoid relying on import ordering.
- */
-#include <cutils/log.h>
-
-//#define VIDEOEDIT_LOGGING_ENABLED
-
-#define VIDEOEDIT_LOG_INDENTATION                       (3)
-
-#define VIDEOEDIT_LOG_ERROR                             __android_log_print
-#define VIDEOEDIT_LOG_EXCEPTION                         __android_log_print
-
-#ifdef VIDEOEDIT_LOGGING_ENABLED
-
-#define VIDEOEDIT_LOG_ALLOCATION                        __android_log_print
-#define VIDEOEDIT_LOG_API                               __android_log_print
-#define VIDEOEDIT_LOG_FUNCTION                          __android_log_print
-#define VIDEOEDIT_LOG_RESULT(x,y, ...)                     ALOGI(y, __VA_ARGS__ )
-#define VIDEOEDIT_LOG_SETTING                           __android_log_print
-#define VIDEOEDIT_LOG_EDIT_SETTINGS(m_settings)         videoEditClasses_logEditSettings\
-                                               (m_settings, VIDEOEDIT_LOG_INDENTATION)
-#define VIDEOEDIT_PROP_LOG_PROPERTIES(m_properties)          videoEditPropClass_logProperties\
-                                                  (m_properties, VIDEOEDIT_LOG_INDENTATION)
-#define VIDEOEDIT_PROP_LOG_RESULT                            __android_log_print
-
-#else
-
-#define VIDEOEDIT_LOG_ALLOCATION                        (void)
-#define VIDEOEDIT_LOG_API                               (void)
-#define VIDEOEDIT_LOG_FUNCTION                          (void)
-#define VIDEOEDIT_LOG_RESULT                            (void)
-#define VIDEOEDIT_LOG_SETTING                           (void)
-#define VIDEOEDIT_LOG_EDIT_SETTINGS(m_settings)         (void)m_settings
-#define VIDEOEDIT_PROP_LOG_PROPERTIES(m_properties)          (void)m_properties
-#define VIDEOEDIT_PROP_LOG_RESULT                            (void)
-
-#endif
-
-#endif // VIDEO_EDITOR_LOGGING_H
-
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
deleted file mode 100644
index 058012b..0000000
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ /dev/null
@@ -1,3661 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-#define LOG_NDEBUG 1
-#define LOG_TAG "VideoEditorMain"
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorOsal.h>
-#include <VideoEditorLogging.h>
-#include <marker.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorThumbnailMain.h>
-#include <M4OSA_Debug.h>
-#include <M4xVSS_Internal.h>
-#include <gui/Surface.h>
-#include "VideoEditorPreviewController.h"
-
-#include "VideoEditorMain.h"
-
-#include <android_runtime/android_view_Surface.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_Error.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_API.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-};
-
-
-using namespace android;
-
-#define THREAD_STACK_SIZE       (65536)
-
-#define VIDEOEDITOR_VERSION_MAJOR     0
-#define VIDEOEDITOR_VERSION_MINOR     0
-#define VIDEOEDITOR_VERSION_REVISION  1
-
-
-typedef enum
-{
-    ManualEditState_NOT_INITIALIZED,
-    ManualEditState_INITIALIZED,
-    ManualEditState_ANALYZING,
-    ManualEditState_ANALYZING_ERROR,
-    ManualEditState_OPENED,
-    ManualEditState_SAVING,
-    ManualEditState_SAVING_ERROR,
-    ManualEditState_SAVED,
-    ManualEditState_STOPPING
-} ManualEditState;
-
-typedef struct
-{
-    JavaVM*                        pVM;
-    jobject                        engine;
-    jmethodID                      onCompletionMethodId;
-    jmethodID                      onErrorMethodId;
-    jmethodID                      onWarningMethodId;
-    jmethodID                      onProgressUpdateMethodId;
-    jmethodID                      onPreviewProgressUpdateMethodId;
-    jmethodID                      previewFrameEditInfoId;
-    M4xVSS_InitParams              initParams;
-    void*                          pTextRendererHandle;
-    M4xVSS_getTextRgbBufferFct     pTextRendererFunction;
-    M4OSA_Context                  engineContext;
-    ManualEditState                state;
-    M4VSS3GPP_EditSettings*        pEditSettings;
-    M4OSA_Context                  threadContext;
-    M4OSA_ERR                      threadResult;
-    M4OSA_UInt8                    threadProgress;
-    VideoEditorPreviewController   *mPreviewController;
-    M4xVSS_AudioMixingSettings     *mAudioSettings;
-    /* Audio Graph changes */
-    M4OSA_Context                   pAudioGraphMCSCtx;
-    M4OSA_Bool                      bSkipState;
-    jmethodID                       onAudioGraphProgressUpdateMethodId;
-    Mutex                           mLock;
-    bool                            mIsUpdateOverlay;
-    char                            *mOverlayFileName;
-    int                             mOverlayRenderingMode;
-    M4DECODER_VideoDecoders* decoders;
-} ManualEditContext;
-
-extern "C" M4OSA_ERR M4MCS_open_normalMode(
-                M4MCS_Context                       pContext,
-                M4OSA_Void*                         pFileIn,
-                M4VIDEOEDITING_FileType             InputFileType,
-                M4OSA_Void*                         pFileOut,
-                M4OSA_Void*                         pTempFile);
-
-static M4OSA_ERR videoEditor_toUTF8Fct(
-                M4OSA_Void*                         pBufferIn,
-                M4OSA_UInt8*                        pBufferOut,
-                M4OSA_UInt32*                       bufferOutSize);
-
-static M4OSA_ERR videoEditor_fromUTF8Fct(
-                M4OSA_UInt8*                        pBufferIn,
-                M4OSA_Void*                         pBufferOut,
-                M4OSA_UInt32*                       bufferOutSize);
-
-static M4OSA_ERR videoEditor_getTextRgbBufferFct(
-                M4OSA_Void*                         pRenderingData,
-                M4OSA_Void*                         pTextBuffer,
-                M4OSA_UInt32                        textBufferSize,
-                M4VIFI_ImagePlane**                 pOutputPlane);
-
-static void videoEditor_callOnProgressUpdate(
-                ManualEditContext*                  pContext,
-                int                                 task,
-                int                                 progress);
-
-static void videoEditor_freeContext(
-                JNIEnv*                             pEnv,
-                ManualEditContext**                 ppContext);
-
-static M4OSA_ERR videoEditor_threadProc(
-                M4OSA_Void*                         param);
-
-static jobject videoEditor_getVersion(
-                JNIEnv*                             pEnv,
-                jobject                             thiz);
-
-static void videoEditor_init(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             tempPath,
-                jstring                             textRendererPath);
-
-static void videoEditor_loadSettings(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jobject                             settings);
-
-static void videoEditor_unloadSettings(
-                JNIEnv*                             pEnv,
-                jobject                             thiz);
-
-
-static void videoEditor_stopEncoding(
-                JNIEnv*                             pEnv,
-                jobject                             thiz);
-
-static void videoEditor_release(
-                JNIEnv*                             pEnv,
-                jobject                             thiz);
-static jint videoEditor_getPixels(
-                                 JNIEnv*                  env,
-                                 jobject                  thiz,
-                                 jstring                  path,
-                                 jintArray                pixelArray,
-                                 M4OSA_UInt32             width,
-                                 M4OSA_UInt32             height,
-                                 M4OSA_UInt32             timeMS);
-static jint videoEditor_getPixelsList(
-                                     JNIEnv*                  env,
-                                     jobject                  thiz,
-                                     jstring                  path,
-                                     jintArray                pixelArray,
-                                     M4OSA_UInt32             width,
-                                     M4OSA_UInt32             height,
-                                     M4OSA_UInt32             noOfThumbnails,
-                                     jlong                    startTime,
-                                     jlong                    endTime,
-                                     jintArray                indexArray,
-                                     jobject                  callback);
-
-static void
-videoEditor_startPreview(
-                JNIEnv*                 pEnv,
-                jobject                 thiz,
-                jobject                 mSurface,
-                jlong                   fromMs,
-                jlong                   toMs,
-                jint                    callbackInterval,
-                jboolean                loop);
-
-static void
-videoEditor_populateSettings(
-                JNIEnv*                 pEnv,
-                jobject                 thiz,
-                jobject                 settings,
-                jobject                 object,
-                jobject                 audioSettingObject);
-
-static jint videoEditor_stopPreview(JNIEnv*  pEnv,
-                              jobject  thiz);
-
-static jobject
-videoEditor_getProperties(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             file);
-
-static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
-                                    jobject thiz,
-                                    jobject    mSurface,
-                                    jlong fromMs,
-                                    jint  surfaceWidth,
-                                    jint  surfaceHeight);
-
-static int videoEditor_registerManualEditMethods(
-                JNIEnv*                             pEnv);
-
-static void jniPreviewProgressCallback(void* cookie, M4OSA_UInt32 msgType,
-                                        void *argc);
-
-static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
-                                                    jobject thiz,
-                                                    jobject mSurface,
-                                                    jstring filePath,
-                                                    jint frameWidth,
-                                                    jint frameHeight,
-                                                    jint surfaceWidth,
-                                                    jint surfaceHeight,
-                                                    jlong fromMs);
-
-static jint videoEditor_generateAudioWaveFormSync ( JNIEnv*     pEnv,
-                                                  jobject     thiz,
-                                                  jstring     pcmfilePath,
-                                                  jstring     outGraphfilePath,
-                                                  jint        frameDuration,
-                                                  jint        channels,
-                                                  jint        samplesCount);
-
-static int videoEditor_generateAudioRawFile(JNIEnv* pEnv,
-                                    jobject thiz,
-                                    jstring infilePath,
-                                    jstring pcmfilePath );
-
-M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext,
-                                    M4OSA_Char* infilePath,
-                                    M4OSA_Char* pcmfilePath );
-
-static jint
-videoEditor_generateClip(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jobject                             settings);
-
-static void videoEditor_clearSurface(JNIEnv* pEnv,
-                                    jobject thiz,
-                                    jobject surface);
-
-static JNINativeMethod gManualEditMethods[] = {
-    {"getVersion",               "()L"VERSION_CLASS_NAME";",
-                                (void *)videoEditor_getVersion      },
-    {"_init",                    "(Ljava/lang/String;Ljava/lang/String;)V",
-                                (void *)videoEditor_init    },
-    {"nativeStartPreview",       "(Landroid/view/Surface;JJIZ)V",
-                                (void *)videoEditor_startPreview    },
-    {"nativePopulateSettings",
-            "(L"EDIT_SETTINGS_CLASS_NAME";L"PREVIEW_PROPERTIES_CLASS_NAME";L"
-            AUDIO_SETTINGS_CLASS_NAME";)V",
-                                (void *)videoEditor_populateSettings    },
-    {"nativeRenderPreviewFrame", "(Landroid/view/Surface;JII)I",
-                                (int *)videoEditor_renderPreviewFrame     },
-    {"nativeRenderMediaItemPreviewFrame",
-    "(Landroid/view/Surface;Ljava/lang/String;IIIIJ)I",
-                        (int *)videoEditor_renderMediaItemPreviewFrame     },
-    {"nativeStopPreview",       "()I",
-                                (int *)videoEditor_stopPreview    },
-    {"stopEncoding",            "()V",
-                                (void *)videoEditor_stopEncoding         },
-    {"release",                 "()V",
-                                (void *)videoEditor_release            },
-    {"nativeGetPixels",         "(Ljava/lang/String;[IIIJ)I",
-                                (void*)videoEditor_getPixels               },
-    {"nativeGetPixelsList",     "(Ljava/lang/String;[IIIIJJ[ILandroid/media/videoeditor/MediaArtistNativeHelper$NativeGetPixelsListCallback;)I",
-                                (void*)videoEditor_getPixelsList           },
-    {"getMediaProperties",
-    "(Ljava/lang/String;)Landroid/media/videoeditor/MediaArtistNativeHelper$Properties;",
-                                (void *)videoEditor_getProperties          },
-    {"nativeGenerateAudioGraph","(Ljava/lang/String;Ljava/lang/String;III)I",
-                                (int *)videoEditor_generateAudioWaveFormSync },
-    {"nativeGenerateRawAudio",  "(Ljava/lang/String;Ljava/lang/String;)I",
-                                (int *)videoEditor_generateAudioRawFile      },
-    {"nativeGenerateClip",      "(L"EDIT_SETTINGS_CLASS_NAME";)I",
-                                (void *)videoEditor_generateClip  },
-    {"nativeClearSurface",       "(Landroid/view/Surface;)V",
-                                (void *)videoEditor_clearSurface  },
-};
-
-// temp file name of VSS out file
-#define TEMP_MCS_OUT_FILE_PATH "tmpOut.3gp"
-
-void
-getClipSetting(
-                JNIEnv*                                       pEnv,
-                jobject                                       object,
-                M4VSS3GPP_ClipSettings*                       pSettings)
-{
-
-    jfieldID fid;
-    int field = 0;
-    bool needToBeLoaded = true;
-    jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME);
-
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == clazz),
-                                             "not initialized");
-
-    fid = pEnv->GetFieldID(clazz,"duration","I");
-    pSettings->ClipProperties.uiClipDuration = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("duration = %d",pSettings->ClipProperties.uiClipDuration);
-
-    fid = pEnv->GetFieldID(clazz,"videoFormat","I");
-    pSettings->ClipProperties.VideoStreamType =
-        (M4VIDEOEDITING_VideoFormat)pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("videoFormat = %d",pSettings->ClipProperties.VideoStreamType);
-
-    fid = pEnv->GetFieldID(clazz,"videoDuration","I");
-    pSettings->ClipProperties.uiClipVideoDuration = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("videoDuration = %d",
-                    pSettings->ClipProperties.uiClipVideoDuration);
-
-    fid = pEnv->GetFieldID(clazz,"width","I");
-    pSettings->ClipProperties.uiVideoWidth = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("width = %d",pSettings->ClipProperties.uiVideoWidth);
-
-    fid = pEnv->GetFieldID(clazz,"height","I");
-    pSettings->ClipProperties.uiVideoHeight = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("height = %d",pSettings->ClipProperties.uiVideoHeight);
-
-    fid = pEnv->GetFieldID(clazz,"audioFormat","I");
-    pSettings->ClipProperties.AudioStreamType =
-        (M4VIDEOEDITING_AudioFormat)pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("audioFormat = %d",pSettings->ClipProperties.AudioStreamType);
-
-    fid = pEnv->GetFieldID(clazz,"audioDuration","I");
-    pSettings->ClipProperties.uiClipAudioDuration = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("audioDuration = %d",
-                    pSettings->ClipProperties.uiClipAudioDuration);
-
-    fid = pEnv->GetFieldID(clazz,"audioBitrate","I");
-    pSettings->ClipProperties.uiAudioBitrate = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("audioBitrate = %d",pSettings->ClipProperties.uiAudioBitrate);
-
-    fid = pEnv->GetFieldID(clazz,"audioChannels","I");
-    pSettings->ClipProperties.uiNbChannels = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("audioChannels = %d",pSettings->ClipProperties.uiNbChannels);
-
-    fid = pEnv->GetFieldID(clazz,"audioSamplingFrequency","I");
-    pSettings->ClipProperties.uiSamplingFrequency = pEnv->GetIntField(object,fid);
-    M4OSA_TRACE1_1("audioSamplingFrequency = %d",
-                    pSettings->ClipProperties.uiSamplingFrequency);
-
-   fid = pEnv->GetFieldID(clazz,"audioVolumeValue","I");
-   pSettings->ClipProperties.uiClipAudioVolumePercentage =
-                    pEnv->GetIntField(object,fid);
-   M4OSA_TRACE1_1("audioVolumeValue = %d",
-                    pSettings->ClipProperties.uiClipAudioVolumePercentage);
-
-   fid = pEnv->GetFieldID(clazz,"videoRotation","I");
-   pSettings->ClipProperties.videoRotationDegrees =
-                    pEnv->GetIntField(object,fid);
-   M4OSA_TRACE1_1("videoRotation = %d",
-                    pSettings->ClipProperties.videoRotationDegrees);
-
-   // Free the local references to avoid memory leaks
-   pEnv->DeleteLocalRef(clazz);
-}
-
-static void jniPreviewProgressCallback (void* cookie, M4OSA_UInt32 msgType,
-                                        void *argc)
-{
-    ManualEditContext *pContext = (ManualEditContext *)cookie;
-    JNIEnv*     pEnv = NULL;
-    bool        isFinished = false;
-    int         currentMs = 0;
-    int         error = M4NO_ERROR;
-    bool        isUpdateOverlay = false;
-    int         overlayEffectIndex;
-    char        *extPos;
-    bool        isSendProgress = true;
-    jstring     tmpFileName;
-    VideoEditorCurretEditInfo *pCurrEditInfo;
-
-    // Attach the current thread.
-    pContext->pVM->AttachCurrentThread(&pEnv, NULL);
-    switch(msgType)
-    {
-        case MSG_TYPE_PROGRESS_INDICATION:
-            currentMs = *(int*)argc;
-            break;
-        case MSG_TYPE_PLAYER_ERROR:
-            currentMs = -1;
-            error = *(int*)argc;
-            break;
-        case MSG_TYPE_PREVIEW_END:
-            isFinished = true;
-            break;
-        case MSG_TYPE_OVERLAY_UPDATE:
-        {
-            int overlayFileNameLen = 0;
-            isSendProgress = false;
-            pContext->mIsUpdateOverlay = true;
-            pCurrEditInfo = (VideoEditorCurretEditInfo*)argc;
-            overlayEffectIndex = pCurrEditInfo->overlaySettingsIndex;
-            ALOGV("MSG_TYPE_OVERLAY_UPDATE");
-
-            if (pContext->mOverlayFileName != NULL) {
-                free(pContext->mOverlayFileName);
-                pContext->mOverlayFileName = NULL;
-            }
-
-            overlayFileNameLen =
-                strlen((const char*)pContext->pEditSettings->Effects[overlayEffectIndex].xVSS.pFramingFilePath);
-
-            pContext->mOverlayFileName =
-                (char*)M4OSA_32bitAlignedMalloc(overlayFileNameLen+1,
-                                    M4VS, (M4OSA_Char*)"videoEdito JNI overlayFile");
-            if (pContext->mOverlayFileName != NULL) {
-                strncpy (pContext->mOverlayFileName,
-                    (const char*)pContext->pEditSettings->\
-                    Effects[overlayEffectIndex].xVSS.pFramingFilePath, overlayFileNameLen);
-                //Change the name to png file
-                extPos = strstr(pContext->mOverlayFileName, ".rgb");
-                if (extPos != NULL) {
-                    *extPos = '\0';
-                } else {
-                    ALOGE("ERROR the overlay file is incorrect");
-                }
-
-                strcat(pContext->mOverlayFileName, ".png");
-                ALOGV("Conv string is %s", pContext->mOverlayFileName);
-                ALOGV("Current Clip index = %d", pCurrEditInfo->clipIndex);
-
-                pContext->mOverlayRenderingMode = pContext->pEditSettings->\
-                         pClipList[pCurrEditInfo->clipIndex]->xVSS.MediaRendering;
-                ALOGV("rendering mode %d ", pContext->mOverlayRenderingMode);
-
-            }
-
-            break;
-        }
-
-        case MSG_TYPE_OVERLAY_CLEAR:
-            isSendProgress = false;
-            if (pContext->mOverlayFileName != NULL) {
-                free(pContext->mOverlayFileName);
-                pContext->mOverlayFileName = NULL;
-            }
-
-            ALOGV("MSG_TYPE_OVERLAY_CLEAR");
-            //argc is not used
-            pContext->mIsUpdateOverlay = true;
-            break;
-        default:
-            break;
-    }
-
-    if (isSendProgress) {
-        tmpFileName  = pEnv->NewStringUTF(pContext->mOverlayFileName);
-        pEnv->CallVoidMethod(pContext->engine,
-                pContext->onPreviewProgressUpdateMethodId,
-                currentMs,isFinished, pContext->mIsUpdateOverlay,
-                tmpFileName, pContext->mOverlayRenderingMode, error);
-
-        if (pContext->mIsUpdateOverlay) {
-            pContext->mIsUpdateOverlay = false;
-        }
-
-        if (tmpFileName) {
-            pEnv->DeleteLocalRef(tmpFileName);
-        }
-    }
-
-    // Detach the current thread.
-    pContext->pVM->DetachCurrentThread();
-
-}
-static M4OSA_ERR checkClipVideoProfileAndLevel(M4DECODER_VideoDecoders *pDecoders,
-    M4OSA_Int32 format, M4OSA_UInt32 profile, M4OSA_UInt32 level){
-
-    M4OSA_Int32 codec = 0;
-    M4OSA_Bool foundCodec = M4OSA_FALSE;
-    M4OSA_ERR  result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE;
-    M4OSA_Bool foundProfile = M4OSA_FALSE;
-    ALOGV("checkClipVideoProfileAndLevel format %d profile;%d level:0x%x",
-       format, profile, level);
-
-    switch (format) {
-        case M4VIDEOEDITING_kH263:
-            codec = M4DA_StreamTypeVideoH263;
-            break;
-        case M4VIDEOEDITING_kH264:
-             codec = M4DA_StreamTypeVideoMpeg4Avc;
-            break;
-        case M4VIDEOEDITING_kMPEG4:
-             codec = M4DA_StreamTypeVideoMpeg4;
-            break;
-        case M4VIDEOEDITING_kNoneVideo:
-        case M4VIDEOEDITING_kNullVideo:
-        case M4VIDEOEDITING_kUnsupportedVideo:
-             // For these case we do not check the profile and level
-             return M4NO_ERROR;
-        default :
-            ALOGE("checkClipVideoProfileAndLevel unsupport Video format %ld", format);
-            break;
-    }
-
-    if (pDecoders != M4OSA_NULL && pDecoders->decoderNumber > 0) {
-        VideoDecoder *pVideoDecoder = pDecoders->decoder;
-        for(size_t k =0; k < pDecoders->decoderNumber; k++) {
-            if (pVideoDecoder != M4OSA_NULL) {
-                if (pVideoDecoder->codec == codec) {
-                    foundCodec = M4OSA_TRUE;
-                    break;
-                }
-            }
-            pVideoDecoder++;
-        }
-
-        if (foundCodec) {
-            VideoComponentCapabilities* pComponent = pVideoDecoder->component;
-            for (size_t i = 0; i < pVideoDecoder->componentNumber; i++) {
-                if (pComponent != M4OSA_NULL) {
-                    VideoProfileLevel *pProfileLevel = pComponent->profileLevel;
-                    for (size_t j =0; j < pComponent->profileNumber; j++) {
-                        // Check the profile and level
-                        if (pProfileLevel != M4OSA_NULL) {
-                            if (profile == pProfileLevel->mProfile) {
-                                foundProfile = M4OSA_TRUE;
-
-                                if (level <= pProfileLevel->mLevel) {
-                                    return M4NO_ERROR;
-                                }
-                            } else {
-                                foundProfile = M4OSA_FALSE;
-                            }
-                        }
-                        pProfileLevel++;
-                    }
-                }
-                pComponent++;
-            }
-        }
-    }
-
-    if (foundProfile) {
-        result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL;
-    } else {
-        result = M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE;
-    }
-
-    return result;
-}
-static jint videoEditor_stopPreview(JNIEnv*  pEnv,
-                              jobject  thiz)
-{
-    ManualEditContext* pContext = M4OSA_NULL;
-    bool needToBeLoaded = true;
-    M4OSA_UInt32 lastProgressTimeMs = 0;
-
-    // Get the context.
-    pContext =
-            (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-    lastProgressTimeMs = pContext->mPreviewController->stopPreview();
-
-    if (pContext->mOverlayFileName != NULL) {
-        free(pContext->mOverlayFileName);
-        pContext->mOverlayFileName = NULL;
-    }
-
-    return (jint)lastProgressTimeMs;
-}
-
-static void videoEditor_clearSurface(JNIEnv* pEnv,
-                                    jobject thiz,
-                                    jobject surface)
-{
-    bool needToBeLoaded = true;
-    M4OSA_ERR result = M4NO_ERROR;
-    VideoEditor_renderPreviewFrameStr frameStr;
-    const char* pMessage = NULL;
-    // Let the size be QVGA
-    int width = 320;
-    int height = 240;
-    ManualEditContext* pContext = M4OSA_NULL;
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-                                "VIDEO_EDITOR","pContext = 0x%x",pContext);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-
-    // Validate the surface parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == surface),
-                                                "surface is null");
-
-    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, surface);
-
-    // Validate the mSurface's mNativeSurface field
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                                (NULL == previewSurface.get()),
-                                                "mNativeSurface is null");
-
-    frameStr.pBuffer = M4OSA_NULL;
-    frameStr.timeMs = 0;
-    frameStr.uiSurfaceWidth = width;
-    frameStr.uiSurfaceHeight = height;
-    frameStr.uiFrameWidth = width;
-    frameStr.uiFrameHeight = height;
-    frameStr.bApplyEffect = M4OSA_FALSE;
-    frameStr.clipBeginCutTime = 0;
-    frameStr.clipEndCutTime = 0;
-
-    result = pContext->mPreviewController->clearSurface(previewSurface,
-                                                              &frameStr);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-            (M4NO_ERROR != result), result);
-
-  }
-
-static jint videoEditor_renderPreviewFrame(JNIEnv* pEnv,
-                                    jobject thiz,
-                                    jobject    mSurface,
-                                    jlong fromMs,
-                                    jint surfaceWidth,
-                                    jint surfaceHeight )
-{
-    bool needToBeLoaded = true;
-    M4OSA_ERR result = M4NO_ERROR;
-    M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs;
-    M4OSA_UInt32 i=0,tnTimeMs = 0, framesizeYuv =0;
-    M4VIFI_UInt8 *pixelArray = M4OSA_NULL;
-    M4OSA_UInt32    iCurrentClipIndex = 0, uiNumberOfClipsInStoryBoard =0,
-                    uiClipDuration = 0, uiTotalClipDuration = 0,
-                    iIncrementedDuration = 0;
-    VideoEditor_renderPreviewFrameStr frameStr;
-    M4OSA_Context tnContext = M4OSA_NULL;
-    const char* pMessage = NULL;
-    M4VIFI_ImagePlane *yuvPlane = NULL;
-    VideoEditorCurretEditInfo  currEditInfo;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-        "VIDEO_EDITOR", "surfaceWidth = %d",surfaceWidth);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-        "VIDEO_EDITOR", "surfaceHeight = %d",surfaceHeight);
-    ManualEditContext* pContext = M4OSA_NULL;
-    // Get the context.
-    pContext =
-            (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-                                "VIDEO_EDITOR","pContext = 0x%x",pContext);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-
-    // Validate the mSurface parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == mSurface),
-                                                "mSurface is null");
-
-    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
-    // Validate the mSurface's mNativeSurface field
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                                (NULL == previewSurface.get()),
-                                                "mNativeSurface is null");
-
-    /* Determine the total number of clips, total duration*/
-    uiNumberOfClipsInStoryBoard = pContext->pEditSettings->uiClipNumber;
-
-    for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) {
-        uiClipDuration = pContext->pEditSettings->pClipList[i]->uiEndCutTime -
-            pContext->pEditSettings->pClipList[i]->uiBeginCutTime;
-        uiTotalClipDuration += uiClipDuration;
-    }
-
-    /* determine the clip whose thumbnail needs to be rendered*/
-    if (timeMs == 0) {
-        iCurrentClipIndex = 0;
-        i=0;
-    } else {
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "videoEditor_renderPreviewFrame() timeMs=%d", timeMs);
-
-        if (timeMs > uiTotalClipDuration) {
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                "videoEditor_renderPreviewFrame() timeMs > uiTotalClipDuration");
-            pMessage = videoEditJava_getErrorName(M4ERR_PARAMETER);
-            jniThrowException(pEnv, "java/lang/IllegalArgumentException", pMessage);
-            return -1;
-        }
-
-        for (i = 0; i < uiNumberOfClipsInStoryBoard; i++) {
-            if (timeMs <= (iIncrementedDuration +
-                          (pContext->pEditSettings->pClipList[i]->uiEndCutTime -
-                           pContext->pEditSettings->pClipList[i]->uiBeginCutTime)))
-            {
-                iCurrentClipIndex = i;
-                VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                    "videoEditor_renderPreviewFrame() iCurrentClipIndex=%d for timeMs=%d",
-                    iCurrentClipIndex, timeMs);
-                break;
-            }
-            else {
-                iIncrementedDuration = iIncrementedDuration +
-                    (pContext->pEditSettings->pClipList[i]->uiEndCutTime -
-                    pContext->pEditSettings->pClipList[i]->uiBeginCutTime);
-            }
-        }
-    }
-    /* If timestamp is beyond story board duration, return*/
-    if (i >= uiNumberOfClipsInStoryBoard) {
-        if (timeMs == iIncrementedDuration) {
-            iCurrentClipIndex = i-1;
-        } else {
-           return -1;
-        }
-    }
-
-    /*+ Handle the image files here */
-      if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType ==
-          /*M4VIDEOEDITING_kFileType_JPG*/ M4VIDEOEDITING_kFileType_ARGB8888 ) {
-          VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", " iCurrentClipIndex %d ", iCurrentClipIndex);
-          VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                "  Height = %d",
-                pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight);
-
-          VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                "  Width = %d",
-                pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth);
-
-          LvGetImageThumbNail((const char *)pContext->pEditSettings->\
-          pClipList[iCurrentClipIndex]->pFile,
-            pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoHeight,
-            pContext->pEditSettings->pClipList[iCurrentClipIndex]->ClipProperties.uiVideoWidth,
-            (M4OSA_Void **)&frameStr.pBuffer);
-            tnTimeMs = (M4OSA_UInt32)timeMs;
-
-          frameStr.videoRotationDegree = 0;
-    } else {
-        /* Handle 3gp/mp4 Clips here */
-        /* get thumbnail*/
-        result = ThumbnailOpen(&tnContext,
-            (const M4OSA_Char*)pContext->pEditSettings->\
-            pClipList[iCurrentClipIndex]->pFile, M4OSA_TRUE);
-        if (result != M4NO_ERROR || tnContext  == M4OSA_NULL) {
-            return -1;
-        }
-
-        /* timeMs is relative to storyboard; in this api it shud be relative to this clip */
-        if ((i >= uiNumberOfClipsInStoryBoard) &&
-            (timeMs == iIncrementedDuration)) {
-            tnTimeMs = pContext->pEditSettings->\
-            pClipList[iCurrentClipIndex]->uiEndCutTime;
-        } else {
-            tnTimeMs = pContext->pEditSettings->\
-            pClipList[iCurrentClipIndex]->uiBeginCutTime
-            + (timeMs - iIncrementedDuration);
-        }
-
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "video width = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoWidth);
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "video height = %d",pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoHeight);
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "current clip index = %d",iCurrentClipIndex);
-
-        M4OSA_UInt32 width = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoWidth;
-        M4OSA_UInt32 height = pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoHeight;
-
-        framesizeYuv = width * height * 1.5;
-
-        pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS,
-            (M4OSA_Char*)"videoEditor pixelArray");
-        if (pixelArray == M4OSA_NULL) {
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                "videoEditor_renderPreviewFrame() malloc error");
-            ThumbnailClose(tnContext);
-            pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
-            jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-            return -1;
-        }
-
-        result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray,
-            pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoWidth,
-            pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-            ClipProperties.uiVideoHeight,
-            &tnTimeMs, 0);
-        if (result != M4NO_ERROR) {
-            free(pixelArray);
-            ThumbnailClose(tnContext);
-            return -1;
-        }
-
-        ThumbnailClose(tnContext);
-        tnContext = M4OSA_NULL;
-
-#ifdef DUMPTOFILE
-        {
-            M4OSA_Context fileContext;
-            M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.raw";
-            remove((const char *)fileName);
-            M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
-                M4OSA_kFileWrite|M4OSA_kFileCreate);
-            M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray,
-                framesizeYuv);
-            M4OSA_fileWriteClose(fileContext);
-        }
-#endif
-
-        /**
-        * Allocate output YUV planes
-        */
-        yuvPlane = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(3*sizeof(M4VIFI_ImagePlane), M4VS,
-            (M4OSA_Char*)"videoEditor_renderPreviewFrame Output plane YUV");
-        if (yuvPlane == M4OSA_NULL) {
-            VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                "videoEditor_renderPreviewFrame() malloc error for yuv plane");
-            free(pixelArray);
-            pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
-            jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-            return -1;
-        }
-
-        yuvPlane[0].u_width = width;
-        yuvPlane[0].u_height = height;
-        yuvPlane[0].u_topleft = 0;
-        yuvPlane[0].u_stride = width;
-        yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray;
-
-        yuvPlane[1].u_width = width>>1;
-        yuvPlane[1].u_height = height>>1;
-        yuvPlane[1].u_topleft = 0;
-        yuvPlane[1].u_stride = width>>1;
-        yuvPlane[1].pac_data = yuvPlane[0].pac_data
-                    + yuvPlane[0].u_width * yuvPlane[0].u_height;
-        yuvPlane[2].u_width = (width)>>1;
-        yuvPlane[2].u_height = (height)>>1;
-        yuvPlane[2].u_topleft = 0;
-        yuvPlane[2].u_stride = (width)>>1;
-        yuvPlane[2].pac_data = yuvPlane[1].pac_data
-                    + yuvPlane[1].u_width * yuvPlane[1].u_height;
-
-#ifdef DUMPTOFILE
-        {
-            M4OSA_Context fileContext;
-            M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv";
-            remove((const char *)fileName);
-            M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
-                M4OSA_kFileWrite|M4OSA_kFileCreate);
-            M4OSA_fileWriteData(fileContext,
-                (M4OSA_MemAddr8) yuvPlane[0].pac_data, framesizeYuv);
-            M4OSA_fileWriteClose(fileContext);
-        }
-#endif
-
-        /* Fill up the render structure*/
-        frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data;
-
-        frameStr.videoRotationDegree = pContext->pEditSettings->\
-            pClipList[iCurrentClipIndex]->ClipProperties.videoRotationDegrees;
-    }
-
-    frameStr.timeMs = timeMs;    /* timestamp on storyboard*/
-    frameStr.uiSurfaceWidth =
-        pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-        ClipProperties.uiVideoWidth;
-    frameStr.uiSurfaceHeight =
-        pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-        ClipProperties.uiVideoHeight;
-    frameStr.uiFrameWidth =
-        pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-        ClipProperties.uiVideoWidth;
-    frameStr.uiFrameHeight =
-        pContext->pEditSettings->pClipList[iCurrentClipIndex]->\
-        ClipProperties.uiVideoHeight;
-    if (pContext->pEditSettings->nbEffects > 0) {
-        frameStr.bApplyEffect = M4OSA_TRUE;
-    } else {
-        frameStr.bApplyEffect = M4OSA_FALSE;
-    }
-    frameStr.clipBeginCutTime = iIncrementedDuration;
-    frameStr.clipEndCutTime =
-        iIncrementedDuration +
-        (pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiEndCutTime -\
-        pContext->pEditSettings->pClipList[iCurrentClipIndex]->uiBeginCutTime);
-
-    pContext->mPreviewController->setPreviewFrameRenderingMode(
-        pContext->pEditSettings->\
-        pClipList[iCurrentClipIndex]->xVSS.MediaRendering,
-        pContext->pEditSettings->xVSS.outputVideoSize);
-    result = pContext->mPreviewController->renderPreviewFrame(previewSurface,
-                                                              &frameStr, &currEditInfo);
-
-    if (currEditInfo.overlaySettingsIndex != -1) {
-        char tmpOverlayFilename[100];
-        char *extPos = NULL;
-        jstring tmpOverlayString;
-        int tmpRenderingMode = 0;
-
-        strncpy (tmpOverlayFilename,
-                (const char*)pContext->pEditSettings->Effects[currEditInfo.overlaySettingsIndex].xVSS.pFramingFilePath, 99);
-
-        //Change the name to png file
-        extPos = strstr(tmpOverlayFilename, ".rgb");
-        if (extPos != NULL) {
-            *extPos = '\0';
-        } else {
-            ALOGE("ERROR the overlay file is incorrect");
-        }
-
-        strcat(tmpOverlayFilename, ".png");
-
-        tmpRenderingMode = pContext->pEditSettings->pClipList[iCurrentClipIndex]->xVSS.MediaRendering;
-        tmpOverlayString = pEnv->NewStringUTF(tmpOverlayFilename);
-        pEnv->CallVoidMethod(pContext->engine,
-            pContext->previewFrameEditInfoId,
-            tmpOverlayString, tmpRenderingMode);
-
-    }
-
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-            (M4NO_ERROR != result), result);
-
-    free(frameStr.pBuffer);
-    if (pContext->pEditSettings->pClipList[iCurrentClipIndex]->FileType !=
-            M4VIDEOEDITING_kFileType_ARGB8888) {
-        free(yuvPlane);
-    }
-
-    return (jint)tnTimeMs;
-}
-
-static jint videoEditor_renderMediaItemPreviewFrame(JNIEnv* pEnv,
-                                                    jobject thiz,
-                                                    jobject mSurface,
-                                                    jstring filePath,
-                                                    jint    frameWidth,
-                                                    jint    frameHeight,
-                                                    jint    surfaceWidth,
-                                                    jint    surfaceHeight,
-                                                    jlong   fromMs)
-{
-    bool needToBeLoaded = true;
-    M4OSA_ERR result = M4NO_ERROR;
-    M4OSA_UInt32 timeMs = (M4OSA_UInt32)fromMs;
-    M4OSA_UInt32 framesizeYuv =0;
-    M4VIFI_UInt8 *pixelArray = M4OSA_NULL;
-    VideoEditor_renderPreviewFrameStr frameStr;
-    M4OSA_Context tnContext = M4OSA_NULL;
-    const char* pMessage = NULL;
-    M4VIFI_ImagePlane yuvPlane[3], rgbPlane;
-
-    ManualEditContext* pContext = M4OSA_NULL;
-    // Get the context.
-    pContext =
-            (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
-                                                      pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-
-    // Validate the mSurface parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == mSurface),
-                                                "mSurface is null");
-
-    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
-    const char *pString = pEnv->GetStringUTFChars(filePath, NULL);
-    if (pString == M4OSA_NULL) {
-        if (pEnv != NULL) {
-            jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
-        }
-    }
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-        "videoEditor_renderMediaItemPreviewFrame() timeMs=%d", timeMs);
-    /* get thumbnail*/
-    result = ThumbnailOpen(&tnContext,(const M4OSA_Char*)pString, M4OSA_TRUE);
-    if (result != M4NO_ERROR || tnContext  == M4OSA_NULL) {
-        return (jint)timeMs;
-    }
-
-    framesizeYuv = ((frameWidth)*(frameHeight)*1.5);
-
-    pixelArray = (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(framesizeYuv, M4VS,\
-        (M4OSA_Char*)"videoEditor pixelArray");
-    if (pixelArray == M4OSA_NULL) {
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "videoEditor_renderPreviewFrame() malloc error");
-        ThumbnailClose(tnContext);
-        pMessage = videoEditJava_getErrorName(M4ERR_ALLOC);
-        jniThrowException(pEnv, "java/lang/RuntimeException", pMessage);
-        return (jint)timeMs;
-    }
-
-    result = ThumbnailGetPixels16(tnContext, (M4OSA_Int16 *)pixelArray,
-                                                frameWidth,
-                                                frameHeight, &timeMs, 0);
-    if (result != M4NO_ERROR) {
-        free(pixelArray);
-        ThumbnailClose(tnContext);
-        return (jint)fromMs;
-    }
-
-#ifdef DUMPTOFILESYSTEM
-    {
-        M4OSA_Context fileContext;
-        M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/FirstRGB565.rgb";
-        M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
-            M4OSA_kFileWrite|M4OSA_kFileCreate);
-        M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) pixelArray,
-                            framesizeRgb);
-        M4OSA_fileWriteClose(fileContext);
-    }
-#endif
-
-    yuvPlane[0].pac_data = (M4VIFI_UInt8*)pixelArray;
-    yuvPlane[0].u_height = frameHeight;
-    yuvPlane[0].u_width = frameWidth;
-    yuvPlane[0].u_stride = yuvPlane[0].u_width;
-    yuvPlane[0].u_topleft = 0;
-
-    yuvPlane[1].u_height = frameHeight/2;
-    yuvPlane[1].u_width = frameWidth/2;
-    yuvPlane[1].u_stride = yuvPlane[1].u_width;
-    yuvPlane[1].u_topleft = 0;
-    yuvPlane[1].pac_data = yuvPlane[0].pac_data
-                + yuvPlane[0].u_width*yuvPlane[0].u_height;
-
-    yuvPlane[2].u_height = frameHeight/2;
-    yuvPlane[2].u_width = frameWidth/2;
-    yuvPlane[2].u_stride = yuvPlane[2].u_width;
-    yuvPlane[2].u_topleft = 0;
-    yuvPlane[2].pac_data = yuvPlane[0].pac_data
-        + yuvPlane[0].u_width*yuvPlane[0].u_height + \
-        (yuvPlane[0].u_width/2)*(yuvPlane[0].u_height/2);
-#ifdef DUMPTOFILESYSTEM
-    {
-        M4OSA_Context fileContext;
-        M4OSA_Char* fileName = (M4OSA_Char*)"/mnt/sdcard/ConvertedYuv.yuv";
-        M4OSA_fileWriteOpen(&fileContext, (M4OSA_Void*) fileName,\
-            M4OSA_kFileWrite|M4OSA_kFileCreate);
-        M4OSA_fileWriteData(fileContext, (M4OSA_MemAddr8) yuvPlane[0].pac_data,
-                            framesizeYuv);
-        M4OSA_fileWriteClose(fileContext);
-    }
-#endif
-
-    /* Fill up the render structure*/
-    frameStr.pBuffer = (M4OSA_Void*)yuvPlane[0].pac_data;
-    frameStr.timeMs = timeMs;    /* timestamp on storyboard*/
-    frameStr.uiSurfaceWidth = frameWidth;
-    frameStr.uiSurfaceHeight = frameHeight;
-    frameStr.uiFrameWidth = frameWidth;
-    frameStr.uiFrameHeight = frameHeight;
-    frameStr.bApplyEffect = M4OSA_FALSE;
-    // clip begin cuttime and end cuttime set to 0
-    // as its only required when effect needs to be applied while rendering
-    frameStr.clipBeginCutTime = 0;
-    frameStr.clipEndCutTime = 0;
-
-    /*  pContext->mPreviewController->setPreviewFrameRenderingMode(M4xVSS_kBlackBorders,
-    (M4VIDEOEDITING_VideoFrameSize)(M4VIDEOEDITING_kHD960+1));*/
-    result
-    = pContext->mPreviewController->renderPreviewFrame(previewSurface,&frameStr, NULL);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                                                (M4NO_ERROR != result), result);
-
-    /* free the pixelArray and yuvPlane[0].pac_data */
-    free(yuvPlane[0].pac_data);
-
-    ThumbnailClose(tnContext);
-
-    if (pString != NULL) {
-        pEnv->ReleaseStringUTFChars(filePath, pString);
-    }
-
-    return (jint)timeMs;
-}
-
-jint videoEditor_generateAudioRawFile(  JNIEnv*     pEnv,
-                                        jobject     thiz,
-                                        jstring     infilePath,
-                                        jstring     pcmfilePath)
-{
-    M4OSA_ERR result = M4NO_ERROR;
-    bool               loaded   = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-
-
-
-    const char *pInputFile = pEnv->GetStringUTFChars(infilePath, NULL);
-    if (pInputFile == M4OSA_NULL) {
-        if (pEnv != NULL) {
-            jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
-        }
-    }
-
-    const char *pStringOutPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL);
-    if (pStringOutPCMFilePath == M4OSA_NULL) {
-        if (pEnv != NULL) {
-            jniThrowException(pEnv, "java/lang/RuntimeException", "Input string null");
-        }
-    }
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-        "VIDEO_EDITOR", "videoEditor_generateAudioRawFile infilePath %s",
-        pInputFile);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO,
-        "VIDEO_EDITOR", "videoEditor_generateAudioRawFile pcmfilePath %s",
-        pStringOutPCMFilePath);
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
-    result = videoEditor_generateAudio( pEnv, pContext, (M4OSA_Char*)pInputFile,
-        (M4OSA_Char*)pStringOutPCMFilePath);
-
-    if (pInputFile != NULL) {
-        pEnv->ReleaseStringUTFChars(infilePath, pInputFile);
-    }
-    if (pStringOutPCMFilePath != NULL) {
-        pEnv->ReleaseStringUTFChars(pcmfilePath, pStringOutPCMFilePath);
-    }
-
-    return (jint)result;
-}
-
-M4OSA_ERR videoEditor_generateAudio(JNIEnv* pEnv,ManualEditContext* pContext,
-                                    M4OSA_Char* infilePath,
-                                    M4OSA_Char* pcmfilePath )
-{
-    bool                            needToBeLoaded = true;
-    M4OSA_ERR                       result = M4NO_ERROR;
-    M4MCS_Context                   mcsContext = M4OSA_NULL;
-    M4OSA_Char*                     pInputFile = M4OSA_NULL;
-    M4OSA_Char*                     pOutputFile = M4OSA_NULL;
-    M4OSA_Char*                     pTempPath = M4OSA_NULL;
-    M4MCS_OutputParams*             pOutputParams = M4OSA_NULL;
-    M4MCS_EncodingParams*           pEncodingParams = M4OSA_NULL;
-    M4OSA_Int32                     pInputFileType = 0;
-    M4OSA_UInt8                     threadProgress = 0;
-    M4OSA_Char*                     pTemp3gpFilePath = M4OSA_NULL;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio()");
-
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-        (NULL == pContext),
-        "ManualEditContext is null");
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_init()");
-
-    pOutputParams = (M4MCS_OutputParams *)M4OSA_32bitAlignedMalloc(
-        sizeof(M4MCS_OutputParams),0x00,
-        (M4OSA_Char *)"M4MCS_OutputParams");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-        (M4OSA_NULL == pOutputParams),
-        "not initialized");
-    if (needToBeLoaded == false) {
-        return M4ERR_ALLOC;
-    }
-
-    pEncodingParams = (M4MCS_EncodingParams *)M4OSA_32bitAlignedMalloc(
-        sizeof(M4MCS_EncodingParams),0x00,
-        (M4OSA_Char *)"M4MCS_EncodingParams");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-        (M4OSA_NULL == pEncodingParams),
-        "not initialized");
-    if (needToBeLoaded == false) {
-        free(pEncodingParams);
-        pEncodingParams = M4OSA_NULL;
-        return M4ERR_ALLOC;
-    }
-
-    // Initialize the MCS library.
-    result = M4MCS_init(&mcsContext, pContext->initParams.pFileReadPtr,
-        pContext->initParams.pFileWritePtr);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,\
-        (M4NO_ERROR != result), result);
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-        (M4OSA_NULL == mcsContext),
-        "not initialized");
-     if(needToBeLoaded == false) {
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-         return result;
-     }
-
-    // generate the path for temp 3gp output file
-    pTemp3gpFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc (
-        (strlen((const char*)pContext->initParams.pTempPath)
-        + strlen((const char*)TEMP_MCS_OUT_FILE_PATH)) + 1 /* for null termination */ , 0x0,
-        (M4OSA_Char*)"Malloc for temp 3gp file");
-    if (pTemp3gpFilePath != M4OSA_NULL)
-    {
-        memset((void *)pTemp3gpFilePath  ,0,
-            strlen((const char*)pContext->initParams.pTempPath)
-            + strlen((const char*)TEMP_MCS_OUT_FILE_PATH) + 1);
-        strncat((char *)pTemp3gpFilePath,
-            (const char *)pContext->initParams.pTempPath  ,
-            (size_t) ((M4OSA_Char*)pContext->initParams.pTempPath));
-        strncat((char *)pTemp3gpFilePath , (const char *)TEMP_MCS_OUT_FILE_PATH,
-            (size_t)strlen ((const char*)TEMP_MCS_OUT_FILE_PATH));
-    }
-    else {
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-         return M4ERR_ALLOC;
-    }
-
-    pInputFile = (M4OSA_Char *) infilePath; //pContext->mAudioSettings->pFile;
-    //Delete this file later
-    pOutputFile = (M4OSA_Char *) pTemp3gpFilePath;
-    // Temp folder path for VSS use = ProjectPath
-    pTempPath = (M4OSA_Char *) pContext->initParams.pTempPath;
-    pInputFileType = (M4VIDEOEDITING_FileType)pContext->mAudioSettings->fileType;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "TEMP_MCS_OUT_FILE_PATH len %d",
-        strlen ((const char*)TEMP_MCS_OUT_FILE_PATH));
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pTemp3gpFilePath %s",
-        pOutputFile);
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_open()");
-
-    result = M4MCS_open(mcsContext, pInputFile,
-        (M4VIDEOEDITING_FileType)pInputFileType,
-        pOutputFile, pTempPath);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4NO_ERROR != result), result);
-    if(needToBeLoaded == false) {
-         free(pTemp3gpFilePath);
-         pTemp3gpFilePath = M4OSA_NULL;
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-         return result;
-    }
-
-    pOutputParams->OutputFileType
-        = (M4VIDEOEDITING_FileType)M4VIDEOEDITING_kFileType_3GPP;
-    // Set the video format.
-    pOutputParams->OutputVideoFormat =
-        (M4VIDEOEDITING_VideoFormat)M4VIDEOEDITING_kNoneVideo;//M4VIDEOEDITING_kNoneVideo;
-    pOutputParams->outputVideoProfile = 1;
-    pOutputParams->outputVideoLevel = 1;
-    // Set the frame size.
-    pOutputParams->OutputVideoFrameSize
-        = (M4VIDEOEDITING_VideoFrameSize)M4VIDEOEDITING_kQCIF;
-    // Set the frame rate.
-    pOutputParams->OutputVideoFrameRate
-        = (M4VIDEOEDITING_VideoFramerate)M4VIDEOEDITING_k5_FPS;
-
-    // Set the audio format.
-    pOutputParams->OutputAudioFormat
-        = (M4VIDEOEDITING_AudioFormat)M4VIDEOEDITING_kAAC;
-    // Set the audio sampling frequency.
-    pOutputParams->OutputAudioSamplingFrequency =
-        (M4VIDEOEDITING_AudioSamplingFrequency)M4VIDEOEDITING_k32000_ASF;
-    // Set the audio mono.
-    pOutputParams->bAudioMono = false;
-    // Set the pcm file; null for now.
-    pOutputParams->pOutputPCMfile = (M4OSA_Char *)pcmfilePath;
-    //(M4OSA_Char *)"/sdcard/Output/AudioPcm.pcm";
-    // Set the audio sampling frequency.
-    pOutputParams->MediaRendering = (M4MCS_MediaRendering)M4MCS_kCropping;
-    // new params after integrating MCS 2.0
-    // Set the number of audio effects; 0 for now.
-    pOutputParams->nbEffects = 0;
-    // Set the audio effect; null for now.
-    pOutputParams->pEffects = NULL;
-    // Set the audio effect; null for now.
-    pOutputParams->bDiscardExif = M4OSA_FALSE;
-    // Set the audio effect; null for now.
-    pOutputParams->bAdjustOrientation = M4OSA_FALSE;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_setOutputParams()");
-    result = M4MCS_setOutputParams(mcsContext, pOutputParams);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                                        (M4NO_ERROR != result), result);
-    if (needToBeLoaded == false) {
-         free(pTemp3gpFilePath);
-         pTemp3gpFilePath = M4OSA_NULL;
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-        return result;
-    }
-    // Set the video bitrate.
-    pEncodingParams->OutputVideoBitrate =
-    (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_kUndefinedBitrate;
-    // Set the audio bitrate.
-    pEncodingParams->OutputAudioBitrate
-        = (M4VIDEOEDITING_Bitrate)M4VIDEOEDITING_k128_KBPS;
-    // Set the end cut time in milliseconds.
-    pEncodingParams->BeginCutTime = 0;
-    // Set the end cut time in milliseconds.
-    pEncodingParams->EndCutTime = 0;
-    // Set the output file size in bytes.
-    pEncodingParams->OutputFileSize = 0;
-    // Set video time scale.
-    pEncodingParams->OutputVideoTimescale = 0;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                            "M4MCS_setEncodingParams()");
-    result = M4MCS_setEncodingParams(mcsContext, pEncodingParams);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4NO_ERROR != result), result);
-    if (needToBeLoaded == false) {
-         free(pTemp3gpFilePath);
-         pTemp3gpFilePath = M4OSA_NULL;
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-         return result;
-    }
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                            "M4MCS_checkParamsAndStart()");
-    result = M4MCS_checkParamsAndStart(mcsContext);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4NO_ERROR != result), result);
-    if (needToBeLoaded == false) {
-         free(pTemp3gpFilePath);
-         pTemp3gpFilePath = M4OSA_NULL;
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-        return result;
-    }
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_step()");
-
-    /*+ PROGRESS CB */
-    M4OSA_UInt8 curProgress = 0;
-    int         lastProgress = 0;
-
-    ALOGV("LVME_generateAudio Current progress is =%d", curProgress);
-    pEnv->CallVoidMethod(pContext->engine,
-            pContext->onProgressUpdateMethodId, 1/*task status*/,
-            curProgress/*progress*/);
-    do {
-        result = M4MCS_step(mcsContext, &curProgress);
-
-        if (result != M4NO_ERROR) {
-            ALOGV("LVME_generateAudio M4MCS_step returned 0x%x",result);
-
-            if (result == M4MCS_WAR_TRANSCODING_DONE) {
-                ALOGV("LVME_generateAudio MCS process ended");
-
-                // Send a progress notification.
-                curProgress = 100;
-                pEnv->CallVoidMethod(pContext->engine,
-                    pContext->onProgressUpdateMethodId, 1/*task status*/,
-                    curProgress);
-                ALOGV("LVME_generateAudio Current progress is =%d", curProgress);
-            }
-        } else {
-            // Send a progress notification if needed
-            if (curProgress != lastProgress) {
-                lastProgress = curProgress;
-                pEnv->CallVoidMethod(pContext->engine,
-                    pContext->onProgressUpdateMethodId, 0/*task status*/,
-                    curProgress/*progress*/);
-                ALOGV("LVME_generateAudio Current progress is =%d",curProgress);
-            }
-        }
-    } while (result == M4NO_ERROR);
-    /*- PROGRESS CB */
-
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4MCS_WAR_TRANSCODING_DONE != result), result);
-    if (needToBeLoaded == false) {
-         free(pTemp3gpFilePath);
-         pTemp3gpFilePath = M4OSA_NULL;
-         M4MCS_abort(mcsContext);
-         free(pOutputParams);
-         pOutputParams = M4OSA_NULL;
-         free(pEncodingParams);
-         pEncodingParams = M4OSA_NULL;
-        return result;
-    }
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4MCS_abort()");
-    result = M4MCS_abort(mcsContext);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4NO_ERROR != result), result);
-
-    //pContext->mAudioSettings->pFile = pOutputParams->pOutputPCMfile;
-    remove((const char *) pTemp3gpFilePath);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_generateAudio() EXIT ");
-
-    if (pTemp3gpFilePath != M4OSA_NULL) {
-        free(pTemp3gpFilePath);
-    }
-    if (pOutputParams != M4OSA_NULL) {
-       free(pOutputParams);
-    }
-    if(pEncodingParams != M4OSA_NULL) {
-       free(pEncodingParams);
-    }
-    return result;
-}
-
-static int removeAlphafromRGB8888 (
-                        M4OSA_Char* pFramingFilePath,
-                        M4xVSS_FramingStruct *pFramingCtx)
-{
-    M4OSA_UInt32 frameSize_argb = (pFramingCtx->width * pFramingCtx->height * 4); // aRGB data
-    M4OSA_Context lImageFileFp  = M4OSA_NULL;
-    M4OSA_ERR err = M4NO_ERROR;
-
-    ALOGV("removeAlphafromRGB8888: width %d", pFramingCtx->width);
-
-    M4OSA_UInt8 *pTmpData = (M4OSA_UInt8*) M4OSA_32bitAlignedMalloc(frameSize_argb, M4VS, (M4OSA_Char*)"Image argb data");
-    if (pTmpData == M4OSA_NULL) {
-        ALOGE("Failed to allocate memory for Image clip");
-        return M4ERR_ALLOC;
-    }
-
-       /** Read the argb data from the passed file. */
-    M4OSA_ERR lerr = M4OSA_fileReadOpen(&lImageFileFp, (M4OSA_Void *) pFramingFilePath, M4OSA_kFileRead);
-
-
-    if ((lerr != M4NO_ERROR) || (lImageFileFp == M4OSA_NULL))
-    {
-        ALOGE("removeAlphafromRGB8888: Can not open the file ");
-        free(pTmpData);
-        return M4ERR_FILE_NOT_FOUND;
-    }
-
-
-    lerr = M4OSA_fileReadData(lImageFileFp, (M4OSA_MemAddr8)pTmpData, &frameSize_argb);
-    if (lerr != M4NO_ERROR)
-    {
-        ALOGE("removeAlphafromRGB8888: can not read the data ");
-        M4OSA_fileReadClose(lImageFileFp);
-        free(pTmpData);
-        return lerr;
-    }
-    M4OSA_fileReadClose(lImageFileFp);
-
-    M4OSA_UInt32 frameSize = (pFramingCtx->width * pFramingCtx->height * 3); //Size of RGB 888 data.
-
-    pFramingCtx->FramingRgb = (M4VIFI_ImagePlane*)M4OSA_32bitAlignedMalloc(
-             sizeof(M4VIFI_ImagePlane), M4VS, (M4OSA_Char*)"Image clip RGB888 data");
-    pFramingCtx->FramingRgb->pac_data = (M4VIFI_UInt8*)M4OSA_32bitAlignedMalloc(
-             frameSize, M4VS, (M4OSA_Char*)"Image clip RGB888 data");
-
-    if (pFramingCtx->FramingRgb == M4OSA_NULL)
-    {
-        ALOGE("Failed to allocate memory for Image clip");
-        free(pTmpData);
-        return M4ERR_ALLOC;
-    }
-
-    /** Remove the alpha channel */
-    for (size_t i = 0, j = 0; i < frameSize_argb; i++) {
-        if ((i % 4) == 0) continue;
-        pFramingCtx->FramingRgb->pac_data[j] = pTmpData[i];
-        j++;
-    }
-    free(pTmpData);
-    return M4NO_ERROR;
-}
-
-static void
-videoEditor_populateSettings(
-                JNIEnv*                 pEnv,
-                jobject                 thiz,
-                jobject                 settings,
-                jobject                 object,
-                jobject                 audioSettingObject)
-{
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "videoEditor_populateSettings()");
-
-    bool                needToBeLoaded  = true;
-    ManualEditContext*  pContext        = M4OSA_NULL;
-    M4OSA_ERR           result          = M4NO_ERROR;
-    jstring             strPath         = M4OSA_NULL;
-    jstring             strPCMPath      = M4OSA_NULL;
-    jobjectArray        propertiesClipsArray           = M4OSA_NULL;
-    jobject             properties      = M4OSA_NULL;
-    jint*               bitmapArray     =  M4OSA_NULL;
-    jobjectArray        effectSettingsArray = M4OSA_NULL;
-    jobject             effectSettings  = M4OSA_NULL;
-    jintArray           pixelArray      = M4OSA_NULL;
-    int width = 0;
-    int height = 0;
-    int nbOverlays = 0;
-    int i,j = 0;
-    int *pOverlayIndex = M4OSA_NULL;
-    M4OSA_Char* pTempChar = M4OSA_NULL;
-
-    // Add a code marker (the condition must always be true).
-    ADD_CODE_MARKER_FUN(NULL != pEnv)
-
-    // Validate the settings parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == settings),
-                                                "settings is null");
-    // Get the context.
-    pContext =
-            (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-    jclass mPreviewClipPropClazz = pEnv->FindClass(PREVIEW_PROPERTIES_CLASS_NAME);
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == mPreviewClipPropClazz),
-                                     "not initialized");
-
-    jfieldID fid = pEnv->GetFieldID(mPreviewClipPropClazz,"clipProperties",
-            "[L"PROPERTIES_CLASS_NAME";"  );
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == fid),
-                                     "not initialized");
-
-    propertiesClipsArray = (jobjectArray)pEnv->GetObjectField(object, fid);
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == propertiesClipsArray),
-                                     "not initialized");
-
-    jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == engineClass),
-                                     "not initialized");
-
-    pContext->onPreviewProgressUpdateMethodId = pEnv->GetMethodID(engineClass,
-            "onPreviewProgressUpdate",     "(IZZLjava/lang/String;II)V");
-    // Check if the context is valid (required because the context is dereferenced).
-    if (needToBeLoaded) {
-        // Make sure that we are in a correct state.
-        videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                             (pContext->state != ManualEditState_INITIALIZED),
-                             "settings already loaded");
-        if (needToBeLoaded) {
-            // Retrieve the edit settings.
-            if (pContext->pEditSettings != M4OSA_NULL) {
-                videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-                pContext->pEditSettings = M4OSA_NULL;
-            }
-            videoEditClasses_getEditSettings(&needToBeLoaded, pEnv,
-                settings, &pContext->pEditSettings,false);
-        }
-    }
-
-    if (needToBeLoaded == false) {
-        j = 0;
-        while (j < pContext->pEditSettings->nbEffects)
-        {
-            if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
-                if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
-                    free(pContext->pEditSettings->\
-                    Effects[j].xVSS.pFramingBuffer);
-                    pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
-                }
-            }
-          j++;
-        }
-        return;
-    }
-
-    M4OSA_TRACE1_0("videoEditorC_getEditSettings done");
-
-    pContext->previewFrameEditInfoId = pEnv->GetMethodID(engineClass,
-        "previewFrameEditInfo", "(Ljava/lang/String;I)V");
-
-    if ( pContext->pEditSettings != NULL )
-    {
-        // Check if the edit settings could be retrieved.
-        jclass mEditClazz = pEnv->FindClass(EDIT_SETTINGS_CLASS_NAME);
-        if(mEditClazz == M4OSA_NULL)
-        {
-            M4OSA_TRACE1_0("cannot find object field for mEditClazz");
-            goto videoEditor_populateSettings_cleanup;
-        }
-        jclass mEffectsClazz = pEnv->FindClass(EFFECT_SETTINGS_CLASS_NAME);
-        if(mEffectsClazz == M4OSA_NULL)
-        {
-            M4OSA_TRACE1_0("cannot find object field for mEffectsClazz");
-            goto videoEditor_populateSettings_cleanup;
-        }
-        fid = pEnv->GetFieldID(mEditClazz,"effectSettingsArray", "[L"EFFECT_SETTINGS_CLASS_NAME";"  );
-        if(fid == M4OSA_NULL)
-        {
-            M4OSA_TRACE1_0("cannot find field for effectSettingsArray Array");
-            goto videoEditor_populateSettings_cleanup;
-        }
-        effectSettingsArray = (jobjectArray)pEnv->GetObjectField(settings, fid);
-        if(effectSettingsArray == M4OSA_NULL)
-        {
-            M4OSA_TRACE1_0("cannot find object field for effectSettingsArray");
-            goto videoEditor_populateSettings_cleanup;
-        }
-
-        //int overlayIndex[pContext->pEditSettings->nbEffects];
-        if (pContext->pEditSettings->nbEffects > 0)
-        {
-            pOverlayIndex
-            = (int*) M4OSA_32bitAlignedMalloc(pContext->pEditSettings->nbEffects * sizeof(int), 0,
-                (M4OSA_Char*)"pOverlayIndex");
-            if (pOverlayIndex == M4OSA_NULL) {
-                videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                    M4OSA_TRUE, M4ERR_ALLOC);
-                goto videoEditor_populateSettings_cleanup;
-            }
-        }
-
-        i = 0;
-        j = 0;
-        M4OSA_TRACE1_1("no of effects = %d",pContext->pEditSettings->nbEffects);
-        while (j < pContext->pEditSettings->nbEffects)
-        {
-            if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL)
-            {
-                pOverlayIndex[nbOverlays] = j;
-
-                M4xVSS_FramingStruct *aFramingCtx = M4OSA_NULL;
-                aFramingCtx
-                = (M4xVSS_FramingStruct*)M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_FramingStruct), M4VS,
-                  (M4OSA_Char*)"M4xVSS_internalDecodeGIF: Context of the framing effect");
-                if (aFramingCtx == M4OSA_NULL)
-                {
-                    M4OSA_TRACE1_0("Allocation error in videoEditor_populateSettings");
-                    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                        M4OSA_TRUE, M4ERR_ALLOC);
-                    goto videoEditor_populateSettings_cleanup;
-                }
-
-                aFramingCtx->pCurrent = M4OSA_NULL; /* Only used by the first element of the chain */
-                aFramingCtx->previousClipTime = -1;
-                aFramingCtx->FramingYuv = M4OSA_NULL;
-                aFramingCtx->FramingRgb = M4OSA_NULL;
-                aFramingCtx->topleft_x
-                    = pContext->pEditSettings->Effects[j].xVSS.topleft_x;
-                aFramingCtx->topleft_y
-                    = pContext->pEditSettings->Effects[j].xVSS.topleft_y;
-
-
-                 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_width %d",
-                                        pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width);
-                 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF u_height() %d",
-                                        pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height);
-                 VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "OF rgbType() %d",
-                                        pContext->pEditSettings->Effects[j].xVSS.rgbType);
-
-                 aFramingCtx->width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width;
-                 aFramingCtx->height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
-
-                result = M4xVSS_internalConvertARGB888toYUV420_FrammingEffect(pContext->engineContext,
-                    &(pContext->pEditSettings->Effects[j]),aFramingCtx,
-                pContext->pEditSettings->Effects[j].xVSS.framingScaledSize);
-                videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                                            (M4NO_ERROR != result), result);
-                if (needToBeLoaded == false) {
-                    M4OSA_TRACE1_1("M4xVSS_internalConvertARGB888toYUV420_FrammingEffect returned 0x%x", result);
-                    if (aFramingCtx != M4OSA_NULL) {
-                        free(aFramingCtx);
-                        aFramingCtx = M4OSA_NULL;
-                    }
-                    goto videoEditor_populateSettings_cleanup;
-                }
-
-                //framing buffers are resized to fit the output video resolution.
-                pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width =
-                    aFramingCtx->FramingRgb->u_width;
-                pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height =
-                    aFramingCtx->FramingRgb->u_height;
-
-                VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->width = %d",
-                    aFramingCtx->FramingRgb->u_width);
-
-                VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "A framing Context aFramingCtx->height = %d",
-                    aFramingCtx->FramingRgb->u_height);
-
-
-                width = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_width;
-                height = pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_height;
-
-                //RGB 565
-                pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_stride = width * 2;
-
-                //for RGB565
-                pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->u_topleft = 0;
-                pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data =
-                            (M4VIFI_UInt8 *)M4OSA_32bitAlignedMalloc(width*height*2,
-                            0x00,(M4OSA_Char *)"pac_data buffer");
-
-                if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer->pac_data == M4OSA_NULL) {
-                    M4OSA_TRACE1_0("Failed to allocate memory for framing buffer");
-                    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                                            M4OSA_TRUE, M4ERR_ALLOC);
-                    goto videoEditor_populateSettings_cleanup;
-                }
-
-                memcpy((void *)&pContext->pEditSettings->\
-                    Effects[j].xVSS.pFramingBuffer->\
-                    pac_data[0],(void *)&aFramingCtx->FramingRgb->pac_data[0],(width*height*2));
-
-                //As of now rgb type is 565
-                pContext->pEditSettings->Effects[j].xVSS.rgbType =
-                    (M4VSS3GPP_RGBType) M4VSS3GPP_kRGB565;
-
-                if (aFramingCtx->FramingYuv != M4OSA_NULL )
-                {
-                    if (aFramingCtx->FramingYuv[0].pac_data != M4OSA_NULL) {
-                        free(aFramingCtx->FramingYuv[0].pac_data);
-                        aFramingCtx->FramingYuv[0].pac_data = M4OSA_NULL;
-                    }
-                    if (aFramingCtx->FramingYuv[1].pac_data != M4OSA_NULL) {
-                        free(aFramingCtx->FramingYuv[1].pac_data);
-                        aFramingCtx->FramingYuv[1].pac_data = M4OSA_NULL;
-                    }
-                    if (aFramingCtx->FramingYuv[2].pac_data != M4OSA_NULL) {
-                        free(aFramingCtx->FramingYuv[2].pac_data);
-                        aFramingCtx->FramingYuv[2].pac_data = M4OSA_NULL;
-                    }
-
-                    free(aFramingCtx->FramingYuv);
-                    aFramingCtx->FramingYuv = M4OSA_NULL;
-                }
-                if (aFramingCtx->FramingRgb->pac_data != M4OSA_NULL) {
-                    free(aFramingCtx->FramingRgb->pac_data);
-                    aFramingCtx->FramingRgb->pac_data = M4OSA_NULL;
-                }
-                if (aFramingCtx->FramingRgb != M4OSA_NULL) {
-                    free(aFramingCtx->FramingRgb);
-                    aFramingCtx->FramingRgb = M4OSA_NULL;
-                }
-                if (aFramingCtx != M4OSA_NULL) {
-                    free(aFramingCtx);
-                    aFramingCtx = M4OSA_NULL;
-                }
-                nbOverlays++;
-            }
-            j++;
-        }
-
-        // Check if the edit settings could be retrieved.
-        M4OSA_TRACE1_1("total clips are = %d",pContext->pEditSettings->uiClipNumber);
-        for (i = 0; i < pContext->pEditSettings->uiClipNumber; i++) {
-            M4OSA_TRACE1_1("clip no = %d",i);
-            properties = pEnv->GetObjectArrayElement(propertiesClipsArray, i);
-            videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                (M4OSA_NULL == properties),
-                "not initialized");
-            if (needToBeLoaded) {
-                getClipSetting(pEnv,properties, pContext->pEditSettings->pClipList[i]);
-                pEnv->DeleteLocalRef(properties);
-            } else {
-                pEnv->DeleteLocalRef(properties);
-                goto videoEditor_populateSettings_cleanup;
-            }
-        }
-
-        if (needToBeLoaded) {
-            // Log the edit settings.
-            VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings);
-        }
-    }
-    /* free previous allocations , if any */
-    if (pContext->mAudioSettings != M4OSA_NULL) {
-        if (pContext->mAudioSettings->pFile != NULL) {
-            free(pContext->mAudioSettings->pFile);
-            pContext->mAudioSettings->pFile = M4OSA_NULL;
-        }
-        if (pContext->mAudioSettings->pPCMFilePath != NULL) {
-            free(pContext->mAudioSettings->pPCMFilePath);
-            pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
-        }
-    }
-
-    if (audioSettingObject != M4OSA_NULL) {
-        jclass audioSettingClazz = pEnv->FindClass(AUDIO_SETTINGS_CLASS_NAME);
-        videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                         (M4OSA_NULL == audioSettingClazz),
-                                         "not initialized");
-
-        videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == pContext->mAudioSettings),
-                                     "not initialized");
-
-        if (needToBeLoaded == false) {
-            goto videoEditor_populateSettings_cleanup;
-        }
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"bRemoveOriginal","Z");
-        pContext->mAudioSettings->bRemoveOriginal =
-            pEnv->GetBooleanField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("bRemoveOriginal = %d",pContext->mAudioSettings->bRemoveOriginal);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"channels","I");
-        pContext->mAudioSettings->uiNbChannels = pEnv->GetIntField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("uiNbChannels = %d",pContext->mAudioSettings->uiNbChannels);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"Fs","I");
-        pContext->mAudioSettings->uiSamplingFrequency = pEnv->GetIntField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("uiSamplingFrequency = %d",pContext->mAudioSettings->uiSamplingFrequency);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"ExtendedFs","I");
-        pContext->mAudioSettings->uiExtendedSamplingFrequency =
-         pEnv->GetIntField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("uiExtendedSamplingFrequency = %d",
-        pContext->mAudioSettings->uiExtendedSamplingFrequency);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"startMs","J");
-        pContext->mAudioSettings->uiAddCts
-            = pEnv->GetLongField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("uiAddCts = %d",pContext->mAudioSettings->uiAddCts);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"volume","I");
-        pContext->mAudioSettings->uiAddVolume
-            = pEnv->GetIntField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("uiAddVolume = %d",pContext->mAudioSettings->uiAddVolume);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"loop","Z");
-        pContext->mAudioSettings->bLoop
-            = pEnv->GetBooleanField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("bLoop = %d",pContext->mAudioSettings->bLoop);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"beginCutTime","J");
-        pContext->mAudioSettings->beginCutMs
-            = pEnv->GetLongField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("begin cut time = %d",pContext->mAudioSettings->beginCutMs);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"endCutTime","J");
-        pContext->mAudioSettings->endCutMs
-            = pEnv->GetLongField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("end cut time = %d",pContext->mAudioSettings->endCutMs);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"fileType","I");
-        pContext->mAudioSettings->fileType
-            = pEnv->GetIntField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("fileType = %d",pContext->mAudioSettings->fileType);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"pFile","Ljava/lang/String;");
-        strPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
-        pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPath, M4OSA_NULL);
-        if (pTempChar != NULL) {
-            pContext->mAudioSettings->pFile = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(
-                (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
-                (M4OSA_Char*)"strPath allocation " );
-            if (pContext->mAudioSettings->pFile != M4OSA_NULL) {
-                memcpy((void *)pContext->mAudioSettings->pFile ,
-                    (void *)pTempChar , strlen((const char*)pTempChar));
-                ((M4OSA_Int8 *)(pContext->mAudioSettings->pFile))[strlen((const char*)pTempChar)] = '\0';
-                pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
-            } else {
-                pEnv->ReleaseStringUTFChars(strPath,(const char *)pTempChar);
-                VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                    "regenerateAudio() Malloc failed for pContext->mAudioSettings->pFile ");
-                videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                    M4OSA_TRUE, M4ERR_ALLOC);
-                goto videoEditor_populateSettings_cleanup;
-            }
-        }
-        M4OSA_TRACE1_1("file name = %s",pContext->mAudioSettings->pFile);
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio() file name = %s",\
-        pContext->mAudioSettings->pFile);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"pcmFilePath","Ljava/lang/String;");
-        strPCMPath = (jstring)pEnv->GetObjectField(audioSettingObject,fid);
-        pTempChar = (M4OSA_Char*)pEnv->GetStringUTFChars(strPCMPath, M4OSA_NULL);
-        if (pTempChar != NULL) {
-            pContext->mAudioSettings->pPCMFilePath = (M4OSA_Char*) M4OSA_32bitAlignedMalloc(
-                (M4OSA_UInt32)(strlen((const char*)pTempChar))+1 /* +1 for NULL termination */, 0,
-                (M4OSA_Char*)"strPCMPath allocation " );
-            if (pContext->mAudioSettings->pPCMFilePath != M4OSA_NULL) {
-                memcpy((void *)pContext->mAudioSettings->pPCMFilePath ,
-                    (void *)pTempChar , strlen((const char*)pTempChar));
-                ((M4OSA_Int8 *)(pContext->mAudioSettings->pPCMFilePath))[strlen((const char*)pTempChar)] = '\0';
-                pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
-            } else {
-                pEnv->ReleaseStringUTFChars(strPCMPath,(const char *)pTempChar);
-                VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-                    "regenerateAudio() Malloc failed for pContext->mAudioSettings->pPCMFilePath ");
-                videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                    M4OSA_TRUE, M4ERR_ALLOC);
-                goto videoEditor_populateSettings_cleanup;
-            }
-        }
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "pPCMFilePath -- %s ",\
-        pContext->mAudioSettings->pPCMFilePath);
-
-        fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
-        bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
-
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEOEDITOR", "regenerateAudio -- %d ",\
-        regenerateAudio);
-
-        if (regenerateAudio) {
-            M4OSA_TRACE1_0("Calling Generate Audio now");
-            result = videoEditor_generateAudio(pEnv,
-                        pContext,
-                        (M4OSA_Char*)pContext->mAudioSettings->pFile,
-                        (M4OSA_Char*)pContext->mAudioSettings->pPCMFilePath);
-
-            videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                (M4NO_ERROR != result), result);
-            if (needToBeLoaded == false) {
-                goto videoEditor_populateSettings_cleanup;
-            }
-
-            regenerateAudio = false;
-            pEnv->SetBooleanField(thiz,fid,regenerateAudio);
-        }
-
-        /* Audio mix and duck */
-        fid = pEnv->GetFieldID(audioSettingClazz,"ducking_threshold","I");
-        pContext->mAudioSettings->uiInDucking_threshold
-            = pEnv->GetIntField(audioSettingObject,fid);
-
-        M4OSA_TRACE1_1("ducking threshold = %d",
-            pContext->mAudioSettings->uiInDucking_threshold);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"ducking_lowVolume","I");
-        pContext->mAudioSettings->uiInDucking_lowVolume
-            = pEnv->GetIntField(audioSettingObject,fid);
-
-        M4OSA_TRACE1_1("ducking lowVolume = %d",
-            pContext->mAudioSettings->uiInDucking_lowVolume);
-
-        fid = pEnv->GetFieldID(audioSettingClazz,"bInDucking_enable","Z");
-        pContext->mAudioSettings->bInDucking_enable
-            = pEnv->GetBooleanField(audioSettingObject,fid);
-        M4OSA_TRACE1_1("ducking lowVolume = %d",
-            pContext->mAudioSettings->bInDucking_enable);
-
-    } else {
-        if (pContext->mAudioSettings != M4OSA_NULL) {
-            pContext->mAudioSettings->pFile = M4OSA_NULL;
-            pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
-            pContext->mAudioSettings->bRemoveOriginal = 0;
-            pContext->mAudioSettings->uiNbChannels = 0;
-            pContext->mAudioSettings->uiSamplingFrequency = 0;
-            pContext->mAudioSettings->uiExtendedSamplingFrequency = 0;
-            pContext->mAudioSettings->uiAddCts = 0;
-            pContext->mAudioSettings->uiAddVolume = 0;
-            pContext->mAudioSettings->beginCutMs = 0;
-            pContext->mAudioSettings->endCutMs = 0;
-            pContext->mAudioSettings->fileType = 0;
-            pContext->mAudioSettings->bLoop = 0;
-            pContext->mAudioSettings->uiInDucking_lowVolume  = 0;
-            pContext->mAudioSettings->bInDucking_enable  = 0;
-            pContext->mAudioSettings->uiBTChannelCount  = 0;
-            pContext->mAudioSettings->uiInDucking_threshold = 0;
-
-            fid = pEnv->GetFieldID(engineClass,"mRegenerateAudio","Z");
-            bool regenerateAudio = pEnv->GetBooleanField(thiz,fid);
-            if (!regenerateAudio) {
-                regenerateAudio = true;
-                pEnv->SetBooleanField(thiz,fid,regenerateAudio);
-            }
-        }
-    }
-
-    if (pContext->pEditSettings != NULL)
-    {
-        result = pContext->mPreviewController->loadEditSettings(pContext->pEditSettings,
-            pContext->mAudioSettings);
-        videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-                                            (M4NO_ERROR != result), result);
-
-        if (needToBeLoaded) {
-            pContext->mPreviewController->setJniCallback((void*)pContext,
-            (jni_progress_callback_fct)jniPreviewProgressCallback);
-        }
-    }
-
-videoEditor_populateSettings_cleanup:
-        j = 0;
-        while (j < nbOverlays)
-        {
-            if (pContext->pEditSettings->Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data != \
-                M4OSA_NULL) {
-                free(pContext->pEditSettings->\
-                Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data);
-                pContext->pEditSettings->\
-                Effects[pOverlayIndex[j]].xVSS.pFramingBuffer->pac_data = M4OSA_NULL;
-            }
-            j++;
-        }
-
-        j = 0;
-        while (j < pContext->pEditSettings->nbEffects)
-        {
-            if (pContext->pEditSettings->Effects[j].xVSS.pFramingFilePath != M4OSA_NULL) {
-                if (pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer != M4OSA_NULL) {
-                    free(pContext->pEditSettings->\
-                    Effects[j].xVSS.pFramingBuffer);
-                    pContext->pEditSettings->Effects[j].xVSS.pFramingBuffer = M4OSA_NULL;
-                }
-            }
-          j++;
-        }
-
-    if (pOverlayIndex != M4OSA_NULL)
-    {
-        free(pOverlayIndex);
-        pOverlayIndex = M4OSA_NULL;
-    }
-    return;
-}
-
-static void
-videoEditor_startPreview(
-                JNIEnv*                 pEnv,
-                jobject                 thiz,
-                jobject                 mSurface,
-                jlong                   fromMs,
-                jlong                   toMs,
-                jint                    callbackInterval,
-                jboolean                loop)
-{
-    bool needToBeLoaded = true;
-    M4OSA_ERR result = M4NO_ERROR;
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_startPreview()");
-
-    ManualEditContext* pContext = M4OSA_NULL;
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                     (M4OSA_NULL == pContext->mAudioSettings),
-                                     "not initialized");
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-
-    // Validate the mSurface parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == mSurface),
-                                                "mSurface is null");
-
-    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
-
-    // Validate the mSurface's mNativeSurface field
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                                (NULL == previewSurface.get()),
-                                                "mNativeSurface is null");
-
-    result =  pContext->mPreviewController->setSurface(previewSurface);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv,
-        (M4NO_ERROR != result), result);
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "fromMs=%ld, toMs=%ld",
-        (M4OSA_UInt32)fromMs, (M4OSA_Int32)toMs);
-
-    result = pContext->mPreviewController->startPreview((M4OSA_UInt32)fromMs,
-                                                (M4OSA_Int32)toMs,
-                                                (M4OSA_UInt16)callbackInterval,
-                                                (M4OSA_Bool)loop);
-    videoEditJava_checkAndThrowRuntimeException(&needToBeLoaded, pEnv, (M4NO_ERROR != result), result);
-}
-
-
-static jobject
-videoEditor_getProperties(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             file)
-{
-    jobject object = M4OSA_NULL;
-    jclass clazz = pEnv->FindClass(PROPERTIES_CLASS_NAME);
-    jfieldID fid;
-    bool needToBeLoaded = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-    M4OSA_ERR          result   = M4NO_ERROR;
-    int profile = 0;
-    int level = 0;
-    int videoFormat = 0;
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == clazz),
-                                             "not initialized");
-
-    object = videoEditProp_getProperties(pEnv,thiz,file);
-
-    if (object != M4OSA_NULL) {
-        fid = pEnv->GetFieldID(clazz,"profile","I");
-        profile = pEnv->GetIntField(object,fid);
-        fid = pEnv->GetFieldID(clazz,"level","I");
-        level = pEnv->GetIntField(object,fid);
-        fid = pEnv->GetFieldID(clazz,"videoFormat","I");
-        videoFormat = pEnv->GetIntField(object,fid);
-
-        result = checkClipVideoProfileAndLevel(pContext->decoders, videoFormat, profile, level);
-
-        fid = pEnv->GetFieldID(clazz,"profileSupported","Z");
-        if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_PROFILE == result) {
-            pEnv->SetBooleanField(object,fid,false);
-        }
-
-        fid = pEnv->GetFieldID(clazz,"levelSupported","Z");
-        if (M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_LEVEL == result) {
-            pEnv->SetBooleanField(object,fid,false);
-        }
-    }
-    return object;
-
-}
-static jint videoEditor_getPixels(
-                    JNIEnv*                     env,
-                    jobject                     thiz,
-                    jstring                     path,
-                    jintArray                   pixelArray,
-                    M4OSA_UInt32                width,
-                    M4OSA_UInt32                height,
-                    M4OSA_UInt32                timeMS)
-{
-
-    M4OSA_ERR       err = M4NO_ERROR;
-    M4OSA_Context   mContext = M4OSA_NULL;
-    jint*           m_dst32 = M4OSA_NULL;
-
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != env)
-
-    const char *pString = env->GetStringUTFChars(path, NULL);
-    if (pString == M4OSA_NULL) {
-        if (env != NULL) {
-            jniThrowException(env, "java/lang/RuntimeException", "Input string null");
-        }
-        return M4ERR_ALLOC;
-    }
-
-    err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE);
-    if (err != M4NO_ERROR || mContext == M4OSA_NULL) {
-        if (pString != NULL) {
-            env->ReleaseStringUTFChars(path, pString);
-        }
-        if (env != NULL) {
-            jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed");
-        }
-    }
-
-    m_dst32 = env->GetIntArrayElements(pixelArray, NULL);
-
-    err = ThumbnailGetPixels32(mContext, (M4OSA_Int32 *)m_dst32, width,height,&timeMS,0);
-    if (err != M4NO_ERROR ) {
-        if (env != NULL) {
-            jniThrowException(env, "java/lang/RuntimeException",\
-                "ThumbnailGetPixels32 failed");
-        }
-    }
-    env->ReleaseIntArrayElements(pixelArray, m_dst32, 0);
-
-    ThumbnailClose(mContext);
-    if (pString != NULL) {
-        env->ReleaseStringUTFChars(path, pString);
-    }
-
-    return (jint)timeMS;
-}
-
-static jint videoEditor_getPixelsList(
-                JNIEnv*                 env,
-                jobject                 thiz,
-                jstring                 path,
-                jintArray               pixelArray,
-                M4OSA_UInt32            width,
-                M4OSA_UInt32            height,
-                M4OSA_UInt32            noOfThumbnails,
-                jlong                   startTime,
-                jlong                   endTime,
-                jintArray               indexArray,
-                jobject                 callback)
-{
-
-    M4OSA_ERR           err = M4NO_ERROR;
-    M4OSA_Context       mContext = M4OSA_NULL;
-
-    const char *pString = env->GetStringUTFChars(path, NULL);
-    if (pString == M4OSA_NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "Input string null");
-        return (jint)M4ERR_ALLOC;
-    }
-
-    err = ThumbnailOpen(&mContext,(const M4OSA_Char*)pString, M4OSA_FALSE);
-    if (err != M4NO_ERROR || mContext == M4OSA_NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "ThumbnailOpen failed");
-        if (pString != NULL) {
-            env->ReleaseStringUTFChars(path, pString);
-        }
-        return (jint)err;
-    }
-
-    jlong duration = (endTime - startTime);
-    M4OSA_UInt32 tolerance = duration / (2 * noOfThumbnails);
-    jint* m_dst32 = env->GetIntArrayElements(pixelArray, NULL);
-    jint* indices = env->GetIntArrayElements(indexArray, NULL);
-    jsize len = env->GetArrayLength(indexArray);
-
-    jclass cls = env->GetObjectClass(callback);
-    jmethodID mid = env->GetMethodID(cls, "onThumbnail", "(I)V");
-
-    for (int i = 0; i < len; i++) {
-        int k = indices[i];
-        M4OSA_UInt32 timeMS = startTime;
-        timeMS += (2 * k + 1) * duration / (2 * noOfThumbnails);
-        err = ThumbnailGetPixels32(mContext, ((M4OSA_Int32 *)m_dst32),
-            width, height, &timeMS, tolerance);
-        if (err != M4NO_ERROR) {
-            break;
-        }
-        env->CallVoidMethod(callback, mid, (jint)k);
-        if (env->ExceptionCheck()) {
-            err = M4ERR_ALLOC;
-            break;
-        }
-    }
-
-    env->ReleaseIntArrayElements(pixelArray, m_dst32, 0);
-    env->ReleaseIntArrayElements(indexArray, indices, 0);
-
-    ThumbnailClose(mContext);
-    if (pString != NULL) {
-        env->ReleaseStringUTFChars(path, pString);
-    }
-
-    if (err != M4NO_ERROR && !env->ExceptionCheck()) {
-        jniThrowException(env, "java/lang/RuntimeException",\
-                "ThumbnailGetPixels32 failed");
-    }
-
-    return (jint)err;
-}
-
-static M4OSA_ERR
-videoEditor_toUTF8Fct(
-                M4OSA_Void*                         pBufferIn,
-                M4OSA_UInt8*                        pBufferOut,
-                M4OSA_UInt32*                       bufferOutSize)
-{
-    M4OSA_ERR    result = M4NO_ERROR;
-    M4OSA_UInt32 length = 0;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_toUTF8Fct()");
-
-    // Determine the length of the input buffer.
-    if (M4OSA_NULL != pBufferIn)
-    {
-        length = strlen((const char *)pBufferIn);
-    }
-
-    // Check if the output buffer is large enough to hold the input buffer.
-    if ((*bufferOutSize) > length)
-    {
-        // Check if the input buffer is not M4OSA_NULL.
-        if (M4OSA_NULL != pBufferIn)
-        {
-            // Copy the temp path, ignore the result.
-            M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length);
-        }
-        else
-        {
-            // Set the output buffer to an empty string.
-            (*(M4OSA_Char *)pBufferOut) = 0;
-        }
-    }
-    else
-    {
-        // The buffer is too small.
-        result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL;
-    }
-
-    // Return the buffer output size.
-    (*bufferOutSize) = length + 1;
-
-    // Return the result.
-    return(result);
-}
-
-static M4OSA_ERR
-videoEditor_fromUTF8Fct(
-                M4OSA_UInt8*                        pBufferIn,
-                M4OSA_Void*                         pBufferOut,
-                M4OSA_UInt32*                       bufferOutSize)
-{
-    M4OSA_ERR    result = M4NO_ERROR;
-    M4OSA_UInt32 length = 0;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_fromUTF8Fct()");
-
-    // Determine the length of the input buffer.
-    if (M4OSA_NULL != pBufferIn)
-    {
-        length = strlen((const char *)pBufferIn);
-    }
-
-    // Check if the output buffer is large enough to hold the input buffer.
-    if ((*bufferOutSize) > length)
-    {
-        // Check if the input buffer is not M4OSA_NULL.
-        if (M4OSA_NULL != pBufferIn)
-        {
-            // Copy the temp path, ignore the result.
-            M4OSA_chrNCopy((M4OSA_Char *)pBufferOut, (M4OSA_Char *)pBufferIn, length);
-        }
-        else
-        {
-            // Set the output buffer to an empty string.
-            (*(M4OSA_Char *)pBufferOut) = 0;
-        }
-    }
-    else
-    {
-        // The buffer is too small.
-        result = M4xVSSWAR_BUFFER_OUT_TOO_SMALL;
-    }
-
-    // Return the buffer output size.
-    (*bufferOutSize) = length + 1;
-
-    // Return the result.
-    return(result);
-}
-
-static M4OSA_ERR
-videoEditor_getTextRgbBufferFct(
-                M4OSA_Void*                         pRenderingData,
-                M4OSA_Void*                         pTextBuffer,
-                M4OSA_UInt32                        textBufferSize,
-                M4VIFI_ImagePlane**                 pOutputPlane)
-{
-    M4OSA_ERR result = M4NO_ERROR;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getTextRgbBufferFct()");
-
-    // Return the result.
-    return(result);
-}
-
-static void
-videoEditor_callOnProgressUpdate(
-                ManualEditContext*                  pContext,
-                int                                 task,
-                int                                 progress)
-{
-    JNIEnv* pEnv = NULL;
-
-
-    // Attach the current thread.
-    pContext->pVM->AttachCurrentThread(&pEnv, NULL);
-
-
-    // Call the on completion callback.
-    pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId,
-     videoEditJava_getEngineCToJava(task), progress);
-
-
-    // Detach the current thread.
-    pContext->pVM->DetachCurrentThread();
-}
-
-static void
-videoEditor_freeContext(
-                JNIEnv*                             pEnv,
-                ManualEditContext**                 ppContext)
-{
-    ManualEditContext* pContext = M4OSA_NULL;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_freeContext");
-
-    // Set the context pointer.
-    pContext = (*ppContext);
-
-    // Check if the context was set.
-    if (M4OSA_NULL != pContext)
-    {
-        // Check if a global reference to the engine object was set.
-        if (NULL != pContext->engine)
-        {
-            // Free the global reference.
-            pEnv->DeleteGlobalRef(pContext->engine);
-            pContext->engine = NULL;
-        }
-
-        // Check if the temp path was set.
-        if (M4OSA_NULL != pContext->initParams.pTempPath)
-        {
-            // Free the memory allocated for the temp path.
-            videoEditOsal_free(pContext->initParams.pTempPath);
-            pContext->initParams.pTempPath = M4OSA_NULL;
-        }
-
-        // Check if the file writer was set.
-        if (M4OSA_NULL != pContext->initParams.pFileWritePtr)
-        {
-            // Free the memory allocated for the file writer.
-            videoEditOsal_free(pContext->initParams.pFileWritePtr);
-            pContext->initParams.pFileWritePtr = M4OSA_NULL;
-        }
-
-        // Check if the file reader was set.
-        if (M4OSA_NULL != pContext->initParams.pFileReadPtr)
-        {
-            // Free the memory allocated for the file reader.
-            videoEditOsal_free(pContext->initParams.pFileReadPtr);
-            pContext->initParams.pFileReadPtr = M4OSA_NULL;
-        }
-
-        // Free the memory allocated for the context.
-        videoEditOsal_free(pContext);
-        pContext = M4OSA_NULL;
-
-        // Reset the context pointer.
-        (*ppContext) = M4OSA_NULL;
-    }
-}
-
-static jobject
-videoEditor_getVersion(
-                JNIEnv*                             pEnv,
-                jobject                             thiz)
-{
-    bool           isSuccessful          = true;
-    jobject        version         = NULL;
-    M4_VersionInfo versionInfo     = {0, 0, 0, 0};
-    M4OSA_ERR      result          = M4NO_ERROR;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion()");
-
-    versionInfo.m_structSize = sizeof(versionInfo);
-    versionInfo.m_major = VIDEOEDITOR_VERSION_MAJOR;
-    versionInfo.m_minor = VIDEOEDITOR_VERSION_MINOR;
-    versionInfo.m_revision = VIDEOEDITOR_VERSION_REVISION;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_getVersion() major %d,\
-     minor %d, revision %d", versionInfo.m_major, versionInfo.m_minor, versionInfo.m_revision);
-
-    // Create a version object.
-    videoEditClasses_createVersion(&isSuccessful, pEnv, &versionInfo, &version);
-
-    // Return the version object.
-    return(version);
-}
-
-static void
-videoEditor_init(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             tempPath,
-                jstring                             libraryPath)
-{
-    bool                  initialized            = true;
-    ManualEditContext*    pContext               = M4OSA_NULL;
-    VideoEditJava_EngineMethodIds methodIds              = {NULL};
-    M4OSA_Char*           pLibraryPath           = M4OSA_NULL;
-    M4OSA_Char*           pTextRendererPath      = M4OSA_NULL;
-    M4OSA_UInt32          textRendererPathLength = 0;
-    M4OSA_ERR             result                 = M4NO_ERROR;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_init()");
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&initialized, pEnv, thiz);
-
-    // Get the engine method ids.
-    videoEditJava_getEngineMethodIds(&initialized, pEnv, &methodIds);
-
-    // Validate the tempPath parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&initialized, pEnv,
-                                                (NULL == tempPath),
-                                                "tempPath is null");
-
-    // Make sure that the context was not set already.
-    videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
-                                             (M4OSA_NULL != pContext),
-                                             "already initialized");
-
-    // Check if the initialization succeeded (required because of dereferencing of psContext,
-    // and freeing when initialization fails).
-    if (initialized)
-    {
-        // Allocate a new context.
-        pContext = new ManualEditContext;
-
-        // Check if the initialization succeeded (required because of dereferencing of psContext).
-        //if (initialized)
-        if (pContext != NULL)
-        {
-            // Set the state to not initialized.
-            pContext->state = ManualEditState_NOT_INITIALIZED;
-
-            // Allocate a file read pointer structure.
-            pContext->initParams.pFileReadPtr =
-             (M4OSA_FileReadPointer*)videoEditOsal_alloc(&initialized, pEnv,
-              sizeof(M4OSA_FileReadPointer), "FileReadPointer");
-
-            // Allocate a file write pointer structure.
-            pContext->initParams.pFileWritePtr =
-             (M4OSA_FileWriterPointer*)videoEditOsal_alloc(&initialized, pEnv,
-              sizeof(M4OSA_FileWriterPointer), "FileWriterPointer");
-
-            // Get the temp path.
-            M4OSA_Char* tmpString =
-                (M4OSA_Char *)videoEditJava_getString(&initialized, pEnv, tempPath,
-                NULL, M4OSA_NULL);
-            M4OSA_UInt32 length = strlen((const char *)tmpString);
-            // Malloc additional 2 bytes for beginning and tail separator.
-            M4OSA_UInt32 pathLength = length + 2;
-
-            pContext->initParams.pTempPath = (M4OSA_Char *)
-                 M4OSA_32bitAlignedMalloc(pathLength, 0x0, (M4OSA_Char *)"tempPath");
-
-            //initialize the first char. so that strcat works.
-            M4OSA_Char *ptmpChar = (M4OSA_Char*)pContext->initParams.pTempPath;
-            ptmpChar[0] = 0x00;
-            strncat((char *)pContext->initParams.pTempPath, (const char *)tmpString,
-                length);
-            strncat((char *)pContext->initParams.pTempPath, (const char *)"/", (size_t)1);
-            free(tmpString);
-            tmpString = NULL;
-            pContext->mIsUpdateOverlay = false;
-            pContext->mOverlayFileName = NULL;
-            pContext->decoders = NULL;
-        }
-
-        // Check if the initialization succeeded
-        // (required because of dereferencing of pContext, pFileReadPtr and pFileWritePtr).
-        if (initialized)
-        {
-
-            // Initialize the OSAL file system function pointers.
-            videoEditOsal_getFilePointers(pContext->initParams.pFileReadPtr ,
-                                          pContext->initParams.pFileWritePtr);
-
-            // Set the UTF8 conversion functions.
-            pContext->initParams.pConvToUTF8Fct   = videoEditor_toUTF8Fct;
-            pContext->initParams.pConvFromUTF8Fct = videoEditor_fromUTF8Fct;
-
-            // Set the callback method ids.
-            pContext->onProgressUpdateMethodId = methodIds.onProgressUpdate;
-
-            // Set the virtual machine.
-            pEnv->GetJavaVM(&(pContext->pVM));
-
-            // Create a global reference to the engine object.
-            pContext->engine = pEnv->NewGlobalRef(thiz);
-
-            // Check if the global reference could be created.
-            videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
-             (NULL == pContext->engine), M4NO_ERROR);
-        }
-
-        // Check if the initialization succeeded (required because of dereferencing of pContext).
-        if (initialized)
-        {
-            // Log the API call.
-            VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "M4xVSS_Init()");
-
-            // Initialize the visual studio library.
-            result = M4xVSS_Init(&pContext->engineContext, &pContext->initParams);
-
-            // Log the result.
-            VIDEOEDIT_LOG_RESULT(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-             videoEditOsal_getResultString(result));
-
-            // Check if the library could be initialized.
-            videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
-             (M4NO_ERROR != result), result);
-
-            // Get platform video decoder capablities.
-            result = M4xVSS_getVideoDecoderCapabilities(&pContext->decoders);
-
-            videoEditJava_checkAndThrowRuntimeException(&initialized, pEnv,
-             (M4NO_ERROR != result), result);
-        }
-
-        if(initialized)
-        {
-            pContext->mPreviewController = new VideoEditorPreviewController();
-            videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
-                                 (M4OSA_NULL == pContext->mPreviewController),
-                                 "not initialized");
-            pContext->mAudioSettings =
-             (M4xVSS_AudioMixingSettings *)
-             M4OSA_32bitAlignedMalloc(sizeof(M4xVSS_AudioMixingSettings),0x0,
-             (M4OSA_Char *)"mAudioSettings");
-            videoEditJava_checkAndThrowIllegalStateException(&initialized, pEnv,
-                                     (M4OSA_NULL == pContext->mAudioSettings),
-                                     "not initialized");
-            pContext->mAudioSettings->pFile = M4OSA_NULL;
-            pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
-            pContext->mAudioSettings->bRemoveOriginal = 0;
-            pContext->mAudioSettings->uiNbChannels = 0;
-            pContext->mAudioSettings->uiSamplingFrequency = 0;
-            pContext->mAudioSettings->uiExtendedSamplingFrequency = 0;
-            pContext->mAudioSettings->uiAddCts = 0;
-            pContext->mAudioSettings->uiAddVolume = 0;
-            pContext->mAudioSettings->beginCutMs = 0;
-            pContext->mAudioSettings->endCutMs = 0;
-            pContext->mAudioSettings->fileType = 0;
-            pContext->mAudioSettings->bLoop = 0;
-            pContext->mAudioSettings->uiInDucking_lowVolume  = 0;
-            pContext->mAudioSettings->bInDucking_enable  = 0;
-            pContext->mAudioSettings->uiBTChannelCount  = 0;
-            pContext->mAudioSettings->uiInDucking_threshold = 0;
-        }
-        // Check if the library could be initialized.
-        if (initialized)
-        {
-            // Set the state to initialized.
-            pContext->state = ManualEditState_INITIALIZED;
-        }
-
-        // Set the context.
-        videoEditClasses_setContext(&initialized, pEnv, thiz, (void* )pContext);
-        pLibraryPath = M4OSA_NULL;
-
-        pContext->pEditSettings = M4OSA_NULL;
-        // Cleanup if anything went wrong during initialization.
-        if (!initialized)
-        {
-            // Free the context.
-            videoEditor_freeContext(pEnv, &pContext);
-        }
-    }
-}
-
-/*+ PROGRESS CB */
-static
-M4OSA_ERR videoEditor_processClip(
-                            JNIEnv*  pEnv,
-                            jobject  thiz,
-                            int      unuseditemID) {
-
-    bool               loaded           = true;
-    ManualEditContext* pContext         = NULL;
-    M4OSA_UInt8        progress         = 0;
-    M4OSA_UInt8        progressBase     = 0;
-    M4OSA_UInt8        lastProgress     = 0;
-    M4OSA_ERR          result           = M4NO_ERROR;
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // We start in Analyzing state
-    pContext->state = ManualEditState_INITIALIZED;
-    M4OSA_ERR          completionResult = M4VSS3GPP_WAR_ANALYZING_DONE;
-    ManualEditState    completionState  = ManualEditState_OPENED;
-    ManualEditState    errorState       = ManualEditState_ANALYZING_ERROR;
-
-    // While analyzing progress goes from 0 to 10 (except Kenburn clip
-    // generation, which goes from 0 to 50)
-    progressBase     = 0;
-
-    // Set the text rendering function.
-    if (M4OSA_NULL != pContext->pTextRendererFunction)
-    {
-        // Use the text renderer function in the library.
-        pContext->pEditSettings->xVSS.pTextRenderingFct = pContext->pTextRendererFunction;
-    }
-    else
-    {
-        // Use the internal text renderer function.
-        pContext->pEditSettings->xVSS.pTextRenderingFct = videoEditor_getTextRgbBufferFct;
-    }
-
-    // Send the command.
-    ALOGV("videoEditor_processClip ITEM %d Calling M4xVSS_SendCommand()", unuseditemID);
-    result = M4xVSS_SendCommand(pContext->engineContext, pContext->pEditSettings);
-    ALOGV("videoEditor_processClip ITEM %d M4xVSS_SendCommand() returned 0x%x",
-        unuseditemID, (unsigned int) result);
-
-    // Remove warnings indications (we only care about errors here)
-    if ((result == M4VSS3GPP_WAR_TRANSCODING_NECESSARY)
-        || (result == M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED)) {
-        result = M4NO_ERROR;
-    }
-
-    // Send the first progress indication (=0)
-    ALOGV("VERY FIRST PROGRESS videoEditor_processClip ITEM %d Progress indication %d",
-        unuseditemID, progress);
-    pEnv->CallVoidMethod(pContext->engine, pContext->onProgressUpdateMethodId,
-        unuseditemID, progress);
-
-    // Check if a task is being performed.
-    // ??? ADD STOPPING MECHANISM
-    ALOGV("videoEditor_processClip Entering processing loop");
-    M4OSA_UInt8 prevReportedProgress = 0;
-    while((result == M4NO_ERROR)
-        &&(pContext->state!=ManualEditState_SAVED)
-        &&(pContext->state!=ManualEditState_STOPPING)) {
-
-            // Perform the next processing step.
-            //ALOGV("LVME_processClip Entering M4xVSS_Step()");
-            result = M4xVSS_Step(pContext->engineContext, &progress);
-
-            if (progress != prevReportedProgress) {
-                prevReportedProgress = progress;
-                // Log the 1 % .. 100 % progress after processing.
-                if (M4OSA_TRUE ==
-                    pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
-                    // For KenBurn clip generation, return 0 to 50
-                    // for Analysis phase and 50 to 100 for Saving phase
-                    progress = progressBase + progress/2;
-                } else {
-                    // For export/transition clips, 0 to 10 for Analysis phase
-                    // and 10 to 100 for Saving phase
-                    if (ManualEditState_INITIALIZED == pContext->state) {
-                        progress = 0.1*progress;
-                    } else {
-                        progress = progressBase + 0.9*progress;
-                    }
-                }
-
-                if (progress > lastProgress)
-                {
-                    // Send a progress notification.
-                    ALOGV("videoEditor_processClip ITEM %d Progress indication %d",
-                        unuseditemID, progress);
-                    pEnv->CallVoidMethod(pContext->engine,
-                        pContext->onProgressUpdateMethodId,
-                        unuseditemID, progress);
-                    lastProgress = progress;
-                }
-            }
-
-            // Check if processing has been completed.
-            if (result == completionResult)
-            {
-                // Set the state to the completions state.
-                pContext->state = completionState;
-                ALOGV("videoEditor_processClip ITEM %d STATE changed to %d",
-                    unuseditemID, pContext->state);
-
-                // Reset progress indication, as we switch to next state
-                lastProgress = 0;
-
-                // Reset error code, as we start a new round of processing
-                result = M4NO_ERROR;
-
-                // Check if we are analyzing input
-                if (pContext->state == ManualEditState_OPENED) {
-                    // File is opened, we must start saving it
-                    ALOGV("videoEditor_processClip Calling M4xVSS_SaveStart()");
-                    result = M4xVSS_SaveStart(pContext->engineContext,
-                        (M4OSA_Char*)pContext->pEditSettings->pOutputFile,
-                        (M4OSA_UInt32)pContext->pEditSettings->uiOutputPathSize);
-                    ALOGV("videoEditor_processClip ITEM %d SaveStart() returned 0x%x",
-                        unuseditemID, (unsigned int) result);
-
-                    // Set the state to saving.
-                    pContext->state  = ManualEditState_SAVING;
-                    completionState  = ManualEditState_SAVED;
-                    completionResult = M4VSS3GPP_WAR_SAVING_DONE;
-                    errorState       = ManualEditState_SAVING_ERROR;
-
-                    // While saving, progress goes from 10 to 100
-                    // except for Kenburn clip which goes from 50 to 100
-                    if (M4OSA_TRUE ==
-                            pContext->pEditSettings->pClipList[0]->xVSS.isPanZoom) {
-                        progressBase = 50;
-                    } else {
-                        progressBase     = 10;
-                    }
-                }
-                // Check if we encoding is ongoing
-                else if (pContext->state == ManualEditState_SAVED) {
-
-                    // Send a progress notification.
-                    progress = 100;
-                    ALOGV("videoEditor_processClip ITEM %d Last progress indication %d",
-                        unuseditemID, progress);
-                    pEnv->CallVoidMethod(pContext->engine,
-                        pContext->onProgressUpdateMethodId,
-                        unuseditemID, progress);
-
-
-                    // Stop the encoding.
-                    ALOGV("videoEditor_processClip Calling M4xVSS_SaveStop()");
-                    result = M4xVSS_SaveStop(pContext->engineContext);
-                    ALOGV("videoEditor_processClip M4xVSS_SaveStop() returned 0x%x", result);
-                }
-                // Other states are unexpected
-                else {
-                    result = M4ERR_STATE;
-                    ALOGE("videoEditor_processClip ITEM %d State ERROR 0x%x",
-                        unuseditemID, (unsigned int) result);
-                }
-            }
-
-            // Check if an error occurred.
-            if (result != M4NO_ERROR)
-            {
-                // Set the state to the error state.
-                pContext->state = errorState;
-
-                // Log the result.
-                ALOGE("videoEditor_processClip ITEM %d Processing ERROR 0x%x",
-                    unuseditemID, (unsigned int) result);
-            }
-    }
-
-    // Return the error result
-    ALOGE("videoEditor_processClip ITEM %d END 0x%x", unuseditemID, (unsigned int) result);
-    return result;
-}
-/*+ PROGRESS CB */
-
-static jint
-videoEditor_generateClip(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jobject                             settings) {
-    bool               loaded   = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-    M4OSA_ERR          result   = M4NO_ERROR;
-
-    ALOGV("videoEditor_generateClip START");
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&loaded, pEnv, thiz);
-
-    Mutex::Autolock autoLock(pContext->mLock);
-
-    // Validate the settings parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&loaded, pEnv,
-                                                (NULL == settings),
-                                                "settings is null");
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&loaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Load the clip settings
-    ALOGV("videoEditor_generateClip Calling videoEditor_loadSettings");
-    videoEditor_loadSettings(pEnv, thiz, settings);
-    ALOGV("videoEditor_generateClip videoEditor_loadSettings returned");
-
-    // Generate the clip
-    ALOGV("videoEditor_generateClip Calling LVME_processClip");
-    result = videoEditor_processClip(pEnv, thiz, 0 /*item id is unused*/);
-    ALOGV("videoEditor_generateClip videoEditor_processClip returned 0x%x", result);
-
-    if (pContext->state != ManualEditState_INITIALIZED) {
-        // Free up memory (whatever the result)
-        videoEditor_unloadSettings(pEnv, thiz);
-    }
-
-    ALOGV("videoEditor_generateClip END 0x%x", (unsigned int) result);
-    return (jint)result;
-}
-
-static void
-videoEditor_loadSettings(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jobject                             settings)
-{
-    bool               needToBeLoaded   = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_loadSettings()");
-
-    // Add a code marker (the condition must always be true).
-    ADD_CODE_MARKER_FUN(NULL != pEnv)
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded,
-                                                                pEnv, thiz);
-
-    // Validate the settings parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
-                                                (NULL == settings),
-                                                "settings is null");
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Check if the context is valid (required because the context is dereferenced).
-    if (needToBeLoaded)
-    {
-        // Make sure that we are in a correct state.
-        videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                             (pContext->state != ManualEditState_INITIALIZED),
-                             "settings already loaded");
-
-        // Retrieve the edit settings.
-        if(pContext->pEditSettings != M4OSA_NULL) {
-            videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-            pContext->pEditSettings = M4OSA_NULL;
-        }
-        videoEditClasses_getEditSettings(&needToBeLoaded, pEnv, settings,
-            &pContext->pEditSettings,true);
-    }
-
-    // Check if the edit settings could be retrieved.
-    if (needToBeLoaded)
-    {
-        // Log the edit settings.
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "inside load settings");
-        VIDEOEDIT_LOG_EDIT_SETTINGS(pContext->pEditSettings);
-    }
-    ALOGV("videoEditor_loadSettings END");
-}
-
-
-
-static void
-videoEditor_unloadSettings(
-                JNIEnv*                             pEnv,
-                jobject                             thiz)
-{
-    bool               needToBeUnLoaded = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-    M4OSA_ERR          result   = M4NO_ERROR;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_unloadSettings()");
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeUnLoaded, pEnv, thiz);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    // Check if the context is valid (required because the context is dereferenced).
-    if (needToBeUnLoaded)
-    {
-        ALOGV("videoEditor_unloadSettings state %d", pContext->state);
-        // Make sure that we are in a correct state.
-        videoEditJava_checkAndThrowIllegalStateException(&needToBeUnLoaded, pEnv,
-                     ((pContext->state != ManualEditState_ANALYZING      ) &&
-                      (pContext->state != ManualEditState_ANALYZING_ERROR) &&
-                      (pContext->state != ManualEditState_OPENED         ) &&
-                      (pContext->state != ManualEditState_SAVING_ERROR   ) &&
-                      (pContext->state != ManualEditState_SAVED          ) &&
-                      (pContext->state != ManualEditState_STOPPING       ) ),
-                     "videoEditor_unloadSettings no load settings in progress");
-    }
-
-    // Check if we are in a correct state.
-    if (needToBeUnLoaded)
-    {
-        // Check if the thread could be stopped.
-        if (needToBeUnLoaded)
-        {
-            // Close the command.
-            ALOGV("videoEditor_unloadSettings Calling M4xVSS_CloseCommand()");
-            result = M4xVSS_CloseCommand(pContext->engineContext);
-            ALOGV("videoEditor_unloadSettings M4xVSS_CloseCommand() returned 0x%x",
-                (unsigned int)result);
-
-            // Check if the command could be closed.
-            videoEditJava_checkAndThrowRuntimeException(&needToBeUnLoaded, pEnv,
-             (M4NO_ERROR != result), result);
-        }
-
-        // Check if the command could be closed.
-        if (needToBeUnLoaded)
-        {
-            // Free the edit settings.
-            //videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-
-            // Reset the thread result.
-            pContext->threadResult = M4NO_ERROR;
-
-            // Reset the thread progress.
-            pContext->threadProgress = 0;
-
-            // Set the state to initialized.
-            pContext->state = ManualEditState_INITIALIZED;
-        }
-    }
-}
-
-static void
-videoEditor_stopEncoding(
-                JNIEnv*                             pEnv,
-                jobject                             thiz)
-{
-    bool               stopped  = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-    M4OSA_ERR          result   = M4NO_ERROR;
-
-    ALOGV("videoEditor_stopEncoding START");
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&stopped, pEnv, thiz);
-
-    // Change state and get Lock
-    // This will ensure the generateClip function exits
-    pContext->state = ManualEditState_STOPPING;
-    Mutex::Autolock autoLock(pContext->mLock);
-
-    // Make sure that the context was set.
-    videoEditJava_checkAndThrowIllegalStateException(&stopped, pEnv,
-                                             (M4OSA_NULL == pContext),
-                                             "not initialized");
-
-    if (stopped) {
-
-        // Check if the command should be closed.
-        if (pContext->state != ManualEditState_INITIALIZED)
-        {
-            // Close the command.
-            ALOGV("videoEditor_stopEncoding Calling M4xVSS_CloseCommand()");
-            result = M4xVSS_CloseCommand(pContext->engineContext);
-            ALOGV("videoEditor_stopEncoding M4xVSS_CloseCommand() returned 0x%x",
-                (unsigned int)result);
-        }
-
-        // Check if the command could be closed.
-        videoEditJava_checkAndThrowRuntimeException(&stopped, pEnv,
-            (M4NO_ERROR != result), result);
-
-        // Free the edit settings.
-        videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-
-        // Set the state to initialized.
-        pContext->state = ManualEditState_INITIALIZED;
-    }
-
-}
-
-static void
-videoEditor_release(
-                JNIEnv*                             pEnv,
-                jobject                             thiz)
-{
-    bool               released = true;
-    ManualEditContext* pContext = M4OSA_NULL;
-    M4OSA_ERR          result   = M4NO_ERROR;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "videoEditor_release()");
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
-    // Get the context.
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&released, pEnv, thiz);
-
-    // If context is not set, return (we consider release already happened)
-    if (pContext == NULL) {
-        ALOGV("videoEditor_release Nothing to do, context is aleady NULL");
-        return;
-    }
-
-
-    // Check if the context is valid (required because the context is dereferenced).
-    if (released)
-    {
-        if (pContext->state != ManualEditState_INITIALIZED)
-        {
-            // Change state and get Lock
-            // This will ensure the generateClip function exits if it is running
-            pContext->state = ManualEditState_STOPPING;
-            Mutex::Autolock autoLock(pContext->mLock);
-        }
-
-        // Reset the context.
-        videoEditClasses_setContext(&released, pEnv, thiz, (void *)M4OSA_NULL);
-
-        // Check if the command should be closed.
-        if (pContext->state != ManualEditState_INITIALIZED)
-        {
-            // Close the command.
-            ALOGV("videoEditor_release Calling M4xVSS_CloseCommand() state =%d",
-                pContext->state);
-            result = M4xVSS_CloseCommand(pContext->engineContext);
-            ALOGV("videoEditor_release M4xVSS_CloseCommand() returned 0x%x",
-                (unsigned int)result);
-
-            // Check if the command could be closed.
-            videoEditJava_checkAndThrowRuntimeException(&released, pEnv,
-                (M4NO_ERROR != result), result);
-        }
-
-        // Cleanup the engine.
-        ALOGV("videoEditor_release Calling M4xVSS_CleanUp()");
-        result = M4xVSS_CleanUp(pContext->engineContext);
-        ALOGV("videoEditor_release M4xVSS_CleanUp() returned 0x%x", (unsigned int)result);
-
-        // Check if the cleanup succeeded.
-        videoEditJava_checkAndThrowRuntimeException(&released, pEnv,
-            (M4NO_ERROR != result), result);
-
-        // Free the edit settings.
-        videoEditClasses_freeEditSettings(&pContext->pEditSettings);
-        pContext->pEditSettings = M4OSA_NULL;
-
-
-        if(pContext->mPreviewController != M4OSA_NULL)
-        {
-            delete pContext->mPreviewController;
-            pContext->mPreviewController = M4OSA_NULL;
-        }
-
-        // Free the mAudioSettings context.
-        if(pContext->mAudioSettings != M4OSA_NULL)
-        {
-            if (pContext->mAudioSettings->pFile != NULL) {
-                free(pContext->mAudioSettings->pFile);
-                pContext->mAudioSettings->pFile = M4OSA_NULL;
-            }
-            if (pContext->mAudioSettings->pPCMFilePath != NULL) {
-                free(pContext->mAudioSettings->pPCMFilePath);
-                pContext->mAudioSettings->pPCMFilePath = M4OSA_NULL;
-            }
-
-            free(pContext->mAudioSettings);
-            pContext->mAudioSettings = M4OSA_NULL;
-        }
-        // Free video Decoders capabilities
-        if (pContext->decoders != M4OSA_NULL) {
-            VideoDecoder *pDecoder = NULL;
-            VideoComponentCapabilities *pComponents = NULL;
-            int32_t decoderNumber = pContext->decoders->decoderNumber;
-            if (pContext->decoders->decoder != NULL &&
-                decoderNumber > 0) {
-                pDecoder = pContext->decoders->decoder;
-                for (int32_t k = 0; k < decoderNumber; k++) {
-                    // free each component
-                    ALOGV("decoder index :%d",k);
-                    if (pDecoder != NULL &&
-                        pDecoder->component != NULL &&
-                        pDecoder->componentNumber > 0) {
-                        ALOGV("component number %d",pDecoder->componentNumber);
-                        int32_t componentNumber =
-                           pDecoder->componentNumber;
-
-                        pComponents = pDecoder->component;
-                        for (int32_t i = 0; i< componentNumber; i++) {
-                            ALOGV("component index :%d",i);
-                            if (pComponents != NULL &&
-                                pComponents->profileLevel != NULL) {
-                                free(pComponents->profileLevel);
-                                pComponents->profileLevel = NULL;
-                            }
-                            pComponents++;
-                        }
-                        free(pDecoder->component);
-                        pDecoder->component = NULL;
-                    }
-
-                    pDecoder++;
-                }
-                free(pContext->decoders->decoder);
-                pContext->decoders->decoder = NULL;
-            }
-            free(pContext->decoders);
-            pContext->decoders = NULL;
-        }
-
-        videoEditor_freeContext(pEnv, &pContext);
-    }
-}
-
-static int
-videoEditor_registerManualEditMethods(
-                JNIEnv*                             pEnv)
-{
-    int result = -1;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-     "videoEditor_registerManualEditMethods()");
-
-    // Look up the engine class
-    jclass engineClazz = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
-
-    // Clear any resulting exceptions.
-    pEnv->ExceptionClear();
-
-    // Check if the engine class was found.
-    if (NULL != engineClazz)
-    {
-        // Register all the methods.
-        if (pEnv->RegisterNatives(engineClazz, gManualEditMethods,
-                sizeof(gManualEditMethods) / sizeof(gManualEditMethods[0])) == JNI_OK)
-        {
-            // Success.
-            result = 0;
-        }
-    }
-
-    // Return the result.
-    return(result);
-}
-
-/*******Audio Graph*******/
-
-static M4OSA_UInt32 getDecibelSound(M4OSA_UInt32 value)
-{
-    int dbSound = 1;
-
-    if (value == 0) return 0;
-
-    if (value > 0x4000 && value <= 0x8000) // 32768
-        dbSound = 90;
-    else if (value > 0x2000 && value <= 0x4000) // 16384
-        dbSound = 84;
-    else if (value > 0x1000 && value <= 0x2000) // 8192
-        dbSound = 78;
-    else if (value > 0x0800 && value <= 0x1000) // 4028
-        dbSound = 72;
-    else if (value > 0x0400 && value <= 0x0800) // 2048
-        dbSound = 66;
-    else if (value > 0x0200 && value <= 0x0400) // 1024
-        dbSound = 60;
-    else if (value > 0x0100 && value <= 0x0200) // 512
-        dbSound = 54;
-    else if (value > 0x0080 && value <= 0x0100) // 256
-        dbSound = 48;
-    else if (value > 0x0040 && value <= 0x0080) // 128
-        dbSound = 42;
-    else if (value > 0x0020 && value <= 0x0040) // 64
-        dbSound = 36;
-    else if (value > 0x0010 && value <= 0x0020) // 32
-        dbSound = 30;
-    else if (value > 0x0008 && value <= 0x0010) //16
-        dbSound = 24;
-    else if (value > 0x0007 && value <= 0x0008) //8
-        dbSound = 24;
-    else if (value > 0x0003 && value <= 0x0007) // 4
-        dbSound = 18;
-    else if (value > 0x0001 && value <= 0x0003) //2
-        dbSound = 12;
-    else if (value > 0x000 && value == 0x0001) // 1
-        dbSound = 6;
-    else
-        dbSound = 0;
-
-    return dbSound;
-}
-
-typedef struct
-{
-    M4OSA_UInt8      *m_dataAddress;
-    M4OSA_UInt32    m_bufferSize;
-} M4AM_Buffer;
-
-
-M4OSA_UInt8 logLookUp[256] = {
-0,120,137,146,154,159,163,167,171,173,176,178,181,182,184,186,188,189,190,192,193,
-194,195,196,198,199,199,200,201,202,203,204,205,205,206,207,207,208,209,209,210,
-211,211,212,212,213,213,214,215,215,216,216,216,217,217,218,218,219,219,220,220,
-220,221,221,222,222,222,223,223,223,224,224,224,225,225,225,226,226,226,227,227,
-227,228,228,228,229,229,229,229,230,230,230,230,231,231,231,232,232,232,232,233,
-233,233,233,233,234,234,234,234,235,235,235,235,236,236,236,236,236,237,237,237,
-237,237,238,238,238,238,238,239,239,239,239,239,240,240,240,240,240,240,241,241,
-241,241,241,241,242,242,242,242,242,242,243,243,243,243,243,243,244,244,244,244,
-244,244,245,245,245,245,245,245,245,246,246,246,246,246,246,246,247,247,247,247,
-247,247,247,247,248,248,248,248,248,248,248,249,249,249,249,249,249,249,249,250,
-250,250,250,250,250,250,250,250,251,251,251,251,251,251,251,251,252,252,252,252,
-252,252,252,252,252,253,253,253,253,253,253,253,253,253,253,254,254,254,254,254,
-254,254,254,254,255,255,255,255,255,255,255,255,255,255,255};
-
-M4OSA_ERR M4MA_generateAudioGraphFile(JNIEnv* pEnv, M4OSA_Char* pInputFileURL,
-                     M4OSA_Char* pOutFileURL,
-                     M4OSA_UInt32 samplesPerValue,
-                     M4OSA_UInt32 channels,
-                     M4OSA_UInt32 frameDuration,
-                     ManualEditContext* pContext)
-{
-    M4OSA_ERR           err;
-    M4OSA_Context       outFileHandle = M4OSA_NULL;
-    M4OSA_Context       inputFileHandle = M4OSA_NULL;
-    M4AM_Buffer         bufferIn = {0, 0};
-    M4OSA_UInt32        peakVolumeDbValue = 0;
-    M4OSA_UInt32        samplesCountInBytes= 0 , numBytesToRead = 0, index = 0;
-    M4OSA_UInt32        writeCount = 0, samplesCountBigEndian = 0, volumeValuesCount = 0;
-    M4OSA_Int32         seekPos = 0;
-    M4OSA_UInt32        fileSize = 0;
-    M4OSA_UInt32        totalBytesRead = 0;
-    M4OSA_UInt32        prevProgress = 0;
-    bool                threadStarted = true;
-
-    int dbValue = 0;
-    M4OSA_Int16 *ptr16 ;
-
-    jclass engineClass = pEnv->FindClass(MANUAL_EDIT_ENGINE_CLASS_NAME);
-    videoEditJava_checkAndThrowIllegalStateException(&threadStarted, pEnv,
-                                             (M4OSA_NULL == engineClass),
-                                             "not initialized");
-
-    /* register the call back function pointer */
-    pContext->onAudioGraphProgressUpdateMethodId =
-            pEnv->GetMethodID(engineClass, "onAudioGraphExtractProgressUpdate", "(IZ)V");
-
-
-    /* ENTER */
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "ENTER - M4MA_generateAudioGraphFile");
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "Audio Graph samplesPerValue %d channels %d", samplesPerValue, channels);
-
-    /******************************************************************************
-        OPEN INPUT AND OUTPUT FILES
-    *******************************************************************************/
-    err = M4OSA_fileReadOpen (&inputFileHandle, pInputFileURL, M4OSA_kFileRead);
-    if (inputFileHandle == M4OSA_NULL) {
-        VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "M4MA_generateAudioGraphFile: Cannot open input file 0x%lx", err);
-        return err;
-    }
-
-    /* get the file size for progress */
-    err = M4OSA_fileReadGetOption(inputFileHandle, M4OSA_kFileReadGetFileSize,
-                                (M4OSA_Void**)&fileSize);
-    if ( err != M4NO_ERROR) {
-        //LVMEL_LOG_ERROR("M4MA_generateAudioGraphFile : File write failed \n");
-        jniThrowException(pEnv, "java/lang/IOException", "file size get option failed");
-        //return -1;
-    }
-
-    err = M4OSA_fileWriteOpen (&outFileHandle,(M4OSA_Char*) pOutFileURL,
-        M4OSA_kFileCreate | M4OSA_kFileWrite);
-    if (outFileHandle == M4OSA_NULL) {
-        if (inputFileHandle != NULL)
-        {
-            M4OSA_fileReadClose(inputFileHandle);
-        }
-        return err;
-    }
-
-    /******************************************************************************
-        PROCESS THE SAMPLES
-    *******************************************************************************/
-    samplesCountInBytes = (samplesPerValue * sizeof(M4OSA_UInt16) * channels);
-
-    bufferIn.m_dataAddress = (M4OSA_UInt8*)M4OSA_32bitAlignedMalloc(samplesCountInBytes*sizeof(M4OSA_UInt16), 0,
-    (M4OSA_Char*)"AudioGraph" );
-    if ( bufferIn.m_dataAddress != M4OSA_NULL) {
-        bufferIn.m_bufferSize = samplesCountInBytes*sizeof(M4OSA_UInt16);
-    } else {
-        VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "M4MA_generateAudioGraphFile: Malloc failed for bufferIn.m_dataAddress 0x%lx",
-            M4ERR_ALLOC);
-        return M4ERR_ALLOC;
-    }
-    /* sample to be converted to BIG endian ; store the frame duration */
-    samplesCountBigEndian = ((frameDuration>>24)&0xff) | // move byte 3 to byte 0
-                    ((frameDuration<<8)&0xff0000) | // move byte 1 to byte 2
-                    ((frameDuration>>8)&0xff00) | // move byte 2 to byte 1
-                    ((frameDuration<<24)&0xff000000); // byte 0 to byte 3
-
-    /* write the samples per value supplied to out file */
-    err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian,
-        sizeof(M4OSA_UInt32) );
-    if (err != M4NO_ERROR) {
-        jniThrowException(pEnv, "java/lang/IOException", "file write failed");
-    }
-
-
-    /* write UIn32 value 0 for no of values as place holder */
-    samplesCountBigEndian = 0; /* reusing local var */
-    err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&samplesCountBigEndian,
-        sizeof(M4OSA_UInt32) );
-    if (err != M4NO_ERROR) {
-        jniThrowException(pEnv, "java/lang/IOException", "file write failed");
-    }
-
-    /* loop until EOF */
-    do
-    {
-        memset((void *)bufferIn.m_dataAddress,0,bufferIn.m_bufferSize);
-
-        numBytesToRead = samplesCountInBytes;
-
-        err =  M4OSA_fileReadData(  inputFileHandle,
-                                    (M4OSA_MemAddr8)bufferIn.m_dataAddress,
-                                    &numBytesToRead );
-
-        if (err != M4NO_ERROR) {
-            // if out value of bytes-read is 0, break
-            if ( numBytesToRead == 0) {
-                VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "numBytesToRead 0x%lx",
-                numBytesToRead);
-                break; /* stop if file is empty or EOF */
-            }
-        }
-
-        ptr16 = (M4OSA_Int16*)bufferIn.m_dataAddress;
-
-        peakVolumeDbValue = 0;
-        index = 0;
-
-        // loop through half the lenght frame bytes read 'cause its 16 bits samples
-        while (index < (numBytesToRead / 2)) {
-            /* absolute values of 16 bit sample */
-            if (ptr16[index] < 0) {
-                ptr16[index] = -(ptr16[index]);
-            }
-            peakVolumeDbValue = (peakVolumeDbValue > (M4OSA_UInt32)ptr16[index] ?\
-             peakVolumeDbValue : (M4OSA_UInt32)ptr16[index]);
-            index++;
-        }
-
-        // move 7 bits , ignore sign bit
-        dbValue = (peakVolumeDbValue >> 7);
-        dbValue = logLookUp[(M4OSA_UInt8)dbValue];
-
-        err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&dbValue, sizeof(M4OSA_UInt8) );
-        if (err != M4NO_ERROR) {
-            VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-             "M4MA_generateAudioGraphFile : File write failed");
-            break;
-        }
-
-        volumeValuesCount ++;
-        totalBytesRead += numBytesToRead;
-
-        if ((((totalBytesRead*100)/fileSize)) != prevProgress) {
-            if ( (pContext->threadProgress != prevProgress) && (prevProgress != 0 )) {
-                //pContext->threadProgress = prevProgress;
-                //onWveformProgressUpdateMethodId(prevProgress, 0);
-                //LVME_callAudioGraphOnProgressUpdate(pContext, 0, prevProgress);
-            pEnv->CallVoidMethod(pContext->engine,
-                                 pContext->onAudioGraphProgressUpdateMethodId,
-                                 prevProgress, 0);
-            VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "pContext->threadProgress %d",
-                             prevProgress);
-            }
-        }
-        prevProgress = (((totalBytesRead*100)/fileSize));
-
-    } while (numBytesToRead != 0);
-
-    VIDEOEDIT_LOG_ERROR(ANDROID_LOG_INFO, "VIDEO_EDITOR", "loop 0x%lx", volumeValuesCount);
-
-    /* if some error occured in fwrite */
-    if (numBytesToRead != 0) {
-        //err = -1;
-        jniThrowException(pEnv, "java/lang/IOException", "numBytesToRead != 0 ; file write failed");
-    }
-
-    /* write the count in place holder after seek */
-    seekPos = sizeof(M4OSA_UInt32);
-    err = M4OSA_fileWriteSeek(outFileHandle, M4OSA_kFileSeekBeginning,
-            &seekPos /* after samples per value */);
-    if ( err != M4NO_ERROR) {
-        jniThrowException(pEnv, "java/lang/IOException", "file seek failed");
-    } else {
-        volumeValuesCount = ((volumeValuesCount>>24)&0xff) | // move byte 3 to byte 0
-                    ((volumeValuesCount<<8)&0xff0000) | // move byte 1 to byte 2
-                    ((volumeValuesCount>>8)&0xff00) |  // move byte 2 to byte 1
-                    ((volumeValuesCount<<24)&0xff000000); // byte 0 to byte 3
-
-        err = M4OSA_fileWriteData (outFileHandle, (M4OSA_MemAddr8)&volumeValuesCount,
-                                    sizeof(M4OSA_UInt32) );
-        if ( err != M4NO_ERROR) {
-            jniThrowException(pEnv, "java/lang/IOException", "file write failed");
-        }
-    }
-
-    /******************************************************************************
-    CLOSE AND FREE ALLOCATIONS
-    *******************************************************************************/
-    free(bufferIn.m_dataAddress);
-    M4OSA_fileReadClose(inputFileHandle);
-    M4OSA_fileWriteClose(outFileHandle);
-    /* final finish callback */
-    pEnv->CallVoidMethod(pContext->engine, pContext->onAudioGraphProgressUpdateMethodId, 100, 0);
-
-    /* EXIT */
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR", "EXIT - M4MA_generateAudioGraphFile");
-
-    return err;
-}
-
-static jint videoEditor_generateAudioWaveFormSync (JNIEnv*  pEnv, jobject thiz,
-                                                  jstring pcmfilePath,
-                                                  jstring outGraphfilePath,
-                                                  jint frameDuration, jint channels,
-                                                  jint samplesCount)
-{
-    M4OSA_ERR result = M4NO_ERROR;
-    ManualEditContext* pContext = M4OSA_NULL;
-    bool needToBeLoaded = true;
-    const char *pPCMFilePath, *pStringOutAudioGraphFile;
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-        "videoEditor_generateAudioWaveFormSync() ");
-
-    /* Get the context. */
-    pContext = (ManualEditContext*)videoEditClasses_getContext(&needToBeLoaded, pEnv, thiz);
-    if (pContext == M4OSA_NULL) {
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-            "videoEditor_generateAudioWaveFormSync() - pContext is NULL ");
-    }
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-        "videoEditor_generateAudioWaveFormSync Retrieving pStringOutAudioGraphFile");
-
-    pPCMFilePath = pEnv->GetStringUTFChars(pcmfilePath, NULL);
-    if (pPCMFilePath == M4OSA_NULL) {
-        jniThrowException(pEnv, "java/lang/RuntimeException",
-            "Input string PCMFilePath is null");
-        result = M4ERR_PARAMETER;
-        goto out;
-    }
-
-    pStringOutAudioGraphFile = pEnv->GetStringUTFChars(outGraphfilePath, NULL);
-    if (pStringOutAudioGraphFile == M4OSA_NULL) {
-        jniThrowException(pEnv, "java/lang/RuntimeException",
-            "Input string outGraphfilePath is null");
-        result = M4ERR_PARAMETER;
-        goto out2;
-    }
-
-    VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-        "videoEditor_generateAudioWaveFormSync Generate the waveform data %s %d %d %d",
-        pStringOutAudioGraphFile, frameDuration, channels, samplesCount);
-
-    /* Generate the waveform */
-    result = M4MA_generateAudioGraphFile(pEnv, (M4OSA_Char*) pPCMFilePath,
-        (M4OSA_Char*) pStringOutAudioGraphFile,
-        (M4OSA_UInt32) samplesCount,
-        (M4OSA_UInt32) channels,
-        (M4OSA_UInt32)frameDuration,
-        pContext);
-
-    pEnv->ReleaseStringUTFChars(outGraphfilePath, pStringOutAudioGraphFile);
-
-out2:
-    if (pPCMFilePath != NULL) {
-        pEnv->ReleaseStringUTFChars(pcmfilePath, pPCMFilePath);
-    }
-
-out:
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR",
-        "videoEditor_generateAudioWaveFormSync pContext->bSkipState ");
-
-    return (jint)result;
-}
-
-/******** End Audio Graph *******/
-jint JNI_OnLoad(
-                JavaVM*                             pVm,
-                void*                               pReserved)
-{
-    void* pEnv         = NULL;
-    bool  needToBeInitialized = true;
-    jint  result      = -1;
-
-    VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR", "JNI_OnLoad()");
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pVm)
-
-    // Check the JNI version.
-    if (pVm->GetEnv(&pEnv, JNI_VERSION_1_4) == JNI_OK)
-    {
-        // Add a code marker (the condition must always be true).
-        ADD_CODE_MARKER_FUN(NULL != pEnv)
-
-        // Register the manual edit JNI methods.
-        if (videoEditor_registerManualEditMethods((JNIEnv*)pEnv) == 0)
-        {
-            // Initialize the classes.
-            videoEditClasses_init(&needToBeInitialized, (JNIEnv*)pEnv);
-            if (needToBeInitialized)
-            {
-                // Success, return valid version number.
-                result = JNI_VERSION_1_4;
-            }
-        }
-    }
-
-    // Return the result.
-    return(result);
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorOsal.cpp b/media/jni/mediaeditor/VideoEditorOsal.cpp
deleted file mode 100644
index c12b1f5..0000000
--- a/media/jni/mediaeditor/VideoEditorOsal.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorOsal"
-
-#include <VideoEditorJava.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4xVSS_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4VSS3GPP_API.h>
-#include <M4DECODER_Common.h>
-};
-
-
-#define VIDEOEDIT_OSAL_RESULT_STRING_MAX     (32)
-
-#define VIDEOEDIT_OSAL_RESULT_INIT(m_result) { m_result, #m_result }
-
-
-typedef struct
-{
-    M4OSA_ERR   result;
-    const char* pName;
-} VideoEdit_Osal_Result;
-
-static const VideoEdit_Osal_Result gkRESULTS[] =
-{
-    // M4OSA_Clock.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TIMESCALE_TOO_BIG                                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_CLOCK_BAD_REF_YEAR                               ),
-
-    // M4OSA_Error.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4NO_ERROR                                             ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_PARAMETER                                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_STATE                                            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_ALLOC                                            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_CONTEXT                                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_CONTEXT_FAILED                                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_STREAM_ID                                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_BAD_OPTION_ID                                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_WRITE_ONLY                                       ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READ_ONLY                                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_NOT_IMPLEMENTED                                  ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_UNSUPPORTED_MEDIA_TYPE                           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_DATA_YET                                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_MORE_STREAM                                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_INVALID_TIME                                     ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_NO_MORE_AU                                       ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TIME_OUT                                         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_BUFFER_FULL                                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_REDIRECT                                         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_TOO_MUCH_STREAMS                                 ),
-
-    // M4OSA_FileCommon.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_NOT_FOUND                                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_LOCKED                                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_BAD_MODE_ACCESS                             ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_FILE_INVALID_POSITION                            ),
-
-    // M4OSA_Thread.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_THREAD_NOT_STARTED                               ),
-
-    // M4xVSS_API.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_ANALYZING_DONE                           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_PREVIEW_READY                            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_SAVING_DONE                              ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_TRANSCODING_NECESSARY                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_OUTPUTFILESIZE_EXCEED                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_JPG_TOO_BIG                              ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4xVSSWAR_BUFFER_OUT_TOO_SMALL                         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4xVSSERR_NO_MORE_SPACE                                ),
-
-    // M4VSS3GPP_ErrorCodes.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_FILE_TYPE                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_EFFECT_KIND                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_EFFECT_TYPE                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_AUDIO_EFFECT_TYPE                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_TRANSITION_TYPE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_AUDIO_TRANSITION_TYPE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_VIDEO_ENCODING_FRAME_RATE        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EXTERNAL_EFFECT_NULL                     ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EXTERNAL_TRANSITION_NULL                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_DURATION           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGIN_CUT_LARGER_THAN_END_CUT            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_OVERLAPPING_TRANSITIONS                  ),
-#ifdef M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ANALYSIS_DATA_SIZE_TOO_SMALL             ),
-#endif
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_3GPP_FILE                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_INPUT_VIDEO_FORMAT           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_INPUT_AUDIO_FORMAT           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AMR_EDITING_UNSUPPORTED                  ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_VIDEO_AU_TOO_LARGE                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_AU_TOO_LARGE                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AU                 ),
-#ifdef M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_AUDIO_CORRUPTED_AMR_AU             ),
-#endif
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ENCODER_ACCES_UNIT_ERROR                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_VIDEO_FORMAT         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_H263_PROFILE         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_PROFILE        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_MPEG4_RVLC           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_UNSUPPORTED_AUDIO_FORMAT         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_STREAM_IN_FILE      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_EDITING_NO_SUPPORTED_VIDEO_STREAM_IN_FILE),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_VERSION            ),
-#ifdef M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INVALID_CLIP_ANALYSIS_PLATFORM           ),
-#endif
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FORMAT                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_FRAME_SIZE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_TIME_SCALE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INCOMPATIBLE_VIDEO_DATA_PARTITIONING     ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_MP3_ASSEMBLY                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_STREAM_TYPE           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_NB_OF_CHANNELS        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_WAR_INCOMPATIBLE_AUDIO_SAMPLING_FREQUENCY    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_STREAM_IN_FILE              ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ADDVOLUME_EQUALS_ZERO                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ADDCTS_HIGHER_THAN_VIDEO_DURATION        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNDEFINED_AUDIO_TRACK_FILE_FORMAT        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_UNSUPPORTED_ADDED_AUDIO_STREAM           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_MIXING_UNSUPPORTED                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AUDIO_TRACK     ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_CANNOT_BE_MIXED                    ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INPUT_CLIP_IS_NOT_A_3GPP                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_BEGINLOOP_HIGHER_ENDLOOP                 ),
-#ifdef M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_MIXING_MP3_UNSUPPORTED             ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_AAC             ),
-#endif
-#ifdef M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_ONLY_AMRNB_INPUT_CAN_BE_MIXED            ),
-#endif
-#ifdef M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_FEATURE_UNSUPPORTED_WITH_EVRC            ),
-#endif
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_H263_PROFILE_NOT_SUPPORTED               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_NO_SUPPORTED_VIDEO_STREAM_IN_FILE        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_INTERNAL_STATE                           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_LUMA_FILTER_ERROR                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_TRANSITION_FILTER_ERROR                  ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODER_INIT_FAILED                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_AUDIO_DECODED_PCM_SIZE_ISSUE             ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4VSS3GPP_ERR_OUTPUT_FILE_TYPE_ERROR                   ),
-
-    // M4MCS_ErrorCodes.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_WAR_TRANSCODING_DONE                             ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_WAR_MEDIATYPE_NOT_SUPPORTED                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INPUT_FILE_CONTAINS_NO_SUPPORTED_STREAM      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_INPUT_FILE                           ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FORMAT                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_SIZE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_VIDEO_FRAME_RATE            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_UNDEFINED_OUTPUT_AUDIO_FORMAT                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_VIDEO_FRAME_SIZE_FOR_H263            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_VIDEO_FRAME_RATE_FOR_H263            ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_DURATION_IS_NULL                             ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_H263_FORBIDDEN_IN_MP4_FILE                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_H263_PROFILE_NOT_SUPPORTED                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_INVALID_AAC_SAMPLING_FREQUENCY               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIO_CONVERSION_FAILED                      ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_BEGIN_CUT_LARGER_THAN_DURATION               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_BEGIN_CUT_EQUALS_END_CUT                     ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_END_CUT_SMALLER_THAN_BEGIN_CUT               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_MAXFILESIZE_TOO_SMALL                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_VIDEOBITRATE_TOO_LOW                         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_LOW                         ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_VIDEOBITRATE_TOO_HIGH                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_AUDIOBITRATE_TOO_HIGH                        ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_OUTPUT_FILE_SIZE_TOO_SMALL                   ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_NOMORE_SPACE                                 ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4MCS_ERR_FILE_DRM_PROTECTED                           ),
-
-    // M4READER_Common.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_READER_UNKNOWN_STREAM_TYPE                       ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_READER_NO_METADATA                               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_READER_INFORMATION_NOT_PRESENT                   ),
-
-    // M4WRITER_Common.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_WRITER_STOP_REQ                                  ),
-    // M4DECODER_Common.h
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_VIDEORENDERER_NO_NEW_FRAME                       ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4WAR_DEBLOCKING_FILTER_NOT_IMPLEMENTED                ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_DECODER_H263_PROFILE_NOT_SUPPORTED               ),
-    VIDEOEDIT_OSAL_RESULT_INIT(M4ERR_DECODER_H263_NOT_BASELINE                        )
-};
-
-static const int gkRESULTS_COUNT = (sizeof(gkRESULTS) / sizeof(VideoEdit_Osal_Result));
-
-#ifdef OSAL_MEM_LEAK_DEBUG
-static int gAllocatedBlockCount = 0;
-#endif
-
-const char*
-videoEditOsal_getResultString(
-                M4OSA_ERR                           result)
-{
-    static char string[VIDEOEDIT_OSAL_RESULT_STRING_MAX] = "";
-    const char* pString                         = M4OSA_NULL;
-    int         index                           = 0;
-
-    // Loop over the list with constants.
-    for (index = 0;
-         ((M4OSA_NULL == pString) && (index < gkRESULTS_COUNT));
-         index++)
-    {
-        // Check if the specified result matches.
-        if (result == gkRESULTS[index].result)
-        {
-            // Set the description.
-            pString = gkRESULTS[index].pName;
-        }
-    }
-
-    // Check if no result was found.
-    if (M4OSA_NULL == pString)
-    {
-        // Set the description to a default value.
-        M4OSA_chrSPrintf((M4OSA_Char *)string, sizeof(string) - 1,
-         (M4OSA_Char*)"<unknown(0x%08X)>", result);
-        pString = string;
-    }
-
-    // Return the result.
-    return(pString);
-}
-
-void *
-videoEditOsal_alloc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                size_t                              size,
-                const char*                         pDescription)
-{
-    void *pData = M4OSA_NULL;
-
-    // Check if the previous action succeeded.
-    if (*pResult)
-    {
-        // Allocate memory for the settings.
-        pData = (M4VSS3GPP_EditSettings*)M4OSA_32bitAlignedMalloc(size, 0, (M4OSA_Char*)pDescription);
-        if (M4OSA_NULL != pData)
-        {
-            // Reset the allocated memory.
-            memset((void *)pData, 0,size);
-#ifdef OSAL_MEM_LEAK_DEBUG
-            // Update the allocated block count.
-            gAllocatedBlockCount++;
-#endif
-        }
-        else
-        {
-            // Reset the result flag.
-            (*pResult) = false;
-
-            // Log the error.
-            VIDEOEDIT_LOG_ERROR(ANDROID_LOG_ERROR, "VIDEO_EDITOR_OSAL", "videoEditOsal_alloc,\
-             error: unable to allocate memory for %s", pDescription);
-
-            // Throw an exception.
-            jniThrowException(pEnv, "java/lang/OutOfMemoryError", "unable to allocate memory");
-        }
-    }
-
-    // Return the allocated memory.
-    return(pData);
-}
-
-void
-videoEditOsal_free(
-                void*                               pData)
-{
-    // Check if memory was allocated.
-    if (M4OSA_NULL != pData)
-    {
-        VIDEOEDIT_LOG_FUNCTION(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "videoEditOsal_free()");
-
-        // Log the API call.
-        VIDEOEDIT_LOG_API(ANDROID_LOG_INFO, "VIDEO_EDITOR_OSAL", "free");
-
-        // Free the memory.
-        free(pData);
-#ifdef OSAL_MEM_LEAK_DEBUG
-        // Update the allocated block count.
-        gAllocatedBlockCount--;
-
-        // Log the number of allocated blocks.
-        VIDEOEDIT_LOG_ALLOCATION(ANDROID_LOG_ERROR, "VIDEO_EDITOR_OSAL", "allocated, %d blocks",\
-         gAllocatedBlockCount);
-#endif
-    }
-}
-
-
-void
-videoEditOsal_getFilePointers ( M4OSA_FileReadPointer *pOsaFileReadPtr,
-                                M4OSA_FileWriterPointer *pOsaFileWritePtr)
-{
-    if (pOsaFileReadPtr != M4OSA_NULL)
-    {
-        // Initialize the filereader function pointers.
-        pOsaFileReadPtr->openRead  = M4OSA_fileReadOpen;
-        pOsaFileReadPtr->readData  = M4OSA_fileReadData;
-        pOsaFileReadPtr->seek      = M4OSA_fileReadSeek;
-        pOsaFileReadPtr->closeRead = M4OSA_fileReadClose;
-        pOsaFileReadPtr->setOption = M4OSA_fileReadSetOption;
-        pOsaFileReadPtr->getOption = M4OSA_fileReadGetOption;
-    }
-
-    if (pOsaFileWritePtr != M4OSA_NULL)
-    {
-        // Initialize the filewriter function pointers.
-        pOsaFileWritePtr->openWrite  = M4OSA_fileWriteOpen;
-        pOsaFileWritePtr->writeData  = M4OSA_fileWriteData;
-        pOsaFileWritePtr->seek       = M4OSA_fileWriteSeek;
-        pOsaFileWritePtr->Flush      = M4OSA_fileWriteFlush;
-        pOsaFileWritePtr->closeWrite = M4OSA_fileWriteClose;
-        pOsaFileWritePtr->setOption  = M4OSA_fileWriteSetOption;
-        pOsaFileWritePtr->getOption  = M4OSA_fileWriteGetOption;
-    }
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorOsal.h b/media/jni/mediaeditor/VideoEditorOsal.h
deleted file mode 100644
index 7a6f5ea..0000000
--- a/media/jni/mediaeditor/VideoEditorOsal.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEO_EDITOR_OSAL_H
-#define VIDEO_EDITOR_OSAL_H
-
-#include <jni.h>
-#include <JNIHelp.h>
-
-extern "C" {
-#include <M4OSA_Error.h>
-#include <M4OSA_Thread.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-};
-
-const char*
-videoEditOsal_getResultString(
-                M4OSA_ERR                           result);
-
-void*
-videoEditOsal_alloc(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                size_t                              size,
-                const char*                         pDescription);
-
-void
-videoEditOsal_free(
-                void*                               pData);
-
-void
-videoEditOsal_startThread(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                int                                 stackSize,
-                M4OSA_ThreadDoIt                    callback,
-                M4OSA_Context*                      pContext,
-                void*                               pParam);
-
-void
-videoEditOsal_stopThread(
-                bool*                               pResult,
-                JNIEnv*                             pEnv,
-                M4OSA_Context*                      pContext);
-
-void
-videoEditOsal_getFilePointers ( M4OSA_FileReadPointer *pOsaFileReadPtr,
-                                M4OSA_FileWriterPointer *pOsaFileWritePtr);
-
-#endif // VIDEO_EDITOR_OSAL_H
-
diff --git a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp b/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
deleted file mode 100644
index 2f8e357..0000000
--- a/media/jni/mediaeditor/VideoEditorPropertiesMain.cpp
+++ /dev/null
@@ -1,543 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#define LOG_TAG "VideoEditorPropertiesMain"
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <utils/Log.h>
-#include <utils/threads.h>
-#include <VideoEditorClasses.h>
-#include <VideoEditorJava.h>
-#include <VideoEditorOsal.h>
-#include <VideoEditorLogging.h>
-#include <VideoEditorOsal.h>
-#include <marker.h>
-
-extern "C" {
-#include <M4OSA_Clock.h>
-#include <M4OSA_CharStar.h>
-#include <M4OSA_Error.h>
-#include <M4OSA_FileCommon.h>
-#include <M4OSA_FileReader.h>
-#include <M4OSA_FileWriter.h>
-#include <M4OSA_Memory.h>
-#include <M4OSA_Thread.h>
-#include <M4VSS3GPP_API.h>
-#include <M4VSS3GPP_ErrorCodes.h>
-#include <M4MCS_API.h>
-#include <M4MCS_ErrorCodes.h>
-#include <M4READER_Common.h>
-#include <M4WRITER_common.h>
-#include <M4DECODER_Common.h>
-#include <M4AD_Common.h>
-};
-
-extern "C" M4OSA_ERR M4MCS_open_normalMode(
-                M4MCS_Context                       pContext,
-                M4OSA_Void*                         pFileIn,
-                M4VIDEOEDITING_FileType             InputFileType,
-                M4OSA_Void*                         pFileOut,
-                M4OSA_Void*                         pTempFile);
-
-jobject videoEditProp_getProperties(
-                JNIEnv*                             pEnv,
-                jobject                             thiz,
-                jstring                             file);
-
-static void
-getFileAndMediaTypeFromExtension (
-                M4OSA_Char* pExtension,
-                VideoEditClasses_FileType   *pFileType,
-                M4VIDEOEDITING_FileType       *pClipType);
-
-static M4OSA_ERR
-getClipProperties(  JNIEnv*                         pEnv,
-                    jobject                         thiz,
-                    M4OSA_Char*                     pFile,
-                    M4VIDEOEDITING_FileType         clipType,
-                    M4VIDEOEDITING_ClipProperties*  pClipProperties);
-
-M4OSA_UInt32
-VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
-                     M4OSA_Char* pStrIn2,
-                     M4OSA_Int32* pCmpResult);
-
-jobject videoEditProp_getProperties(
-        JNIEnv* pEnv,
-        jobject thiz,
-        jstring file)
-{
-    bool                           gotten          = true;
-    M4OSA_Char*                    pFile           = M4OSA_NULL;
-    M4OSA_Char*                    pExtension      = M4OSA_NULL;
-    M4OSA_UInt32                   index           = 0;
-    M4OSA_Int32                    cmpResult       = 0;
-    VideoEditPropClass_Properties* pProperties     = M4OSA_NULL;
-    M4VIDEOEDITING_ClipProperties* pClipProperties = M4OSA_NULL;
-    M4OSA_ERR                      result          = M4NO_ERROR;
-    M4MCS_Context                  context         = M4OSA_NULL;
-    M4OSA_FilePosition             size            = 0;
-    M4OSA_UInt32                   width           = 0;
-    M4OSA_UInt32                   height          = 0;
-    jobject                        properties      = NULL;
-    M4OSA_Context                  pOMXContext     = M4OSA_NULL;
-    M4DECODER_VideoInterface*      pOMXVidDecoderInterface = M4OSA_NULL;
-    M4AD_Interface*                pOMXAudDecoderInterface = M4OSA_NULL;
-
-    bool  initialized = true;
-    VideoEditClasses_FileType fileType = VideoEditClasses_kFileType_Unsupported;
-    M4VIDEOEDITING_FileType clipType = M4VIDEOEDITING_kFileType_Unsupported;
-
-    VIDEOEDIT_LOG_API(
-            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
-            "videoEditProp_getProperties()");
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
-    // Initialize the classes.
-    videoEditPropClass_init(&initialized, (JNIEnv*)pEnv);
-
-    // Validate the tempPath parameter.
-    videoEditJava_checkAndThrowIllegalArgumentException(
-            &gotten, pEnv, (NULL == file), "file is null");
-
-    // Get the file path.
-    pFile = (M4OSA_Char *)videoEditJava_getString(
-            &gotten, pEnv, file, NULL, M4OSA_NULL);
-
-    result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
-
-    if(M4NO_ERROR != result) {
-        // Free the file path.
-        videoEditOsal_free(pFile);
-        pFile = M4OSA_NULL;
-    }
-
-    videoEditJava_checkAndThrowIllegalArgumentException(&gotten, pEnv,
-        (M4NO_ERROR != result), "file not found");
-
-    // Close the file and free the file context
-    if (context != NULL) {
-        result = M4OSA_fileReadClose(context);
-        context = M4OSA_NULL;
-    }
-
-    // Return if Error
-    if (M4NO_ERROR != result) {
-        return (properties); // NULL
-    }
-
-    // Check if the file path is valid.
-    if (gotten)
-    {
-        // Retrieve the extension.
-        pExtension = (M4OSA_Char *)strrchr((const char *)pFile, (int)'.');
-        if (M4OSA_NULL != pExtension)
-        {
-            // Skip the dot.
-            pExtension++;
-
-            // Get the file type and Media type from extension
-            getFileAndMediaTypeFromExtension(
-                    pExtension ,&fileType, &clipType);
-        }
-    }
-
-    // Check if the file type could be determined.
-    videoEditJava_checkAndThrowIllegalArgumentException(
-            &gotten, pEnv,
-            (VideoEditClasses_kFileType_Unsupported == fileType),
-            "file type is not supported");
-
-    // Allocate a new properties structure.
-    pProperties = (VideoEditPropClass_Properties*)videoEditOsal_alloc(
-            &gotten, pEnv,
-            sizeof(VideoEditPropClass_Properties), "Properties");
-
-    // Check if the context is valid and allocation succeeded
-    // (required because of dereferencing of pProperties).
-    if (gotten)
-    {
-        // Check if this type of file needs to be analyzed using MCS.
-        if ((VideoEditClasses_kFileType_MP3  == fileType) ||
-            (VideoEditClasses_kFileType_MP4  == fileType) ||
-            (VideoEditClasses_kFileType_3GPP == fileType) ||
-            (VideoEditClasses_kFileType_AMR  == fileType) ||
-            (VideoEditClasses_kFileType_PCM  == fileType) ||
-            (VideoEditClasses_kFileType_M4V  == fileType))
-        {
-            // Allocate a new clip properties structure.
-            pClipProperties =
-                (M4VIDEOEDITING_ClipProperties*)videoEditOsal_alloc(
-                    &gotten, pEnv,
-                    sizeof(M4VIDEOEDITING_ClipProperties), "ClipProperties");
-
-            // Check if allocation succeeded (required because of
-            // dereferencing of pClipProperties).
-            if (gotten)
-            {
-                // Add a code marker (the condition must always be true).
-                ADD_CODE_MARKER_FUN(NULL != pClipProperties)
-
-                // Log the API call.
-                VIDEOEDIT_LOG_API(
-                        ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
-                        "getClipProperties");
-
-                // Get Video clip properties
-                result = getClipProperties(
-                        pEnv, thiz, pFile, clipType, pClipProperties);
-
-                if (M4MCS_ERR_FILE_DRM_PROTECTED == result) {
-                    // Check if the creation succeeded.
-                    videoEditJava_checkAndThrowIllegalArgumentException(
-                            &gotten, pEnv,(M4NO_ERROR != result),
-                            "Invalid File - DRM Protected ");
-                } else {
-                    // Check if the creation succeeded.
-                    videoEditJava_checkAndThrowIllegalArgumentException(
-                            &gotten, pEnv,(M4NO_ERROR != result),
-                            "Invalid File or File not found ");
-                }
-
-#ifdef USE_SOFTWARE_DECODER
-                /**
-                 * Input clip with non-multiples of 16 is not supported.
-                 */
-                if ( (pClipProperties->uiVideoWidth %16)
-                    || (pClipProperties->uiVideoHeight %16) )
-                {
-                    result = M4MCS_ERR_INPUT_VIDEO_SIZE_NON_X16;
-                    videoEditJava_checkAndThrowIllegalArgumentException(
-                            &gotten, pEnv, (M4NO_ERROR != result),
-                            "non x16 input video frame size is not supported");
-                }
-#endif /* USE_SOFTWARE_DECODER */
-            }
-
-            // Check if the properties could be retrieved.
-            if (gotten)
-            {
-                // Set the properties.
-                pProperties->uiClipDuration = pClipProperties->uiClipDuration;
-                if (M4VIDEOEDITING_kFileType_Unsupported == pClipProperties->FileType)
-                {
-                    pProperties->FileType        = VideoEditClasses_kFileType_Unsupported;
-                }
-                else
-                {
-                    pProperties->FileType        = fileType;
-                }
-                pProperties->VideoStreamType     = pClipProperties->VideoStreamType;
-                pProperties->uiClipVideoDuration = pClipProperties->uiClipVideoDuration;
-                pProperties->uiVideoBitrate      = pClipProperties->uiVideoBitrate;
-                pProperties->uiVideoWidth        = pClipProperties->uiVideoWidth;
-                pProperties->uiVideoHeight       = pClipProperties->uiVideoHeight;
-                pProperties->fAverageFrameRate   = pClipProperties->fAverageFrameRate;
-                pProperties->uiVideoProfile      = pClipProperties->uiVideoProfile;
-                pProperties->uiVideoLevel        = pClipProperties->uiVideoLevel;
-                // Set profile and level support to TRUE, pending check
-                pProperties->bProfileSupported   = M4OSA_TRUE;
-                pProperties->bLevelSupported     = M4OSA_TRUE;
-                pProperties->AudioStreamType     = pClipProperties->AudioStreamType;
-                pProperties->uiClipAudioDuration = pClipProperties->uiClipAudioDuration;
-                pProperties->uiAudioBitrate      = pClipProperties->uiAudioBitrate;
-                pProperties->uiNbChannels        = pClipProperties->uiNbChannels;
-                pProperties->uiSamplingFrequency = pClipProperties->uiSamplingFrequency;
-                pProperties->uiRotation          = pClipProperties->videoRotationDegrees;
-
-            }
-
-            // Free the clip properties.
-            videoEditOsal_free(pClipProperties);
-            pClipProperties = M4OSA_NULL;
-        }
-        else if ((VideoEditClasses_kFileType_JPG == fileType) ||
-            (VideoEditClasses_kFileType_GIF == fileType) ||
-            (VideoEditClasses_kFileType_PNG == fileType))
-        {
-            pProperties->uiClipDuration      = 0;
-            pProperties->FileType            = fileType;
-            pProperties->VideoStreamType     = M4VIDEOEDITING_kNoneVideo;
-            pProperties->uiClipVideoDuration = 0;
-            pProperties->uiVideoBitrate      = 0;
-            pProperties->uiVideoWidth        = width;
-            pProperties->uiVideoHeight       = height;
-            pProperties->fAverageFrameRate   = 0.0f;
-            pProperties->uiVideoProfile = M4VIDEOEDITING_VIDEO_UNKNOWN_PROFILE;
-            pProperties->uiVideoLevel = M4VIDEOEDITING_VIDEO_UNKNOWN_LEVEL;
-            pProperties->AudioStreamType     = M4VIDEOEDITING_kNoneAudio;
-            pProperties->uiClipAudioDuration = 0;
-            pProperties->uiAudioBitrate      = 0;
-            pProperties->uiNbChannels        = 0;
-            pProperties->uiSamplingFrequency = 0;
-
-            // Added for Handling invalid paths and non existent image files
-            // Open the file for reading.
-            result = M4OSA_fileReadOpen(&context, (M4OSA_Void*)pFile, M4OSA_kFileRead);
-            if (M4NO_ERROR != result)
-            {
-                pProperties->FileType = VideoEditClasses_kFileType_Unsupported;
-            }
-            result = M4OSA_fileReadClose(context);
-            context = M4OSA_NULL;
-        }
-    }
-
-    if (M4NO_ERROR == result) {
-        // Create a properties object.
-        videoEditPropClass_createProperties(&gotten, pEnv, pProperties, &properties);
-
-        // Log the properties.
-        VIDEOEDIT_PROP_LOG_PROPERTIES(pProperties);
-    }
-
-    // Free the properties.
-    videoEditOsal_free(pProperties);
-    pProperties = M4OSA_NULL;
-
-    // Free the file path.
-    videoEditOsal_free(pFile);
-    pFile = M4OSA_NULL;
-
-    // Add a text marker (the condition must always be true).
-    ADD_TEXT_MARKER_FUN(NULL != pEnv)
-
-    // Return the Properties object.
-    return(properties);
-}
-
-static void getFileAndMediaTypeFromExtension (
-        M4OSA_Char *pExtension,
-        VideoEditClasses_FileType *pFileType,
-        M4VIDEOEDITING_FileType *pClipType)
-{
-    M4OSA_Char extension[5] = {0, 0, 0, 0, 0};
-    VideoEditClasses_FileType fileType =
-            VideoEditClasses_kFileType_Unsupported;
-
-    M4VIDEOEDITING_FileType clipType =
-            M4VIDEOEDITING_kFileType_Unsupported;
-
-    M4OSA_UInt32 index = 0;
-    M4OSA_ERR result = M4NO_ERROR;
-    M4OSA_Int32 cmpResult = 0;
-    M4OSA_UInt32  extLength = strlen((const char *)pExtension);
-
-    // Assign default
-    *pFileType = VideoEditClasses_kFileType_Unsupported;
-    *pClipType = M4VIDEOEDITING_kFileType_Unsupported;
-
-    // Check if the length of the extension is valid.
-    if ((3 == extLength) || (4 == extLength))
-    {
-        // Convert the extension to lowercase.
-        for (index = 0; index < extLength ; index++)
-        {
-            extension[index] = tolower((int)pExtension[index]);
-        }
-
-        // Check if the extension is ".mp3".
-        if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp3", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_MP3;
-            *pClipType = M4VIDEOEDITING_kFileType_MP3;
-        }
-        // Check if the extension is ".mp4".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"mp4", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_MP4;
-            *pClipType = M4VIDEOEDITING_kFileType_MP4;
-        }
-        // Check if the extension is ".3gp".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gp", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_3GPP;
-            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
-        }
-        // Check if the extension is ".m4a".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4a", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_3GPP;
-            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
-        }
-        // Check if the extension is ".3gpp".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"3gpp", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_3GPP;
-            *pClipType = M4VIDEOEDITING_kFileType_3GPP;
-        }
-        // Check if the extension is ".amr".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"amr", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_AMR;
-            *pClipType = M4VIDEOEDITING_kFileType_AMR;
-        }
-        // Check if the extension is ".pcm".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"pcm", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_PCM;
-            *pClipType = M4VIDEOEDITING_kFileType_PCM;
-        }
-        // Check if the extension is ".jpg".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpg", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_JPG;
-        }
-        // Check if the extension is ".jpeg".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"jpeg", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_JPG;
-        }
-        // Check if the extension is ".gif".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"gif", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_GIF;
-        }
-        // Check if the extension is ".png".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"png", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_PNG;
-        }
-        // Check if the extension is ".m4v".
-        else if (!(VideoEdit_chrCompare(extension, (M4OSA_Char*)"m4v", &cmpResult)))
-        {
-            *pFileType = VideoEditClasses_kFileType_M4V;
-            *pClipType = M4VIDEOEDITING_kFileType_M4V;
-        }
-    }
-}
-
-static M4OSA_ERR getClipProperties(
-        JNIEnv* pEnv,
-        jobject thiz,
-        M4OSA_Char* pFile,
-        M4VIDEOEDITING_FileType clipType,
-        M4VIDEOEDITING_ClipProperties* pClipProperties)
-{
-    bool                      gotten          = true;
-    M4OSA_ERR                 result          = M4NO_ERROR;
-    M4OSA_ERR                 resultAbort     = M4NO_ERROR;
-    M4MCS_Context             context         = M4OSA_NULL;
-
-    M4OSA_FileReadPointer fileReadPtr =
-            { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
-              M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
-
-    M4OSA_FileWriterPointer fileWritePtr =
-            { M4OSA_NULL, M4OSA_NULL, M4OSA_NULL,
-              M4OSA_NULL, M4OSA_NULL, M4OSA_NULL, M4OSA_NULL };
-
-    // Initialize the OSAL file system function pointers.
-    videoEditOsal_getFilePointers(&fileReadPtr , &fileWritePtr);
-
-    // Log the API call.
-    VIDEOEDIT_LOG_API(
-            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",\
-            "getClipProperties - M4MCS_init()");
-
-    // Initialize the MCS context.
-    result = M4MCS_init(&context, &fileReadPtr, &fileWritePtr);
-
-    // Log the result.
-    VIDEOEDIT_PROP_LOG_RESULT(
-            ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
-            videoEditOsal_getResultString(result));
-
-    // Check if the creation succeeded.
-    videoEditJava_checkAndThrowRuntimeException(
-            &gotten, pEnv, (M4NO_ERROR != result), result);
-
-    // Check if opening the MCS context succeeded.
-    if (gotten)
-    {
-        // Log the API call.
-        VIDEOEDIT_LOG_API(
-                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
-                "getClipProperties - M4MCS_open_normalMode()");
-
-        // Open the MCS in the normal opening mode to
-        // retrieve the exact duration
-        result = M4MCS_open_normalMode(
-                context, pFile, clipType, M4OSA_NULL, M4OSA_NULL);
-
-        // Log the result.
-        VIDEOEDIT_PROP_LOG_RESULT(
-                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
-                videoEditOsal_getResultString(result));
-
-        // Check if the creation succeeded.
-        videoEditJava_checkAndThrowRuntimeException(
-                &gotten, pEnv, (M4NO_ERROR != result), result);
-
-        // Check if the MCS could be opened.
-        if (gotten)
-        {
-            // Log the API call.
-            VIDEOEDIT_LOG_API(
-                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
-                    "getClipProperties - M4MCS_getInputFileProperties()");
-
-            // Get the properties.
-            result = M4MCS_getInputFileProperties(context, pClipProperties);
-
-            // Log the result.
-            VIDEOEDIT_PROP_LOG_RESULT(
-                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
-                    videoEditOsal_getResultString(result));
-
-            // Check if the creation succeeded.
-            videoEditJava_checkAndThrowRuntimeException(
-                    &gotten, pEnv, (M4NO_ERROR != result), result);
-        }
-
-        // Log the API call.
-        VIDEOEDIT_LOG_API(
-                ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES",
-                "getClipProperties - M4MCS_abort()");
-
-        // Close the MCS session.
-        resultAbort = M4MCS_abort(context);
-
-       if (result == M4NO_ERROR) {
-            // Log the result.
-            VIDEOEDIT_PROP_LOG_RESULT(
-                    ANDROID_LOG_INFO, "VIDEO_EDITOR_PROPERTIES", "%s",
-                    videoEditOsal_getResultString(resultAbort));
-
-            // Check if the abort succeeded.
-            videoEditJava_checkAndThrowRuntimeException(
-                    &gotten, pEnv, (M4NO_ERROR != resultAbort), resultAbort);
-            result = resultAbort;
-        }
-    }
-
-    return result;
-}
-
-M4OSA_UInt32
-VideoEdit_chrCompare(M4OSA_Char* pStrIn1,
-                     M4OSA_Char* pStrIn2,
-                      M4OSA_Int32* pCmpResult)
-{
-    *pCmpResult = strcmp((const char *)pStrIn1, (const char *)pStrIn2);
-    return *pCmpResult;
-}
-
-
diff --git a/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp b/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp
deleted file mode 100644
index 1508246..0000000
--- a/media/jni/mediaeditor/VideoEditorThumbnailMain.cpp
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
- * Copyright (C) 2011 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 <JNIHelp.h>
-#include <utils/Log.h>
-#include "VideoBrowserMain.h"
-#include "VideoBrowserInternal.h"
-
-#if (M4OSA_TRACE_LEVEL >= 1)
-#undef M4OSA_TRACE1_0
-#undef M4OSA_TRACE1_1
-#undef M4OSA_TRACE1_2
-#undef M4OSA_TRACE1_3
-
-#define M4OSA_TRACE1_0(a)       __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a);
-#define M4OSA_TRACE1_1(a,b)     __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b);
-#define M4OSA_TRACE1_2(a,b,c)   __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c);
-#define M4OSA_TRACE1_3(a,b,c,d) __android_log_print(ANDROID_LOG_INFO, "Thumbnail", a,b,c,d);
-#endif
-
-/*
- * Memory format of 'ARGB8888' in skia is RGBA, so ABGR in 32bit little-endian packed format
- * bitmap format is rgb565
- */
-//                                RED                 GREEN               BLUE            ALPHA
-#define RGB565toSKCOLOR(c) ( (((c)&0xF800)>>8) | (((c)&0x7E0)<<5) | (((c)&0x1F)<<19) | 0xFF000000)
-
-#define GetIntField(env, obj, name) env->GetIntField(obj,\
-env->GetFieldID(env->GetObjectClass(obj), name, "I"))
-
-extern "C" M4OSA_ERR NXPSW_FileReaderOptim_init(M4OSA_Void *lowLevel_functionPointers,
-        M4OSA_Void *optimized_functionPointers);
-
-/*
- * Video Browser execution context.
- * Based on request for RGB565 or RGB888, m_dst16 or m_dst32
- * will be initialized and used
- */
-typedef struct
-{
-    M4OSA_Context       m_pVideoBrowser;
-    M4OSA_UInt32        m_previousTime;
-    M4OSA_Int32*        m_dst32;
-    M4OSA_Int16*        m_dst16;
-    unsigned int        m_width;
-    unsigned int        m_height;
-    M4OSA_Bool          m_bRender;
-} ThumbnailContext;
-
-/**
- ************************************************************************
- * @brief    Interface to retrieve the thumbnail pixels
- * @param    pContext   (IN)    Thumbnail Context.
- * @param    width      (IN)    Width of thumbnail
- * @param    height     (IN)    Height of thumbnail
- * @param    pTimeMS    (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels(const M4OSA_Context pContext,
-                             M4OSA_Int32* pixelArray,
-                             M4OSA_UInt32 width, M4OSA_UInt32 height,
-                             M4OSA_UInt32* pTimeMS, M4OSA_UInt32 tolerance);
-
-
-/**
- ************************************************************************
- * @brief    Video browser callback, called when a frame must be displayed
- * @param    pInstance          (IN) Thumbnail context.
- * @param    notificationID     (IN) Id of the callback which generated the error
- * @param    errCode            (IN) Error code from the Core
- * @param    pCbData            (IN) pointer to data associated wit the callback.
- * @param    pCbUserData        (IN) pointer to application user data passed in init.
- * @note     This callback mechanism is used to request display of an image
- ************************************************************************
-*/
-M4OSA_Void VBcallback(  M4OSA_Context  pInstance,
-                        VideoBrowser_Notification notificationID,
-                        M4OSA_ERR errCode, M4OSA_Void* pCbData,
-                        M4OSA_Void* pCallbackUserData)
-{
-    M4OSA_UInt32 i, j;
-    M4OSA_ERR err;
-
-    M4OSA_TRACE3_0("inside VBcallback");
-    M4VIFI_ImagePlane* pPlane=NULL;
-    M4OSA_UInt16* src=NULL;
-    ThumbnailContext* pC = NULL;
-
-    CHECK_PTR(VBcallback, pCbData, err, M4ERR_PARAMETER);
-    CHECK_PTR(VBcallback, pInstance,err, M4ERR_PARAMETER);
-
-    pC = (ThumbnailContext*)pCallbackUserData ;
-    CHECK_PTR(VBcallback, pC->m_pVideoBrowser, err, M4ERR_PARAMETER);
-
-    pPlane = (M4VIFI_ImagePlane*)pCbData;
-    src = (M4OSA_UInt16*)pPlane->pac_data;
-
-    if (pC->m_dst32 != NULL)
-    {
-        M4OSA_Int32* dst = pC->m_dst32;
-
-        for (j = 0; j < pPlane->u_height; j++)
-        {
-            for (i = 0; i < pPlane->u_width; i++)
-            {
-                dst[i] = RGB565toSKCOLOR(src[i]);
-            }
-            for (i = pPlane->u_width; i < pC->m_width; i++)
-            {
-                dst[i] = 0;
-            }
-            src = (M4OSA_UInt16*)((M4OSA_UInt8*)src + pPlane->u_stride);
-            dst += pC->m_width;
-        }
-    }
-    else if (pC->m_dst16 != NULL)
-    {
-        M4OSA_Int16* dst = pC->m_dst16;
-
-        for (j = 0; j < pPlane->u_height; j++)
-        {
-            memcpy((void * )dst, (void * )src, pPlane->u_stride);
-            for (i = pPlane->u_width; i < pC->m_width; i++)
-            {
-                dst[i] = 0;
-            }
-            src = (M4OSA_UInt16*)((M4OSA_UInt8*)src + pPlane->u_stride);
-            dst += pC->m_width;
-        }
-    }
-    else
-    {
-        CHECK_PTR(VBcallback, NULL, err, M4ERR_PARAMETER);
-    }
-
-VBcallback_cleanUp:
-
-    return;
-}
-
-M4OSA_ERR ThumbnailOpen(M4OSA_Context *pPContext,
-                  const M4OSA_Char *pString,
-                  M4OSA_Bool bRender)
-{
-
-    M4OSA_ERR err;
-    ThumbnailContext *pContext = M4OSA_NULL;
-    VideoBrowser_VideoColorType vbColorType;
-
-    CHECK_PTR(ThumbnailOpen, pString, err, M4ERR_BAD_CONTEXT);
-
-    /*--- Create context ---*/
-    pContext = (ThumbnailContext*)M4OSA_32bitAlignedMalloc(sizeof(ThumbnailContext), VIDEOBROWSER,
-        (M4OSA_Char*)"Thumbnail context") ;
-    M4OSA_TRACE3_1("context value is = %d",pContext);
-    CHECK_PTR(ThumbnailOpen, pContext, err, M4ERR_ALLOC);
-
-    memset((void *)pContext, 0,sizeof(ThumbnailContext));
-
-    M4OSA_FileReadPointer optFP;
-    M4OSA_FileReadPointer llFP;
-
-    NXPSW_FileReaderOptim_init(&llFP, &optFP);
-    M4OSA_TRACE1_2("ThumbnailOpen: entering videoBrowserCreate with 0x%x %s",
-        &pContext->m_pVideoBrowser, pString) ;
-
-    pContext->m_bRender = bRender;
-    if (bRender == M4OSA_TRUE) {
-        //Open is called for rendering the frame.
-        //So set YUV420 as the output color format.
-        vbColorType = VideoBrowser_kYUV420;
-    } else {
-        //Open is called for thumbnail Extraction
-        //So set BGR565 as the output.
-        vbColorType = VideoBrowser_kGB565;
-    }
-
-    err = videoBrowserCreate(&pContext->m_pVideoBrowser, (M4OSA_Char*)pString,
-        VideoBrowser_kVBNormalBliting, &optFP, VBcallback, pContext, vbColorType);
-
-    M4OSA_TRACE1_1("err value is = 0x%x",err);
-    CHECK_ERR(ThumbnailOpen, err);
-    CHECK_PTR(ThumbnailOpen, pContext->m_pVideoBrowser, err, M4ERR_ALLOC);
-
-    *pPContext = pContext;
-    M4OSA_TRACE1_1("context value is = %d",*pPContext);
-
-    return M4NO_ERROR;
-
-ThumbnailOpen_cleanUp:
-
-    M4OSA_TRACE1_0("i am inside cleanUP");
-    if (M4OSA_NULL != pContext)
-    {
-        if (M4OSA_NULL != pContext->m_pVideoBrowser)
-        {
-            videoBrowserCleanUp(pContext->m_pVideoBrowser) ;
-        }
-        free(pContext) ;
-    }
-    return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels(const M4OSA_Context pContext,
-                             M4OSA_Int32* pixelArray,
-                             M4OSA_UInt32 width, M4OSA_UInt32 height,
-                             M4OSA_UInt32* pTimeMS, M4OSA_UInt32 tolerance)
-{
-    M4OSA_ERR err;
-
-    ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
-    if ((pC->m_width != width) || (pC->m_height != height))
-    {
-        err = videoBrowserSetWindow(pC->m_pVideoBrowser, pixelArray,
-                                      0, 0, width, height);
-        CHECK_ERR(ThumbnailGetPixels, err);
-        pC->m_width  = width;
-        pC->m_height = height;
-    }
-
-    // Alter the pTimeMS to a valid value at which a frame is found
-    // m_currentCTS has the actual frame time stamp just ahead of the
-    // pTimeMS supplied.
-    if ((((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS != 0) &&
-        (*pTimeMS >= pC->m_previousTime) &&
-        (*pTimeMS < ((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS))
-    {
-        pC->m_previousTime = *pTimeMS;
-        *pTimeMS = ((VideoBrowserContext*)pC->m_pVideoBrowser)->m_currentCTS;
-    }
-    else
-    {
-        pC->m_previousTime = *pTimeMS;
-    }
-
-    err = videoBrowserPrepareFrame(pC->m_pVideoBrowser, pTimeMS, tolerance);
-    CHECK_ERR(ThumbnailGetPixels, err);
-
-    if (pC->m_bRender != M4OSA_TRUE) {
-        err = videoBrowserDisplayCurrentFrame(pC->m_pVideoBrowser);
-        CHECK_ERR(ThumbnailGetPixels, err);
-    }
-
-ThumbnailGetPixels_cleanUp:
-
-    return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels32(const M4OSA_Context pContext,
-                         M4OSA_Int32* pixelArray, M4OSA_UInt32 width,
-                         M4OSA_UInt32 height, M4OSA_UInt32* timeMS,
-                         M4OSA_UInt32 tolerance)
-{
-
-    M4OSA_ERR err = M4NO_ERROR;
-
-    ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
-    CHECK_PTR(ThumbnailGetPixels32, pC->m_pVideoBrowser, err, M4ERR_ALLOC) ;
-    CHECK_PTR(ThumbnailGetPixels32, pixelArray, err, M4ERR_ALLOC) ;
-
-    pC->m_dst16 = NULL;
-    pC->m_dst32 = pixelArray;
-
-    err = ThumbnailGetPixels(pContext, pixelArray, width, height, timeMS, tolerance);
-
-ThumbnailGetPixels32_cleanUp:
-
-    return err;
-}
-
-M4OSA_ERR ThumbnailGetPixels16(const M4OSA_Context pContext,
-                         M4OSA_Int16* pixelArray, M4OSA_UInt32 width,
-                         M4OSA_UInt32 height, M4OSA_UInt32* timeMS,
-                         M4OSA_UInt32 tolerance)
-{
-    M4OSA_ERR err = M4NO_ERROR;
-
-    ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
-    CHECK_PTR(ThumbnailGetPixels16, pC->m_pVideoBrowser, err, M4ERR_ALLOC);
-    CHECK_PTR(ThumbnailGetPixels16, pixelArray, err, M4ERR_ALLOC);
-
-    pC->m_dst16 = pixelArray;
-    pC->m_dst32 = NULL;
-
-    err = ThumbnailGetPixels(pContext, (M4OSA_Int32*)pixelArray, width, height,
-            timeMS, tolerance);
-
-ThumbnailGetPixels16_cleanUp:
-
-    return err;
-}
-
-
-void ThumbnailClose(const M4OSA_Context pContext)
-{
-    M4OSA_ERR err;
-
-    ThumbnailContext* pC = (ThumbnailContext*)pContext;
-
-    CHECK_PTR(ThumbnailClose, pC, err, M4ERR_ALLOC);
-
-    if (M4OSA_NULL != pC)
-    {
-        if (M4OSA_NULL != pC->m_pVideoBrowser)
-        {
-            videoBrowserCleanUp(pC->m_pVideoBrowser);
-        }
-        free(pC);
-    }
-
-ThumbnailClose_cleanUp:
-
-    return;
-}
-
diff --git a/media/jni/mediaeditor/VideoEditorThumbnailMain.h b/media/jni/mediaeditor/VideoEditorThumbnailMain.h
deleted file mode 100644
index 0b3b0c8..0000000
--- a/media/jni/mediaeditor/VideoEditorThumbnailMain.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2011 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.
- */
-
-#ifndef VIDEOEDITOR_THUMBNAIL_MAIN_H
-#define VIDEOEDITOR_THUMBNAIL_MAIN_H
-
-/**
- ************************************************************************
- * @file        VideoEditorThumbnailMain.h
- * @brief       Thumbnail extract interface.
- ************************************************************************
-*/
-
-/**
- ************************************************************************
- * @brief    Interface to open a Thumbnail session.
- * @param    pContext   (OUT)   Thumbnail Context.
- * @param    pString    (IN)    File path from which thumbnail will be
- *                              retrieved
- * @param    M4OSA_Bool (IN)    true if this is for rendering at native layer.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailOpen(M4OSA_Context *pPContext,
-                  const M4OSA_Char *pString,
-                  M4OSA_Bool bRender);
-
-/**
- ************************************************************************
- * @brief    Interface to retrieve a RGB888 format thumbnail pixels
- * @param    pContext   (IN)    Thumbnail Context.
- * @param    pixelArray (OUT)   Pointer to array in which pixels data to return
- * @param    width      (IN)    Width of thumbnail
- * @param    height     (IN)    Height of thumbnail
- * @param    pTimeMS    (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels32(const M4OSA_Context pContext,
-                             M4OSA_Int32* pixelArray, M4OSA_UInt32 width,
-                             M4OSA_UInt32 height, M4OSA_UInt32 *timeMS,
-                             M4OSA_UInt32 tolerance);
-
-/**
- ************************************************************************
- * @brief    Interface to retrieve a RGB565 format thumbnail pixels
- * @param    pContext   (IN)    Thumbnail Context.
- * @param    pixelArray (OUT)   Pointer to array in which pixcel data to return
- * @param    width      (IN)    Width of thumbnail
- * @param    height     (IN)    Height of thumbnail
- * @param    pTimeMS    (IN/OUT)Time stamp at which thumbnail is retrieved.
- ************************************************************************
-*/
-M4OSA_ERR ThumbnailGetPixels16(const M4OSA_Context pContext,
-                             M4OSA_Int16* pixelArray, M4OSA_UInt32 width,
-                             M4OSA_UInt32 height, M4OSA_UInt32 *timeMS,
-                             M4OSA_UInt32 tolerance);
-
-/**
- ************************************************************************
- * @brief    Interface to close the Thumbnail session.
- * @param    pContext   (IN)    Thumbnail Context.
- ************************************************************************
-*/
-void ThumbnailClose(const M4OSA_Context pContext);
-
-#endif // VIDEOEDITOR_THUMBNAIL_MAIN_H
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
index 3d5905d..cfc0881 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkPerfTestRunner.java
@@ -17,8 +17,6 @@
 package com.android.mediaframeworktest;
 
 import com.android.mediaframeworktest.performance.MediaPlayerPerformance;
-/*Video Editor performance Test cases*/
-import com.android.mediaframeworktest.performance.VideoEditorPerformance;
 import junit.framework.TestSuite;
 
 import android.os.Bundle;
@@ -44,8 +42,6 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(MediaPlayerPerformance.class);
-        /* Video Editor performance Test cases */
-        suite.addTestSuite(VideoEditorPerformance.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index cbb6642..a9dc886 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -32,11 +32,6 @@
 import com.android.mediaframeworktest.functional.audio.MediaPresetReverbTest;
 import com.android.mediaframeworktest.functional.audio.MediaVirtualizerTest;
 import com.android.mediaframeworktest.functional.audio.MediaVisualizerTest;
-import com.android.mediaframeworktest.functional.videoeditor.MediaItemThumbnailTest;
-import com.android.mediaframeworktest.functional.videoeditor.MediaPropertiesTest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorAPITest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorExportTest;
-import com.android.mediaframeworktest.functional.videoeditor.VideoEditorPreviewTest;
 import junit.framework.TestSuite;
 
 import android.os.Bundle;
@@ -76,12 +71,6 @@
         suite.addTestSuite(MediaPresetReverbTest.class);
         suite.addTestSuite(MediaVirtualizerTest.class);
         suite.addTestSuite(MediaVisualizerTest.class);
-        /*Test for Video Editor*/
-        suite.addTestSuite(MediaItemThumbnailTest.class);
-        suite.addTestSuite(MediaPropertiesTest.class);
-        suite.addTestSuite(VideoEditorAPITest.class);
-        suite.addTestSuite(VideoEditorExportTest.class);
-        suite.addTestSuite(VideoEditorPreviewTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
index 0cd784c..5438061 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaPlayerStressTestRunner.java
@@ -19,8 +19,6 @@
 import android.test.InstrumentationTestRunner;
 import android.test.InstrumentationTestSuite;
 import com.android.mediaframeworktest.stress.MediaPlayerStressTest;
-/** Import for Video Editor Stress Test cases*/
-import com.android.mediaframeworktest.stress.VideoEditorStressTest;
 
 import junit.framework.TestSuite;
 
@@ -30,8 +28,6 @@
     public TestSuite getAllTests() {
         TestSuite suite = new InstrumentationTestSuite(this);
         suite.addTestSuite(MediaPlayerStressTest.class);
-        /** Video Editor Stress Test cases*/
-        suite.addTestSuite(VideoEditorStressTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java
deleted file mode 100644
index dd7c4c6..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/VideoEditorHelper.java
+++ /dev/null
@@ -1,479 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Random;
-
-import junit.framework.Assert;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditorFactory;
-import android.util.Log;
-import android.os.Environment;
-
-/**
- * This class has the names of the all the activity name and variables in the
- * instrumentation test.
- */
-public class VideoEditorHelper extends Assert {
-
-    private final String TAG = "VideoEditorMediaNames";
-
-    public VideoEditorHelper() {
-
-    }
-
-    public static final String PROJECT_LOCATION_COMMON =
-        Environment.getExternalStorageDirectory().toString() + "/";
-
-    public static final String INPUT_FILE_PATH_COMMON = PROJECT_LOCATION_COMMON +
-        "media_api/videoeditor/";
-
-    // -----------------------------------------------------------------
-    // HELPER METHODS
-    // -----------------------------------------------------------------
-
-    /**
-     * This method creates an object of VideoEditor
-     *
-     * @param projectPath the directory where all files related to project will
-     *            be stored
-     * @param className The class which implements the VideoEditor Class
-     * @return the object of VideoEditor
-     */
-    public VideoEditor createVideoEditor(String projectPath) {
-        VideoEditor mVideoEditor = null;
-        try {
-            mVideoEditor = VideoEditorFactory.create(projectPath);
-            assertNotNull("VideoEditor", mVideoEditor);
-        } catch (Exception e) {
-            fail("Unable to create Video Editor");
-        }
-        return mVideoEditor;
-    }
-
-    /**
-     *This method deletes the VideoEditor object created using
-     * createVideoEditor method
-     *
-     * @param videoEditor the VideoEditor object which needs to be cleaned up
-     */
-    public void destroyVideoEditor(VideoEditor videoEditor) {
-        // Release VideoEditor
-        if (videoEditor != null) {
-            try {
-                videoEditor.release();
-            } catch (Exception e) {
-                fail("Unable to destory Video Editor");
-            }
-        }
-    }
-
-    /**
-     *This Method checks the Range in "RangePercent" (say 10)
-     *
-     * @param int Expected data
-     * @param actual data
-     * @return boolean flag which confirms the range matching
-     */
-    public boolean checkRange(long expected, long actual, long rangePercent) {
-        long range = 0;
-        range = (100 * actual) / expected;
-
-        Log.i("checkRange", "Range = " + range);
-        if ((range > (100 - rangePercent)) && (range < (100 + rangePercent))) {
-            return true;
-        } else {
-            return false;
-        }
-    }
-
-    /**
-     *This Method Creates a Bitmap with the given input file
-     *
-     * @param file the Input whose Bitmap has top be extracted
-     * @return an Object of EffectColor
-     */
-    public Bitmap getBitmap(String file, int width, int height) throws IOException {
-        assertNotNull("Bitmap File is Null", file);
-        FileInputStream inputStream = null;
-        Bitmap overlayBmp = null;
-        if (!new File(file).exists())
-            throw new IOException("File not Found " + file);
-        try {
-            final BitmapFactory.Options dbo = new BitmapFactory.Options();
-            dbo.inJustDecodeBounds = true;
-            dbo.outWidth = width;
-            dbo.outHeight = height;
-            File flPtr = new File(file);
-            inputStream = new FileInputStream(flPtr);
-            final Bitmap srcBitmap = BitmapFactory.decodeStream(inputStream);
-            overlayBmp = Bitmap.createBitmap(srcBitmap);
-            assertNotNull("Bitmap 1", srcBitmap);
-            assertNotNull("Bitmap 2", overlayBmp);
-            inputStream.close();
-        } catch (IOException e) {
-            e.printStackTrace();
-        }
-        return overlayBmp;
-    }
-
-    /**
-     *This Method Create a Media Video Item with the specified params
-     *
-     * @return an Object of MediaVideoItem
-     */
-    public MediaVideoItem createMediaItem(VideoEditor videoEditor,
-        String MediaId, String filename, int renderingMode) {
-        MediaVideoItem mvi = null;
-        try {
-            mvi = new MediaVideoItem(videoEditor, MediaId, filename,
-                renderingMode);
-            assertNotNull("Can not create an object of MediaVideoItem", mvi);
-        } catch (IllegalArgumentException e) {
-            throw new IllegalArgumentException
-                ("Can not create an object of Media Video Item with file name = "
-                    + filename + " Issue = " + e.toString());
-        } catch (IOException e) {
-            assertTrue
-                ("Can not create an object of Media Video Item with file name = "
-                    + filename + " Issue = " + e.toString(), false);
-        }
-        return mvi;
-    }
-
-    /**
-     *This Method Create a Media Image Item with the specified params
-     *
-     * @return an Object of MediaImageItem
-     */
-    public MediaImageItem createMediaItem(VideoEditor videoEditor,
-        String MediaId, String filename, long duration, int renderingMode) {
-        MediaImageItem mii = null;
-        try {
-            mii = new MediaImageItem(videoEditor, MediaId, filename, duration,
-                renderingMode);
-            assertNotNull("Can not create an object of MediaImageItem", mii);
-
-        } catch (IllegalArgumentException e) {
-            assertTrue("Can not create an object of Media Image with file name = "
-                + filename + " Issue = " + e.toString(), false);
-        } catch (IOException e) {
-            assertTrue("Can not create an object of Media Image with file name = "
-                + filename + " Issue = " + e.toString(), false);
-        }
-        return mii;
-    }
-
-    /**
-     *This Method Create a Effect with the specified params
-     *
-     * @return an Object of EffectColor
-     */
-    public EffectColor createEffectItem(MediaItem mediaItem, String effectId,
-        long startTime, long duration, int effectType, int colorType) {
-        EffectColor effectonMVI = null;
-        effectonMVI = new EffectColor(mediaItem, effectId, startTime,
-            duration, effectType, colorType);
-        return effectonMVI;
-    }
-
-    /**
-     *This Method creates object of Type Transition Cross fade
-     *
-     * @return TransitionCrossfade object
-     */
-    public TransitionCrossfade createTCrossFade(String transitionId,
-        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
-        int behavior) {
-        Log.i("TransitionCrossfade Details === ", "Transid ID = " + transitionId +
-            " Duration= " + durationMs + " Behaviour " + behavior);
-
-        TransitionCrossfade transitionCF = null;
-            transitionCF = new TransitionCrossfade(transitionId, afterMediaItem,
-                beforeMediaItem, durationMs, behavior);
-        return transitionCF;
-    }
-
-    /**
-     *This Method creates object of Type TransitionFadeBlack
-     *
-     * @return TransitionFadeBlack object
-     */
-    public TransitionFadeBlack createTFadeBlack(String transitionId,
-        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
-        int behavior) {
-        TransitionFadeBlack transitionFB = null;
-
-        transitionFB = new TransitionFadeBlack(transitionId, afterMediaItem,
-            beforeMediaItem, durationMs, behavior);
-        return transitionFB;
-    }
-
-    /**
-     *This Method creates object of Type TransitionSliding
-     *
-     * @return TransitionSliding object
-     */
-    public TransitionSliding createTSliding(String transitionId,
-        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
-        int behavior, int direction) {
-        TransitionSliding transSlide = null;
-            transSlide = new TransitionSliding(transitionId, afterMediaItem,
-                beforeMediaItem, durationMs, behavior, direction);
-        return transSlide;
-    }
-
-    /**
-     *This Method creates object of Type TranistionAlpha
-     *
-     * @return TranistionAlpha object
-     */
-
-    public TransitionAlpha createTAlpha(String transitionId,
-        MediaItem afterMediaItem, MediaItem beforeMediaItem, long durationMs,
-        int behavior, String maskFilename, int blendingPercent, boolean invert) {
-        TransitionAlpha transA = null;
-            transA = new TransitionAlpha(transitionId, afterMediaItem,
-                beforeMediaItem, durationMs, behavior, maskFilename,
-                blendingPercent, invert);
-        return transA;
-    }
-
-    /**
-     *This Method creates object of Type OverlayFrame
-     *
-     * @return OverlayFrame object
-     */
-
-    public OverlayFrame createOverlay(MediaItem mediaItem, String overlayId,
-        Bitmap bitmap, long startTimeMs, long durationMs) {
-        OverlayFrame overLayFrame = null;
-        overLayFrame = new OverlayFrame(mediaItem, overlayId, bitmap,
-                startTimeMs, durationMs);
-        return overLayFrame;
-    }
-
-    /**
-     *This Method creates object of Type AudioTrack
-     *
-     * @return OverlayFrame object
-     */
-    public AudioTrack createAudio(VideoEditor videoEditor, String audioTrackId,
-        String filename) {
-        AudioTrack audio = null;
-        try {
-            audio = new AudioTrack(videoEditor, audioTrackId, filename);
-            assertNotNull("Cant not create an object of an  AudioTrack " +
-                audioTrackId, audio);
-        } catch (IllegalArgumentException e) {
-            assertTrue("Can not create object of an AudioTrack " +
-                audioTrackId + " Issue = " + e.toString(), false);
-        } catch (IOException e) {
-            assertTrue("Can not create object of an AudioTrack " +
-                audioTrackId + " Issue = " + e.toString(), false);
-        }
-        return audio;
-    }
-
-    /**
-     *This Method validates the Exported Movie,as per the specified params
-     * during Export
-     */
-
-    public void validateExport(VideoEditor videoEditor, String fileName,
-        int export_height, int startTime, long endTime, int vCodec, int aCodec) {
-        File tempFile = new File(fileName);
-        assertEquals("Exported FileName", tempFile.exists(), true);
-        final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
-            MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        Log.i(TAG, "VideoCodec for file = " + fileName +
-            "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
-            mvi.getVideoType());
-        assertEquals("Export: Video Codec Mismatch for file = " + fileName +
-            "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
-            vCodec, mvi.getVideoType());
-
-        Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
-            export_height + "\tActual VideoHeight = " + mvi.getHeight());
-        assertEquals("Export height Mismatch for file " + fileName +
-            "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
-             export_height, mvi.getHeight());
-        if (startTime == 0) {
-            if (endTime != 0) {
-                Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
-                    "\t VideoTime= " + mvi.getTimelineDuration());
-                assertTrue("Timeline Duration Mismatch for file " + fileName +
-                    "<expected> " + (startTime + endTime) + "\t<actual> " +
-                    mvi.getTimelineDuration(), checkRange((startTime +
-                        endTime), mvi.getTimelineDuration(), 10));
-            }
-        } else {
-            Log.i(TAG, "TimeLine Expected = " + (endTime - startTime) +
-                "\t VideoTime= " + mvi.getTimelineDuration());
-            assertTrue("Timeline Duration Mismatch for file " + fileName +
-                "<expected> " + (endTime - startTime) + "\t<actual> " +
-                mvi.getTimelineDuration(), checkRange((endTime -
-                    startTime), (int)mvi.getTimelineDuration(), 10));
-        }
-    }
-
-    /**
-     * @param videoEditor
-     * @param fileName
-     * @param export_bitrate
-     * @param export_height
-     * @param startTime
-     * @param endTime
-     * @param vCodec
-     * @param aCodec
-     */
-    public void validateExport(VideoEditor videoEditor, String fileName,
-        int export_height, int startTime, int endTime, int vCodec, int aCodec) {
-        File tempFile = new File(fileName);
-        assertEquals("Exported FileName", tempFile.exists(), true);
-        final MediaVideoItem mvi = createMediaItem(videoEditor, "m1", fileName,
-            MediaItem.RENDERING_MODE_BLACK_BORDER);
-        Log.i(TAG, "VideoCodec for file = " + fileName +
-            "\tExpected Video Codec = " + vCodec + "\tActual Video Codec = " +
-            mvi.getVideoType());
-        assertEquals("Export: Video Codec Mismatch for file = " + fileName +
-            "\t<expected> " + vCodec + "\t<actual> " + mvi.getVideoType(),
-            vCodec, mvi.getVideoType());
-
-        Log.i(TAG, "AudioCodec for file = " + fileName +
-            "\tExpected Audio Codec = " + aCodec + "\tActual Audio Codec = " +
-            mvi.getAudioType());
-        assertEquals("Export: Audio Codec Mismatch for file = " + fileName +
-            "\t<expected> " + aCodec + "\t<actual> " + mvi.getAudioType(),
-            aCodec, mvi.getAudioType());
-
-        Log.i(TAG, "Height for file = " + fileName + "\tExpected Height = " +
-            export_height + "\tActual VideoHeight = " + mvi.getHeight());
-        assertEquals("Export: height Mismatch for file " + fileName +
-            "\t<expected> " + export_height + "\t<actual> " + mvi.getHeight(),
-            export_height, mvi.getHeight());
-        if (startTime == 0) {
-            if (endTime != 0) {
-                Log.i(TAG, "TimeLine Expected = " + (startTime + endTime) +
-                    "\t VideoTime= " + mvi.getTimelineDuration());
-                assertTrue("Export :Timeline Duration Mismatch for file " +
-                    fileName + "<expected> " + (startTime + endTime) +
-                    "\t<actual> " + mvi.getTimelineDuration(),
-                    checkRange((startTime + endTime), mvi.getTimelineDuration(), 10));
-            }
-        } else {
-            Log.i(TAG, "TimeLine Expected = " + (endTime-startTime) +
-                "\t VideoTime= " + mvi.getTimelineDuration());
-            assertTrue("Timeline Duration Mismatch for file " + fileName +
-                "<expected> " + (endTime - startTime) + "\t<actual> " +
-                mvi.getTimelineDuration(), checkRange((endTime -
-                    startTime), mvi.getTimelineDuration(), 10));
-        }
-    }
-
-    /**
-     * Check file and deletes it.
-     *
-     * @param filename
-     */
-    public void checkDeleteExistingFile(String filename) {
-        Log.i(TAG, ">>>>>>>>>>>>>>>>>>checkDeleteExistingFile  = " + filename);
-        if (filename != null) {
-            File temp = new File(filename);
-            if (temp != null && temp.exists()) {
-                temp.delete();
-            }
-        }
-    }
-
-    /**
-     * This method creates a Directory and filename
-     *
-     * @param location This is path where the file is to be created
-     *            "/sdcard/Output/"
-     * @return Path in form of /sdcard/Output/200910100000
-     */
-    public String createRandomFile(String location) {
-        Random randomGenerator = new Random();
-        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmssS");
-        Date date = new Date();
-        final String filePath = location + dateFormat.format(date) +
-            randomGenerator.nextInt(10);
-        Log.i(TAG, ">>>>>>>>>>>>>>>>createRandomFile  Location= " + location +
-            "\t FilePath = " + filePath);
-        return filePath;
-    }
-
-    /**
-     * This method recursively deletes all the file and directory
-     *
-     * @param directory where the files are located Example = "/sdcard/Input"
-     * @return boolean True if deletion is successful else False
-     */
-    public boolean deleteProject(File directory) {
-        Log.i(TAG, ">>>>>>>>>>>>>>>>>>>>>>>>deleteProject  directory= " +
-            directory.toString());
-        if (directory.isDirectory()) {
-            String[] filesInDirecory = directory.list();
-            for (int i = 0; i < filesInDirecory.length; i++) {
-                boolean success = deleteProject(new File(directory,
-                    filesInDirecory[i]));
-                if (!success) {
-                    return false;
-                }
-            }
-        }
-        return directory.delete();
-    }
-
-    /**
-     * This method compares the array of Integer from 0 - 100
-     *
-     * @param data set of integer values received as progress
-     * @return true if sucess else false
-     */
-    public boolean checkProgressCBValues(int[] data) {
-        boolean retFlag = false;
-        for (int i = 0; i < 100; i++) {
-            if (data[i] == 100) {
-                retFlag = true;
-                break;
-            } else {
-                retFlag = false;
-            }
-        }
-        return retFlag;
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java
deleted file mode 100644
index 7dfab7d..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaItemThumbnailTest.java
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.graphics.Bitmap;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class MediaItemThumbnailTest extends
-    ActivityInstrumentationTestCase<MediaFrameworkTest> {
-    private final String TAG = "MediaItemThumbailTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private VideoEditor mVideoEditor;
-
-    private VideoEditorHelper mVideoEditorHelper;
-
-    public MediaItemThumbnailTest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath = mVideoEditorHelper.
-            createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    protected void validateThumbnail(Bitmap thumbNailBmp, int outWidth,
-        int outHeight) throws Exception {
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Height", outHeight, thumbNailBmp.getHeight());
-        assertEquals("Thumbnail Width", outWidth, thumbNailBmp.getWidth());
-        thumbNailBmp.recycle();
-    }
-
-    // -----------------------------------------------------------------
-    // THUMBNAIL
-    // -----------------------------------------------------------------
-    /**
-     * To test thumbnail / frame extraction on H.263 QCIF.
-     */
-    @LargeTest
-    public void testThumbnailForH263QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = mediaVideoItem.getHeight();
-
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on MPEG4 VGA .
-     */
-    @LargeTest
-    public void testThumbnailForMPEG4VGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_30fps_512Kbps_0_23.3gp";
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = mediaVideoItem.getHeight();
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on MPEG4 NTSC.
-     */
-    @LargeTest
-    public void testThumbnailForMPEG4NTSC() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth() / 2;
-        final int outHeight = mediaVideoItem.getHeight() / 2;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on MPEG4 WVGA.
-     */
-    @LargeTest
-    public void testThumbnailForMPEG4WVGA() throws Exception {
-
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth() * 2;
-        final int outHeight = mediaVideoItem.getHeight();
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on MPEG4 QCIF.
-     */
-    @LargeTest
-    public void testThumbnailForMPEG4QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth();
-        final int outHeight = mediaVideoItem.getHeight() * 2;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on H264 QCIF.
-     */
-    @LargeTest
-    public void testThumbnailForH264QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
-
-        final int atTime = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth() * 2;
-        final int outHeight = mediaVideoItem.getHeight() * 2;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on H264 VGA.
-     */
-    @LargeTest
-    public void testThumbnailForH264VGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final int outWidth = 32;
-        final int outHeight = 32;
-        final int atTime = 0;
-
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-    /**
-     * To test thumbnail / frame extraction on H264 WVGA.
-     */
-    @LargeTest
-    public void testThumbnailForH264WVGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int outWidth = 64;
-        final int outHeight = 64;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final long atTime = mediaVideoItem.getDuration() / 2;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on H264 854x480.
-     */
-    @LargeTest
-    public void testThumbnailForH264854_480() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
-        final int outWidth = 128;
-        final int outHeight = 128;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        MediaVideoItem mediaVideoItem = null;
-        mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final long atTime = mediaVideoItem.getDuration() - 1000;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on H264 960x720.
-     */
-    @LargeTest
-    public void testThumbnailForH264HD960() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
-        final int outWidth = 75;
-        final int outHeight = 75;
-
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final long atTime = mediaVideoItem.getDuration() - 1000;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on H264 1080x720 .
-     */
-    @LargeTest
-    public void testThumbnailForH264HD1080() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth() / 2;
-        final int outHeight = mediaVideoItem.getHeight() / 2;
-        final long atTime = mediaVideoItem.getDuration() / 4;
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * Check the thumbnail / frame extraction precision at 0,100 and 200 ms
-     */
-    @LargeTest
-    public void testThumbnailForH264VGADifferentDuration() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final int atTime = 0;
-        final int atTime1 = 100;
-        final int atTime2 = 200;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = mediaVideoItem.getWidth();
-        final int outHeight = mediaVideoItem.getHeight();
-
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
-        // get Thumbnail @ 100ms
-        final Bitmap thumbNailBmpAt100 =
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime1);
-        validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
-
-        // get Thumbnail @ 200ms
-        final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
-            outWidth, outHeight, atTime2);
-        validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
-    }
-
-    /**
-     *Check the thumbnail / frame extraction precision at
-     * FileDuration,FileDuration/2 + 100 andFileDuration/2 + 200 ms
-     */
-    @LargeTest
-    public void testThumbnailForMP4VGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        final int outWidth = mediaVideoItem.getWidth();
-        final int outHeight = mediaVideoItem.getHeight();
-        final long atTime = mediaVideoItem.getDuration() / 2;
-        final long atTime1 = atTime + 100;
-        final long atTime2 = atTime + 200;
-
-        // get Thumbnail @ duration/2
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
-        // get Thumbnail @ duration/2 + 100ms
-        final Bitmap thumbNailBmpAt100 = mediaVideoItem.getThumbnail(
-            outWidth, outHeight, atTime1);
-        validateThumbnail(thumbNailBmpAt100, outWidth, outHeight);
-
-        // get Thumbnail @ duration/2 + 200ms
-        final Bitmap thumbNailBmpAt200 = mediaVideoItem.getThumbnail(
-            outWidth, outHeight, atTime2);
-        validateThumbnail(thumbNailBmpAt200, outWidth, outHeight);
-    }
-
-    /**
-     * Check the thumbnail / frame extraction on JPEG file
-     */
-    @LargeTest
-    public void testThumbnailForImage() throws Exception {
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int mediaDuration = 1000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        int outWidth = 0;
-        int outHeight = 0;
-
-        final MediaImageItem mii = mVideoEditorHelper.createMediaItem(
-            mVideoEditor, "m1", imageItemFilename, mediaDuration, renderingMode);
-        assertNotNull("Media Image Item is Null",  mii);
-        outWidth =  mii.getWidth() / 2;
-        outHeight =  mii.getHeight() / 2;
-
-        final Bitmap thumbNailBmp = mii.getThumbnail(outWidth,
-            outHeight, mediaDuration);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-    /**
-     *To test ThumbnailList for H263 QCIF
-     */
-    @LargeTest
-    public void testThumbnailListH263QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        final int startTime = 0;
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = mediaVideoItem.getWidth() / 4;
-        final int outHeight = mediaVideoItem.getHeight() / 4;
-        final long endTime = mediaVideoItem.getDuration() / 2;
-
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
-            outWidth, outHeight, startTime, endTime, tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for MPEG4 QCIF
-     */
-    @LargeTest
-    public void testThumbnailListMPEG4QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = mediaVideoItem.getWidth() / 2;
-        final int outHeight = mediaVideoItem.getHeight() / 2;
-        final long startTime = mediaVideoItem.getDuration() / 2;
-        final long endTime = mediaVideoItem.getDuration();
-
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
-            outWidth, outHeight, startTime, endTime, tnCount);
-
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for H264 VGA
-     */
-    @LargeTest
-    public void testThumbnailListH264VGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = mediaVideoItem.getWidth() / 2;
-        final int outHeight = mediaVideoItem.getHeight() / 2;
-        final long startTime = mediaVideoItem.getDuration() / 3;
-        final long endTime = mediaVideoItem.getDuration() / 2;
-
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
-            outWidth, outHeight, startTime, endTime, tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for H264 WVGA
-     */
-    @LargeTest
-    public void testThumbnailListH264WVGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = mediaVideoItem.getWidth() / 2;
-        final int outHeight = mediaVideoItem.getHeight() / 2;
-        final long startTime = mediaVideoItem.getDuration() / 3;
-        final long endTime = mediaVideoItem.getDuration() / 2;
-
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(
-            outWidth, outHeight, startTime, endTime, tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for H264 VGA ,Time exceeding file duration
-     */
-    @LargeTest
-    public void testThumbnailH264VGAExceedingFileDuration() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        boolean flagForException = false;
-        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        try {
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = mediaVideoItem.getWidth() / 2;
-            final int outHeight = mediaVideoItem.getHeight() / 2;
-            final long atTime = mediaVideoItem.getDuration() + 2000;
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Exception in Extracting thumbanil with Invalid Time",
-            flagForException);
-    }
-
-    /**
-     *To test ThumbnailList for VGA Image
-     */
-    @LargeTest
-    public void testThumbnailListVGAImage() throws Exception {
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemDuration = 10000;
-        final int startTime = 0;
-        final int endTime = 0;
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                imageItemFilename, imageItemDuration, renderingMode);
-        final int outWidth = mediaImageItem.getWidth() / 2;
-        final int outHeight = mediaImageItem.getHeight() / 2;
-
-        final Bitmap thumbNailBmp[] = mediaImageItem.getThumbnailList
-            (outWidth, outHeight, startTime, endTime, tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for Invalid file path
-     */
-    @LargeTest
-    public void testThumbnailForInvalidFilePath() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "/sdcard/abc.jpg";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try{
-        final MediaImageItem mii = new MediaImageItem(mVideoEditor, "m1",
-            imageItemFileName, 3000, renderingMode);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        } catch (IOException e) {
-            flagForException = true;
-        }
-        assertTrue(" Invalid File Path", flagForException);
-    }
-
-    /**
-     * To test thumbnail / frame extraction with setBoundaries
-     */
-    @LargeTest
-    public void testThumbnailForMPEG4WVGAWithSetBoundaries() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
-        final int atTime = 10000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        mediaVideoItem.setExtractBoundaries(1000,
-            (mediaVideoItem.getDuration() - 21000));
-
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = (mediaVideoItem.getHeight() / 2);
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail(outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     *To test ThumbnailList for H264 WVGA with setExtractboundaries
-     */
-    @LargeTest
-    public void testThumbnailListForH264WVGAWithSetBoundaries() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
-        final int thumbNailStartTime = 10000;
-        final int thumbNailEndTime = 12000;
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = (mediaVideoItem.getHeight() / 2);
-
-        mediaVideoItem.setExtractBoundaries(10000, 12000);
-
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList
-            (outWidth, outHeight, thumbNailStartTime, thumbNailEndTime,
-             tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertTrue("Thumbnail Size", (thumbNailBmp.length > 0) ? true : false);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for H264 WVGA with count > frame available
-     */
-    @LargeTest
-    public void testThumbnailListForH264WVGAWithCount() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int tnCount = 70;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = (mediaVideoItem.getHeight() / 2);
-        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
-        final long thumbNailEndTime = thumbNailStartTime + 4000;
-        Bitmap thumbNailBmp[] = null;
-        boolean flagForException = false;
-        try{
-            thumbNailBmp = mediaVideoItem.getThumbnailList(outWidth, outHeight,
-                thumbNailStartTime, thumbNailEndTime, tnCount);
-        }catch (Exception e){
-            assertTrue("Unable to get Thumbnail list", flagForException);
-        }
-        if (thumbNailBmp.length <= tnCount) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail count more than asked", flagForException);
-    }
-
-    /**
-     *To test ThumbnailList for H264 WVGA with startTime > End Time
-     */
-    @LargeTest
-    public void testThumbnailListH264WVGAWithStartGreaterEnd() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int tnCount = 10;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = (mediaVideoItem.getHeight() / 2);
-        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
-        final long thumbNailEndTime = thumbNailStartTime - 1000;
-        try{
-            mediaVideoItem.getThumbnailList(outWidth, outHeight,
-                thumbNailStartTime, thumbNailEndTime, tnCount);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail Extraction where start time > end time",
-            flagForException);
-    }
-
-    /**
-     *To test ThumbnailList for H264 WVGA with startTime = End Time
-     */
-    @LargeTest
-    public void testThumbnailListH264WVGAWithStartEqualEnd() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int tnCount = 1;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = (mediaVideoItem.getWidth() / 2);
-        final int outHeight = (mediaVideoItem.getHeight() / 2);
-        final long thumbNailStartTime = mediaVideoItem.getDuration() / 2;
-        final long thumbNailEndTime = thumbNailStartTime;
-        final Bitmap thumbNailBmp[] = mediaVideoItem.getThumbnailList(outWidth,
-            outHeight, thumbNailStartTime, thumbNailEndTime, tnCount);
-        assertNotNull("Thumbnail Retrived is Null", thumbNailBmp);
-        assertEquals("Thumbnail Count", tnCount, thumbNailBmp.length);
-        for (int i = 0; i < thumbNailBmp.length; i++) {
-            validateThumbnail(thumbNailBmp[i], outWidth, outHeight);
-            thumbNailBmp[i] = null;
-        }
-    }
-
-    /**
-     *To test ThumbnailList for file where video duration is less
-     * than file duration.
-     */
-    @LargeTest
-    public void testThumbnailForVideoDurationLessFileDuration() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = (mediaVideoItem.getWidth() / 2);
-            final int outHeight = (mediaVideoItem.getHeight() / 2);
-            final long atTime = mediaVideoItem.getDuration() - 2000;
-            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
-                outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-
-    }
-
-    /**
-     *To test ThumbnailList for file which has video part corrupted
-     */
-    @LargeTest
-    public void testThumbnailWithCorruptedVideoPart() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "corrupted_H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-
-        try {
-            final MediaVideoItem mediaVideoItem =
-                 mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = mediaVideoItem.getWidth();
-            final int outHeight = mediaVideoItem.getHeight() * 2;
-            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail
-                (outWidth, outHeight, mediaVideoItem.getDuration()/2);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Corrupted File cannot be read", flagForException);
-    }
-
-    /**
-     * Check the thumbnail / frame list extraction for Height as Negative Value
-     */
-    @LargeTest
-    public void testThumbnailWithNegativeHeight() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try {
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = (mediaVideoItem.getWidth() / 2);
-            final int outHeight = -1;
-            final long thumbNailStartTime =
-                mediaVideoItem.getBoundaryBeginTime()/2;
-            final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
-            mediaVideoItem.getThumbnailList(outWidth, outHeight,
-                thumbNailStartTime, thumbNailEndTime, tnCount);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail List with negative Height", flagForException);
-    }
-
-    /**
-     * Check the thumbnail for Height as Zero
-     */
-    @LargeTest
-    public void testThumbnailWithHeightAsZero() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int atTime = 100;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try {
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = (mediaVideoItem.getWidth() / 2);
-            final int outHeight = -1;
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail List with Zero Height", flagForException);
-    }
-
-    /**
-     * Check the thumbnail for Height = 10
-     */
-    @LargeTest
-    public void testThumbnailWithHeight() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int atTime = 1000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = (mediaVideoItem.getWidth() / 2);
-            final int outHeight = 10;
-            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
-                outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * Check the thumbnail / frame list extraction for Width as Negative Value
-     */
-    @LargeTest
-    public void testThumbnailWithNegativeWidth() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int tnCount = 10;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try {
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = -1;
-            final int outHeight = mediaVideoItem.getHeight();
-            final long thumbNailStartTime =
-                mediaVideoItem.getBoundaryBeginTime()/2;
-            final long thumbNailEndTime = mediaVideoItem.getBoundaryEndTime();
-            mediaVideoItem.getThumbnailList(outWidth, outHeight, thumbNailStartTime,
-                thumbNailEndTime, tnCount);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail List with negative Height", flagForException);
-    }
-
-    /**
-     * Check the thumbnail / frame list extraction for Width zero
-     */
-    @LargeTest
-    public void testThumbnailWithWidthAsZero() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int atTime = 1000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try {
-            final MediaVideoItem mediaVideoItem =
-                mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                    videoItemFilename, renderingMode);
-            final int outWidth = 0;
-            final int outHeight = mediaVideoItem.getHeight() / 2;
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail List with Zero Width", flagForException);
-    }
-
-    /**
-     * Check the thumbnail for Width = 10
-     */
-    @LargeTest
-    public void testThumbnailWithWidth() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        final int atTime = 1000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth = 10;
-        final int outHeight = mediaVideoItem.getHeight();
-        final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
-            outHeight, atTime);
-        validateThumbnail(thumbNailBmp, outWidth, outHeight);
-    }
-
-    /**
-     * To test thumbnail / frame extraction on MPEG4 (time beyond file duration).
-     */
-    @LargeTest
-    public void testThumbnailMPEG4withMorethanFileDuration() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_30fps_256kbps_AACLC_44.1kHz_96kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename, renderingMode);
-        final int outWidth =  mediaVideoItem.getWidth()/2;
-        final int outHeight =  mediaVideoItem.getHeight()/2;
-        final long atTime = mediaVideoItem.getDuration() + 100;
-        try{
-            final Bitmap thumbNailBmp = mediaVideoItem.getThumbnail (outWidth,
-            outHeight, atTime);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Thumbnail duration is more than file duration",
-            flagForException);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java
deleted file mode 100644
index 34cf9f0..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/MediaPropertiesTest.java
+++ /dev/null
@@ -1,750 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-import com.android.mediaframeworktest.MediaProfileReader;
-
-public class MediaPropertiesTest extends
-    ActivityInstrumentationTestCase<MediaFrameworkTest> {
-    private final String TAG = "MediaPropertiesTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private VideoEditor mVideoEditor;
-
-    private VideoEditorHelper mVideoEditorHelper;
-
-    public MediaPropertiesTest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path,
-        // where all project related files will be stored.
-        final String projectPath = mVideoEditorHelper.
-            createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    protected void validateVideoProperties(int aspectRatio, int fileType,
-        int videoCodecType, int duration, int videoBitrate, int fps,
-        int videoProfile, int videoLevel, int width, int height, int audioCodecType,
-        int audioSamplingFrequency, int audioChannel, int audioBitrate,
-        MediaVideoItem mvi) throws Exception {
-        assertEquals("Aspect Ratio Mismatch", aspectRatio, mvi.getAspectRatio());
-        assertEquals("File Type Mismatch", fileType, mvi.getFileType());
-        assertEquals("VideoCodec Mismatch", videoCodecType, mvi.getVideoType());
-
-        assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
-            duration, mvi.getDuration(), 10));
-        assertEquals("Video Profile " + mvi.getVideoProfile(), videoProfile,
-            mvi.getVideoProfile());
-        assertEquals("Video Level " + mvi.getVideoLevel(), videoLevel,
-            mvi.getVideoLevel());
-        assertEquals("Video height " + mvi.getHeight(), height, mvi.getHeight());
-        assertEquals("Video width " + mvi.getWidth(), width, mvi.getWidth());
-        /** Check FPS with 10% range */
-        assertTrue("fps Mismatch" + mvi.getFps(),
-            mVideoEditorHelper.checkRange(fps, mvi.getFps(), 10));
-
-        assertEquals("AudioType Mismatch ", audioCodecType, mvi.getAudioType());
-        assertEquals("Audio Sampling " + mvi.getAudioSamplingFrequency(),
-            audioSamplingFrequency, mvi.getAudioSamplingFrequency());
-        // PV SW AAC codec always returns number of channels as Stereo.
-        // So we do not assert for number of audio channels for AAC_LC
-        if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
-            assertEquals("Audio Channels " + mvi.getAudioChannels(), audioChannel,
-                mvi.getAudioChannels());
-        }
-    }
-
-    protected void validateAudioProperties(int audioCodecType, int duration,
-        int audioSamplingFrequency, int audioChannel, int audioBitrate,
-        AudioTrack aT) throws Exception {
-        assertEquals("AudioType Mismatch ", audioCodecType, aT.getAudioType());
-        assertTrue("Video duration Mismatch", mVideoEditorHelper.checkRange (
-            duration, aT.getDuration(), 10));
-        assertEquals("Audio Sampling " + aT.getAudioSamplingFrequency(),
-            audioSamplingFrequency, aT.getAudioSamplingFrequency());
-        // PV SW AAC codec always returns number of channels as Stereo.
-        // So we do not assert for number of audio channels for AAC_LC
-        if ( audioCodecType != MediaProperties.ACODEC_AAC_LC ) {
-            assertEquals("Audio Channels " + aT.getAudioChannels(), audioChannel,
-                aT.getAudioChannels());
-        }
-    }
-
-    protected void validateImageProperties(int aspectRatio, int fileType,
-        int width, int height, MediaImageItem mii)
-        throws Exception {
-        assertEquals("Aspect Ratio Mismatch", aspectRatio, mii.getAspectRatio());
-        assertEquals("File Type Mismatch", fileType, mii.getFileType());
-        assertEquals("Image height " + mii.getHeight(), height, mii.getHeight());
-        assertEquals("Image width " + mii.getWidth(), width, mii.getWidth());
-    }
-
-
-    /**
-     *To test Media Properties for file MPEG4 854 x 480
-     */
-    @LargeTest
-    public void testPropertiesMPEG4854_480() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
-        final int duration = 26933;
-        final int videoBitrate = 319000;
-        final int audioBitrate = 48000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 16000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
-        final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
-        final int width = 854;
-        final int height = MediaProperties.HEIGHT_480;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename,
-            MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-
-    /**
-     *To test Media Properties for file MPEG4 WVGA
-     */
-    @LargeTest
-    public void testPropertiesMPEGWVGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
-        final int duration = 26933;
-        final int videoBitrate = 384000;
-        final int audioBitrate = 12800;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
-        final int audioSamplingFrequency = 8000;
-        final int audioChannel = 1;
-        final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
-        final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
-        final int width = 800;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test media properties for MPEG4 720x480 (NTSC) + AAC file.
-     */
-    @LargeTest
-    public void testPropertiesMPEGNTSC() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
-        final int duration = 26866;
-        final int videoBitrate = 403000;
-        final int audioBitrate = 160000;
-        final int fps = 30;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 48000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
-        final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
-        final int width = 720;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file MPEG4 VGA
-     */
-    @LargeTest
-    public void testPropertiesMPEGVGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
-        final int duration = 26933;
-        final int videoBitrate = 533000;
-        final int audioBitrate = 128000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 48000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
-        final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
-        final int width = 640;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file MPEG4 QCIF
-     */
-    @LargeTest
-    public void testPropertiesMPEGQCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "MPEG4_SP_176x144_12fps_92kbps_AMRNB_8KHz_12.2kbps_m_0_27.3gp";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
-        final int fileType = MediaProperties.FILE_3GP;
-        final int videoCodecType = MediaProperties.VCODEC_MPEG4;
-        final int duration = 27000;
-        final int videoBitrate = 384000;
-        final int audioBitrate = 12200;
-        final int fps = 12;
-        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
-        final int audioSamplingFrequency = 8000;
-        final int audioChannel = 1;
-        final int videoProfile = MediaProperties.MPEG4Profile.MPEG4ProfileSimple;
-        final int videoLevel = MediaProperties.MPEG4Level.MPEG4Level1;
-        final int width = 176;
-        final int height = MediaProperties.HEIGHT_144;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To To test media properties for H263 176x144 (QCIF) + AAC (mono) file.
-     */
-    @LargeTest
-    public void testPropertiesH263QCIF() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_16kHz_32kbps_m_0_26.3gp";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
-        final int fileType = MediaProperties.FILE_3GP;
-        final int videoCodecType = MediaProperties.VCODEC_H263;
-        final int duration = 26933;
-        final int videoBitrate = 384000;
-        final int audioBitrate = 64000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 16000;
-        final int audioChannel = 1;
-        final int videoProfile = MediaProperties.H263Profile.H263ProfileBaseline;
-        final int videoLevel = MediaProperties.H263Level.H263Level10;
-        final int width = 176;
-        final int height = MediaProperties.HEIGHT_144;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file H264 VGA
-     */
-    @LargeTest
-    public void testPropertiesH264VGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int fileType = MediaProperties.FILE_3GP;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77600;
-        final int videoBitrate = 745000;
-        final int audioBitrate = 64000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 48000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 640;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file H264 NTSC
-     */
-    @LargeTest
-    public void testPropertiesH264NTSC() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_720x480_25fps_256kbps_AMRNB_8khz_12.2kbps_m_0_26.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 26880;
-        final int videoBitrate = 244000;
-        final int audioBitrate = 12200;
-        final int fps = 25;
-        final int audioCodecType = MediaProperties.ACODEC_AMRNB;
-        final int audioSamplingFrequency = 8000;
-        final int audioChannel = 1;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 720;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test media properties for H264 800x480 (WVGA) + AAC file.
-     */
-    @LargeTest
-    public void testPropertiesH264WVGA() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-              "H264_BP_800x480_15fps_512kbps_AACLC_24KHz_38Kbps_s_1_17.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77466;
-        final int videoBitrate = 528000;
-        final int audioBitrate = 38000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 24000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 800;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file H264 HD1280
-     */
-    @LargeTest
-    public void testPropertiesH264HD1280() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_1280x720_15fps_512kbps_AACLC_16khz_48kbps_s_1_17.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_16_9;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77600;
-        final int videoBitrate = 606000;
-        final int audioBitrate = 48000;
-        final int fps = 15;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 16000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 1280;
-        final int height = MediaProperties.HEIGHT_720;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test media properties for H264 1080x720 + AAC file
-     */
-    @LargeTest
-    public void testPropertiesH264HD1080WithAudio() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77500;
-        final int videoBitrate = 1190000;
-        final int audioBitrate = 64000;
-        final int fps = 10;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 44100;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 1080;
-        final int height = MediaProperties.HEIGHT_720;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for file WMV - Unsupported type
-     */
-    @LargeTest
-    public void testPropertiesWMVFile() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "WMV_V7_640x480_15fps_512Kbps_wma_V9_44khz_48Kbps_s_1_30.wmv";
-        boolean flagForException = false;
-        if (MediaProfileReader.getWMVEnable() == false) {
-            flagForException = true;
-        } else {
-            try {
-                new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
-                    MediaItem.RENDERING_MODE_BLACK_BORDER);
-            } catch (IllegalArgumentException e) {
-                flagForException = true;
-            } catch (IOException e) {
-                flagForException = true;
-            }
-        }
-        assertTrue("Media Properties for a WMV File -- Unsupported file type",
-            flagForException);
-    }
-
-    /**
-     *To test media properties for H.264 Main/Advanced profile.
-     */
-    @LargeTest
-    public void testPropertiesH264MainLineProfile() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH
-            + "H264_MP_960x720_25fps_800kbps_AACLC_48Khz_192Kbps_s_1_17.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int duration = 77500;
-        final int videoBitrate = 800000;
-        final int audioBitrate = 192000;
-        final int fps = 25;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 48000;
-        final int audioChannel = 2;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileMain;
-        final int videoLevel = MediaProperties.H264Level.H264Level31;
-        final int width = 960;
-        final int height = MediaProperties.HEIGHT_720;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-
-    }
-
-    /**
-     *To test Media Properties for non existing file.
-     */
-    @LargeTest
-    public void testPropertiesForNonExsitingFile() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH + "abc.3gp";
-        boolean flagForException = false;
-
-        try {
-            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
-                MediaItem.RENDERING_MODE_BLACK_BORDER);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        } catch (IOException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Properties for non exsisting file", flagForException);
-     }
-
-    /**
-     *To test Media Properties for file H264 HD1080
-     */
-    @LargeTest
-    public void testPropertiesH264HD1080WithoutAudio() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77366;
-        final int videoBitrate = 859000;
-        final int audioBitrate = 0;
-        final int fps = 30;
-        final int audioCodecType = -1;
-        final int audioSamplingFrequency = 0;
-        final int audioChannel = 0;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 1080;
-        final int height = MediaProperties.HEIGHT_720;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mvi = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", videoItemFilename, renderingMode);
-
-        validateVideoProperties(aspectRatio, fileType, videoCodecType, duration,
-            videoBitrate, fps, videoProfile, videoLevel, width, height, audioCodecType,
-            audioSamplingFrequency, audioChannel, audioBitrate, mvi);
-    }
-
-    /**
-     *To test Media Properties for Image file of JPEG Type
-     */
-    @LargeTest
-    public void testPropertiesVGAImage() throws Exception {
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemDuration = 10000;
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int fileType = MediaProperties.FILE_JPEG;
-        final int width = 640;
-        final int height = MediaProperties.HEIGHT_480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaImageItem mii = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
-            renderingMode);
-        validateImageProperties(aspectRatio, fileType, width, height, mii);
-    }
-
-    /**
-     *To test Media Properties for Image file of PNG Type
-     */
-    @LargeTest
-    public void testPropertiesPNG() throws Exception {
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.png";
-        final int imageItemDuration = 10000;
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int fileType = MediaProperties.FILE_PNG;
-        final int width = 640;
-        final int height = 480;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mii = mVideoEditorHelper.createMediaItem
-            (mVideoEditor, "m1", imageItemFilename, imageItemDuration,
-            renderingMode);
-        validateImageProperties(aspectRatio, fileType, width, height, mii);
-    }
-
-    /**
-     *To test Media Properties for file GIF - Unsupported type
-     */
-    @LargeTest
-    public void testPropertiesGIFFile() throws Exception {
-
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.gif";
-        final int imageItemDuration = 10000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        try {
-            new MediaImageItem(mVideoEditor, "m1", imageItemFilename,
-                imageItemDuration, renderingMode);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Properties for a GIF File -- Unsupported file type",
-            flagForException);
-    }
-
-    /**
-     *To test Media Properties for file Text file named as 3GP
-     */
-    @LargeTest
-    public void testPropertiesofDirtyFile() throws Exception {
-
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "Text_FileRenamedTo3gp.3gp";
-        boolean flagForException = false;
-
-        try {
-            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
-                MediaItem.RENDERING_MODE_BLACK_BORDER);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Properties for a Dirty  File ",
-            flagForException);
-    }
-
-    /**
-     *To test Media Properties for file name as NULL
-     */
-    @LargeTest
-    public void testPropertieNULLFile() throws Exception {
-        final String videoItemFilename = null;
-        boolean flagForException = false;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        try {
-            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
-                renderingMode);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Properties for NULL  File ",
-            flagForException);
-    }
-
-    /**
-     *To test Media Properties for file which is of type MPEG2
-     */
-    @LargeTest
-    public void testPropertiesMPEG2File() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "MPEG2_640x480_30fps_192kbps_1_5.mp4";
-        boolean flagForException = false;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        try {
-            new MediaVideoItem(mVideoEditor, "m1", videoItemFilename,
-                renderingMode);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Properties for a MPEG2 File --Unsupported file type",
-            flagForException);
-    }
-
-    /**
-     *To test Media Properties for file without Video only Audio
-     */
-    @LargeTest
-    public void testProperties3GPWithoutVideoMediaItem() throws Exception {
-        final String audioFilename = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        try {
-            new MediaVideoItem(mVideoEditor, "m1", audioFilename,
-                renderingMode);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Exception in Creaing Media Video item object without video",
-            flagForException);
-    }
-
-    /**
-     *To test media properties for Audio Track file. (No Video, AAC Audio)
-     */
-    @LargeTest
-    public void testProperties3GPWithoutVideoAudioTrack() throws Exception {
-
-        final String audioFilename = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        final int duration = 77554;
-        final int audioBitrate = 384000;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 44100;
-        final int audioChannel = 2;
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio
-            (mVideoEditor, "a1", audioFilename);
-
-        validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
-            audioChannel, audioBitrate, audioTrack);
-    }
-
-        /**
-     *To test media properties for Audio Track file. MP3 file
-     */
-    @LargeTest
-    public void testPropertiesMP3AudioTrack() throws Exception {
-
-        final String audioFilename = INPUT_FILE_PATH +
-            "MP3_48KHz_128kbps_s_1_17.mp3";
-        final int duration = 77640;
-        final int audioBitrate = 128000;
-        final int audioCodecType = MediaProperties.ACODEC_MP3;
-        final int audioSamplingFrequency = 48000;
-        final int audioChannel = 2;
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio
-            (mVideoEditor, "a1", audioFilename);
-
-        validateAudioProperties(audioCodecType, duration, audioSamplingFrequency,
-            audioChannel, audioBitrate, audioTrack);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java
deleted file mode 100644
index 6e520c3..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorAPITest.java
+++ /dev/null
@@ -1,2751 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.util.List;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.ExtractAudioWaveformProgressListener;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-
-import android.util.Log;
-import java.lang.annotation.Annotation;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class VideoEditorAPITest extends
-        ActivityInstrumentationTestCase<MediaFrameworkTest> {
-    private final String TAG = "VideoEditorTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private final String PROJECT_CLASS_NAME =
-        "android.media.videoeditor.VideoEditorImpl";
-    private VideoEditor mVideoEditor;
-    private VideoEditorHelper mVideoEditorHelper;
-
-    public VideoEditorAPITest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath = mVideoEditorHelper.
-            createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    /**
-     * To Test Creation of Media Video Item.
-     */
-    @LargeTest
-    public void testMediaVideoItem() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode =
-            MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-
-        assertTrue("Media Video ID",
-            mediaVideoItem1.getId().equals("mediaVideoItem1"));
-        assertTrue("Media Video Filename",
-            mediaVideoItem1.getFilename().equals(videoItemFileName));
-        assertEquals("Media Video Rendering Mode",
-            videoItemRenderingMode, mediaVideoItem1.getRenderingMode());
-        assertEquals("Media Video Item Duration", mediaVideoItem1.getDuration(),
-            mediaVideoItem1.getTimelineDuration());
-        assertEquals("Media Video Overlay", 0,
-            mediaVideoItem1.getAllOverlays().size());
-        assertEquals("Media Video Effect", 0,
-            mediaVideoItem1.getAllEffects().size());
-        assertNull("Media Video Begin transition",
-            mediaVideoItem1.getBeginTransition());
-        assertNull("Media Video End transition",
-            mediaVideoItem1.getEndTransition());
-        mediaVideoItem1.setExtractBoundaries(1000,11000);
-        boolean flagForException = false;
-        if (mediaVideoItem1.getDuration() !=
-            mediaVideoItem1.getTimelineDuration()) {
-            flagForException = true;
-        }
-        assertTrue("Media Video Item Duration & Timeline are same",
-            flagForException );
-    }
-
-    /**
-     * To test creation of Media Video Item with Set Extract Boundaries With Get
-     * the Begin and End Time.
-     */
-    @LargeTest
-    public void testMediaVideoItemExtractBoundaries() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        mediaVideoItem1.setExtractBoundaries(1000, 11000);
-        assertEquals("Media Item Duration = StoryBoard Duration",
-            mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-        try {
-            mediaVideoItem1.setExtractBoundaries(0, 100000000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Set Extract with Invalid Values endTime > FileDuration",
-            flagForException);
-
-        flagForException = false;
-        try {
-            mediaVideoItem1.setExtractBoundaries(100000000, 11000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Set Extract with Invalid Values startTime > endTime",
-            flagForException);
-
-        flagForException = false;
-        try {
-            mediaVideoItem1.setExtractBoundaries(0, 0);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Set Extract with Invalid Values startTime = endTime",
-            flagForException);
-
-        mediaVideoItem1.setExtractBoundaries(1000, 10000);
-        assertTrue("Media Item Duration is still the same",
-            (mediaVideoItem1.getTimelineDuration() ==
-            (mediaVideoItem1.getBoundaryEndTime()-
-            mediaVideoItem1.getBoundaryBeginTime())) ? true : false);
-
-        mediaVideoItem1.setExtractBoundaries(1,mediaVideoItem1.getDuration()-1);
-        assertEquals("Media Item Start Time", 1,
-            mediaVideoItem1.getBoundaryBeginTime());
-        assertEquals("Media Item End Time", (mediaVideoItem1.getDuration() - 1),
-            mediaVideoItem1.getBoundaryEndTime());
-
-        mediaVideoItem1.setExtractBoundaries(1, mediaVideoItem1.getDuration());
-        assertEquals("Media Item Duration = StoryBoard Duration",
-            mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-
-        mediaVideoItem1.setExtractBoundaries(0,mediaVideoItem1.getDuration()/2);
-        assertEquals("Media Item Duration = StoryBoard Duration",
-            mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-
-        mediaVideoItem1.setExtractBoundaries(0, -1);
-        assertEquals("Media Item Duration = StoryBoard Duration",
-            mediaVideoItem1.getTimelineDuration(), mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test creation of Media Video Item with Set and Get rendering Mode
-     */
-    @LargeTest
-    public void testMediaVideoItemRenderingModes() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode= MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_CROPPING);
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_CROPPING,
-            mediaVideoItem1.getRenderingMode());
-        try {
-            mediaVideoItem1.setRenderingMode(
-                MediaItem.RENDERING_MODE_CROPPING + 911);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Item Invalid rendering Mode", flagForException);
-        flagForException = false;
-        try {
-            mediaVideoItem1.setRenderingMode(
-                MediaItem.RENDERING_MODE_BLACK_BORDER - 11);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Item Invalid rendering Mode", flagForException);
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_CROPPING,
-            mediaVideoItem1.getRenderingMode());
-        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_STRETCH,
-            mediaVideoItem1.getRenderingMode());
-    }
-
-
-    /**
-     * To Test the Media Video API : Set Audio Volume, Get Audio Volume and Mute
-     */
-    @LargeTest
-    public void testMediaVideoItemAudioFeatures() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        mediaVideoItem1.setVolume(77);
-        assertEquals("Updated Volume is 77", 77, mediaVideoItem1.getVolume());
-
-        mediaVideoItem1.setMute(true);
-        assertTrue("Audio must be Muted", mediaVideoItem1.isMuted());
-
-        mediaVideoItem1.setVolume(78);
-        assertEquals("Updated Volume is 78", 78, mediaVideoItem1.getVolume());
-        assertTrue("Audio must be Muted", mediaVideoItem1.isMuted());
-
-        try {
-            mediaVideoItem1.setVolume(1000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid Set Volume", flagForException);
-
-        mediaVideoItem1.setMute(false);
-        assertFalse("Audio must be Un-Muted", mediaVideoItem1.isMuted());
-
-        mediaVideoItem1.setVolume(0);
-        assertFalse("Audio must be Un-Muted", mediaVideoItem1.isMuted());
-
-        flagForException = false;
-        try {
-            mediaVideoItem1.setVolume(-1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid Set Volume", flagForException);
-
-        mediaVideoItem1.setVolume(100);
-        assertEquals("MediaItem Volume", 100, mediaVideoItem1.getVolume());
-        try {
-            mediaVideoItem1.setVolume(101);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid Set Volume", flagForException);
-        assertEquals("MediaItem Volume", 100, mediaVideoItem1.getVolume());
-    }
-
-    /**
-     * To Test the Media Video API : GetWaveFormData and
-     * extractAudioWaveFormData
-     */
-
-    @LargeTest
-    public void testMediaVideoItemGetWaveformData() throws Exception {
-
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        assertNull("WaveForm data", mediaVideoItem1.getWaveformData());
-        final int[] progressWaveform = new int[105];
-
-        mediaVideoItem1.extractAudioWaveform(new
-            ExtractAudioWaveformProgressListener() {
-                int i = 0;
-                public void onProgress(int progress) {
-                    Log.i("WaveformData","progress=" +progress);
-                    progressWaveform[i++] = progress;
-                }
-            });
-        assertTrue("Progress of WaveForm data", mVideoEditorHelper
-            .checkProgressCBValues(progressWaveform));
-        assertNotNull("WaveForm data", mediaVideoItem1.getWaveformData());
-        assertTrue("WaveForm Frame Duration",
-            (mediaVideoItem1.getWaveformData().getFrameDuration() > 0?
-            true : false));
-        assertTrue("WaveForm Frame Count",
-            (mediaVideoItem1.getWaveformData().getFramesCount() > 0 ?
-            true : false));
-        assertTrue("WaveForm Gain",
-            (mediaVideoItem1.getWaveformData().getFrameGains().length > 0 ?
-            true : false));
-
-    }
-
-    /**
-     * To Test the Media Video API : Get Effect, GetAllEffects, remove Effect
-     */
-
-    @LargeTest
-    public void testMediaVideoItemEffect() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem1 = mVideoEditorHelper.
-            createMediaItem(mVideoEditor, "mediaVideoItem1", videoItemFileName,
-            videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        assertTrue("Effect List Size",
-            (mediaVideoItem1.getAllEffects().size() == 0) ? true : false);
-        assertNull("Effect Item by ID", mediaVideoItem1.getEffect("xyx"));
-
-        final EffectColor effectColor = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "Effecton MVi1", 0, 4000, EffectColor.TYPE_GRADIENT,
-            EffectColor.GRAY);
-        mediaVideoItem1.addEffect(effectColor);
-
-        assertTrue("Effect List Size", (mediaVideoItem1.
-            getAllEffects().size() == 1) ? true : false);
-        assertEquals("Effect Item by Valid ID", effectColor,
-            mediaVideoItem1.getEffect(effectColor.getId()));
-        assertNull("Effect Item by Invalid ID",
-            mediaVideoItem1.getEffect("xyz"));
-        assertNull("Effect Item by Invalid ID",
-            mediaVideoItem1.removeEffect("effectId"));
-        assertTrue("Effect List Size",
-            (mediaVideoItem1.getAllEffects().size() == 1) ? true : false);
-        assertEquals("Effect Removed", effectColor,
-            mediaVideoItem1.removeEffect(effectColor.getId()));
-        assertTrue("Effect List Size",
-            (mediaVideoItem1.getAllEffects().size() == 0) ? true : false);
-        assertNull("Effect Item by ID", mediaVideoItem1.getEffect("effectId"));
-    }
-
-    /**
-     * To Test the Media Video API : Get Before and after transition
-     */
-
-    @LargeTest
-    public void testMediaVideoItemTransitions() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        assertNull("Begin Transition", mediaVideoItem1.getBeginTransition());
-        assertNull("End Transition", mediaVideoItem1.getEndTransition());
-
-        TransitionFadeBlack transition1 =
-            mVideoEditorHelper.createTFadeBlack("transition1", mediaVideoItem1,
-            null, 0, Transition.BEHAVIOR_SPEED_UP);
-        mVideoEditor.addTransition(transition1);
-        assertEquals("Begin transition", transition1,
-            mediaVideoItem1.getEndTransition());
-
-        assertNotNull("End Transition", mediaVideoItem1.getEndTransition());
-        assertTrue(mediaVideoItem1.
-            getEndTransition().getId().equals(transition1.getId()));
-        assertTrue(mediaVideoItem1.getEndTransition().getDuration() ==
-            transition1.getDuration() ? true : false);
-        assertTrue(mediaVideoItem1.getEndTransition().getBehavior() ==
-            transition1.getBehavior() ? true : false);
-
-        TransitionFadeBlack transition2 = mVideoEditorHelper.createTFadeBlack(
-            "transition2", null,mediaVideoItem1, 0, Transition.BEHAVIOR_LINEAR);
-        mVideoEditor.addTransition(transition2);
-        assertNotNull("Begin transition", mediaVideoItem1.getBeginTransition());
-        assertEquals("End Transition", transition2,
-            mediaVideoItem1.getBeginTransition());
-        assertTrue(mediaVideoItem1.
-            getBeginTransition().getId().equals(transition2.getId()));
-        assertTrue(mediaVideoItem1. getBeginTransition().getDuration() ==
-            transition2.getDuration() ? true : false);
-        assertTrue(mediaVideoItem1.getBeginTransition().getBehavior() ==
-            transition2.getBehavior() ? true : false);
-    }
-
-    /**
-     * To Test the Media Video API : Get All Overlay, Get Overlay and remove Overlay
-     *
-     */
-
-    @LargeTest
-    public void testMediaVideoItemOverlays() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String overlayItemFileName = INPUT_FILE_PATH +
-            "IMG_176x144_Overlay1.png";
-        final int videoItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        assertTrue("Overlay List Size",
-            (mediaVideoItem1.getAllOverlays().size() == 0) ? true : false);
-        assertNull("Overlay Item by ID", mediaVideoItem1.getOverlay("xyz"));
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayItemFileName,
-            176, 144);
-        final OverlayFrame overlayFrame = mVideoEditorHelper.createOverlay(
-            mediaVideoItem1, "overlayId", mBitmap, 5000, 5000);
-        mediaVideoItem1.addOverlay(overlayFrame);
-
-        assertTrue("Overlay List Size",
-            (mediaVideoItem1.getAllOverlays().size() == 1) ? true : false);
-        assertEquals("Overlay Item by Valid ID", overlayFrame, mediaVideoItem1
-            .getOverlay(overlayFrame.getId()));
-        assertNull("Overlay Item by Invalid ID",
-            mediaVideoItem1.getOverlay("xyz"));
-        assertNull("Overlay Item by Invalid ID",
-            mediaVideoItem1.removeOverlay("xyz"));
-        assertTrue("Overlay List Size",
-            (mediaVideoItem1.getAllOverlays().size() == 1) ? true : false);
-        assertEquals("Overlay Removed", overlayFrame,
-            mediaVideoItem1.removeOverlay(overlayFrame.getId()));
-        assertTrue("Overlay List Size",
-            (mediaVideoItem1.getAllOverlays().size() == 0) ? true : false);
-        assertNull("Overlay Item by ID",mediaVideoItem1.getOverlay("effectId"));
-    }
-
-    /**
-     * To Test Creation of Media Image Item.
-     */
-    @LargeTest
-    public void testMediaImageItem() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-                imageItemFileName, 5000, imageItemRenderingMode);
-        assertTrue("Media Image ID",
-            mediaImageItem1.getId().equals("mediaImageItem1"));
-        assertTrue("Media IMage Filename",
-            mediaImageItem1.getFilename().equals(imageItemFileName));
-        assertEquals("Media Image Rendering Mode",
-            imageItemRenderingMode, mediaImageItem1.getRenderingMode());
-        assertEquals("Media Image Item Duration", mediaImageItem1.getDuration(),
-            mediaImageItem1.getTimelineDuration());
-        assertEquals("Media Image Overlay", 0,
-            mediaImageItem1.getAllOverlays().size());
-        assertEquals("Media Image Effect", 0,
-            mediaImageItem1.getAllEffects().size());
-        assertNull("Media Image Begin transition",
-            mediaImageItem1.getBeginTransition());
-        assertNull("Media Image End transition",
-            mediaImageItem1.getEndTransition());
-        assertEquals("Media Image Scaled Height", MediaProperties.HEIGHT_720,
-            mediaImageItem1.getScaledHeight());
-        assertEquals("Media Image Scaled Width", 960,
-            mediaImageItem1.getScaledWidth());
-        assertEquals("Media Image Aspect Ratio", MediaProperties.ASPECT_RATIO_4_3,
-            mediaImageItem1.getAspectRatio());
-        assertNotNull("Media Image Thumbnail",
-            mediaImageItem1.getThumbnail(960, MediaProperties.HEIGHT_720, 2000));
-    }
-
-    /**
-     * To Test the Media Image API : Get and Set rendering Mode
-     */
-    @LargeTest
-    public void testMediaImageItemRenderingModes() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, imageItemRenderingMode, 5000);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        mediaImageItem1.setRenderingMode(MediaItem.RENDERING_MODE_CROPPING);
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_CROPPING, mediaImageItem1.getRenderingMode());
-        try {
-            mediaImageItem1.setRenderingMode(
-                MediaItem.RENDERING_MODE_CROPPING + 911);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Item Invalid rendering Mode", flagForException);
-
-        flagForException = false;
-        try {
-            mediaImageItem1.setRenderingMode(
-                MediaItem.RENDERING_MODE_BLACK_BORDER - 11);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Media Item Invalid rendering Mode", flagForException);
-
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_CROPPING,
-            mediaImageItem1.getRenderingMode());
-        mediaImageItem1.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
-        assertEquals("MediaVideo Item rendering Mode",
-            MediaItem.RENDERING_MODE_STRETCH,
-            mediaImageItem1.getRenderingMode());
-    }
-
-    /**
-     * To Test the Media Image API : GetHeight and GetWidth
-     */
-    @LargeTest
-    public void testMediaImageItemHeightWidth() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, imageItemRenderingMode, 5000);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        assertEquals("Image Height = Image Scaled Height",
-            mediaImageItem1.getScaledHeight(), mediaImageItem1.getHeight());
-        assertEquals("Image Width = Image Scaled Width",
-            mediaImageItem1.getScaledWidth(), mediaImageItem1.getWidth());
-    }
-
-
-
-/**    This Test Case can be removed as this is already checked in TC 010 */
-    /**
-     * To Test the Media Image API : Scaled Height and Scaled GetWidth
-     */
-    @LargeTest
-    public void testMediaImageItemScaledHeightWidth() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, imageItemRenderingMode, 5000);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        assertNotSame("Image Height = Image Scaled Height",
-            mediaImageItem1.getScaledHeight(), mediaImageItem1.getHeight());
-        assertNotSame("Image Width = Image Scaled Width",
-            mediaImageItem1.getScaledWidth(), mediaImageItem1.getWidth());
-    }
-
-    /**
-     * To Test the Media Image API : Get Effect, GetAllEffects, remove Effect
-     */
-
-    @LargeTest
-    public void testMediaImageItemEffect() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        assertTrue("Effect List Size",
-            (mediaImageItem1.getAllEffects().size() == 0) ? true : false);
-        assertNull("Effect Item by ID", mediaImageItem1.getEffect("xyx"));
-
-        final EffectColor effectColor =
-            mVideoEditorHelper.createEffectItem(mediaImageItem1,
-            "Effecton MVi1", 0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
-        mediaImageItem1.addEffect(effectColor);
-
-        assertTrue("Effect List Size",
-            (mediaImageItem1.getAllEffects().size() == 1) ? true : false);
-        assertEquals("Effect Item by Valid ID",
-            effectColor, mediaImageItem1.getEffect(effectColor.getId()));
-        assertNull("Effect Item by Invalid ID",
-            mediaImageItem1.getEffect("xyz"));
-        assertNull("Effect Item by Invalid ID",
-            mediaImageItem1.removeEffect("effectId"));
-        assertTrue("Effect List Size",
-            (mediaImageItem1.getAllEffects().size() == 1) ? true : false);
-        assertEquals("Effect Removed", effectColor,
-            mediaImageItem1.removeEffect(effectColor.getId()));
-        assertTrue("Effect List Size",
-            (mediaImageItem1.getAllEffects().size() == 0) ? true : false);
-        assertNull("Effect Item by ID", mediaImageItem1.getEffect("effectId"));
-    }
-
-    /**
-     * To Test the Media Image API : Get Before and after transition
-     */
-
-    @LargeTest
-    public void testMediaImageItemTransitions() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        assertNull("Begin Transition", mediaImageItem1.getBeginTransition());
-        assertNull("End Transition", mediaImageItem1.getEndTransition());
-
-        TransitionFadeBlack transition1 =
-            mVideoEditorHelper.createTFadeBlack("transition1", mediaImageItem1,
-            null, 0, Transition.BEHAVIOR_SPEED_UP);
-        mVideoEditor.addTransition(transition1);
-
-        assertEquals("Begin transition", transition1,
-            mediaImageItem1.getEndTransition());
-        assertNotNull("End Transition", mediaImageItem1.getEndTransition());
-        assertTrue(mediaImageItem1.getEndTransition().getId().equals
-            (transition1.getId()));
-        assertTrue(mediaImageItem1.getEndTransition().getDuration() ==
-            transition1.getDuration() ? true : false);
-        assertTrue(mediaImageItem1.getEndTransition().getBehavior() ==
-            transition1.getBehavior() ? true : false);
-
-        TransitionFadeBlack transition2 = mVideoEditorHelper.createTFadeBlack(
-            "transition2",null, mediaImageItem1, 0, Transition.BEHAVIOR_SPEED_UP);
-        mVideoEditor.addTransition(transition2);
-
-        assertNotNull("Begin transition", mediaImageItem1.getBeginTransition());
-        assertEquals("End Transition", transition2,
-            mediaImageItem1.getBeginTransition());
-        assertTrue(mediaImageItem1.getBeginTransition().getId().equals(
-            transition2.getId()));
-        assertTrue(mediaImageItem1.getBeginTransition().getDuration() ==
-            transition2.getDuration() ? true : false);
-        assertTrue(mediaImageItem1.getBeginTransition().getBehavior() ==
-            transition2.getBehavior() ? true : false);
-    }
-
-    /**
-     * To Test the Media Image API : Get All Overlay, Get Overlay and remove
-     * Overlay
-     */
-
-    @LargeTest
-    public void testMediaImageItemOverlays() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String overlayItemFileName = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, 12000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        assertTrue("Overlay List Size",
-            (mediaImageItem1.getAllOverlays().size() == 0) ? true : false);
-        assertNull("Overlay Item by ID", mediaImageItem1.getOverlay("xyz"));
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayItemFileName,
-            640, 480);
-        final OverlayFrame overlayFrame =
-            mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId",
-            mBitmap, 5000, 5000);
-        mediaImageItem1.addOverlay(overlayFrame);
-
-        assertTrue("Overlay List Size",
-            (mediaImageItem1.getAllOverlays().size() == 1) ? true : false);
-        assertEquals("Overlay Item by Valid ID", overlayFrame, mediaImageItem1
-            .getOverlay(overlayFrame.getId()));
-        assertNull("Overlay Item by Invalid ID",
-            mediaImageItem1.getOverlay("xyz"));
-        assertNull("Remove Overlay Item by Invalid ID",
-            mediaImageItem1.removeOverlay("xyz"));
-        assertTrue("Overlay List Size",
-            (mediaImageItem1.getAllOverlays().size() == 1) ? true : false);
-        assertEquals("Overlay Removed",
-            overlayFrame, mediaImageItem1.removeOverlay(overlayFrame.getId()));
-        assertTrue("Overlay List Size",
-            (mediaImageItem1.getAllOverlays().size() == 0) ? true : false);
-        assertNull("Overlay Item by ID",
-            mediaImageItem1.getOverlay("effectId"));
-    }
-
-    /**
-     * To test creation of Audio Track
-     */
-
-    @LargeTest
-    public void testAudioTrack() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        assertEquals("Audio Track Item Duration", audioTrack.getDuration(),
-            audioTrack.getTimelineDuration());
-        assertEquals("Audio Track Start Time", 0, audioTrack.getStartTime());
-        assertFalse("Audio Track is Looping", audioTrack.isLooping());
-        audioTrack.getVolume();
-        assertFalse("Audio Track Ducking is Disabled",
-            audioTrack.isDuckingEnabled());
-        assertTrue("Audio Track Filename",
-            audioTrack.getFilename().equals(audioFileName));
-         assertEquals("Audio Ducking Threshold", 0,
-            audioTrack.getDuckingThreshhold());
-         assertFalse("Audio Track Mute", audioTrack.isMuted());
-         audioTrack.getDuckedTrackVolume();
-    }
-
-    /**
-     * To test creation of Audio Track with set extract boundaries
-     */
-    @LargeTest
-    public void testAudioTrackExtractBoundaries() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        audioTrack.setExtractBoundaries(1000, 5000);
-        assertEquals("Audio Track Start time", 1000,
-            audioTrack.getBoundaryBeginTime());
-        assertEquals("Audio Track End time", 5000,
-            audioTrack.getBoundaryEndTime());
-        try {
-            audioTrack.setExtractBoundaries(0, 100000000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Audio Track With endTime > FileDuration", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.setExtractBoundaries(100000000, 5000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Audio Track With startTime > FileDuration",
-            flagForException);
-        flagForException = false;
-        try {
-            audioTrack.setExtractBoundaries(0, 0);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        /* This is under discussion.  Hence, checked for False */
-        assertFalse("Audio Track With startTime = endTime", flagForException);
-        assertEquals("Audio Track Start time", 0,
-            audioTrack.getBoundaryBeginTime());
-        assertEquals("Audio Track End time", 0,
-            audioTrack.getBoundaryEndTime());
-        assertEquals("Audio Track Start time",0,
-            audioTrack.getBoundaryBeginTime());
-        assertEquals("Audio Track End time", (audioTrack.getTimelineDuration()),
-            audioTrack.getBoundaryEndTime());
-        audioTrack.setExtractBoundaries(0, audioTrack.getDuration() / 2);
-        assertEquals("Audio Track Start time",0,
-            audioTrack.getBoundaryBeginTime());
-        assertEquals("Audio Track End time", (audioTrack.getDuration() / 2),
-            audioTrack.getBoundaryEndTime());
-        audioTrack.setExtractBoundaries(1, audioTrack.getDuration() - 1);
-        assertEquals("Audio Track Start time", 1,
-            audioTrack.getBoundaryBeginTime());
-        assertEquals("Audio Track End time", (audioTrack.getDuration() - 1),
-            audioTrack.getBoundaryEndTime());
-
-        flagForException = false;
-        try {
-                audioTrack.setExtractBoundaries(0, -1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue ("Audio Track end time < 0",flagForException);
-    }
-
-    /**
-     * To test creation of Audio Track with set Start Time and Get Time
-     */
-    @LargeTest
-    public void testAudioTrackSetGetTime() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-        /** set StartTime API is removed and start time is always 0 */
-        assertEquals("Audio Track Start Time", 0, audioTrack.getStartTime());
-    }
-
-    /**
-     * To Test the Audio Track API: Enable Ducking
-     */
-    @LargeTest
-    public void testAudioTrackEnableDucking() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        assertFalse("Audio Ducking Disabled by default",
-            audioTrack.isDuckingEnabled());
-        audioTrack.enableDucking(45, 70);
-        assertTrue("Audio Ducking Enabled", audioTrack.isDuckingEnabled());
-        assertEquals("Audio Ducking Threshold", 45,
-            audioTrack.getDuckingThreshhold());
-        assertEquals("Audio Ducking Volume", 70,
-            audioTrack.getDuckedTrackVolume());
-        audioTrack.enableDucking(85, 70);
-        assertEquals("Audio Ducking Threshold", 85,
-            audioTrack.getDuckingThreshhold());
-        assertEquals("Audio Ducking Volume", 70,
-            audioTrack.getDuckedTrackVolume());
-        try {
-            audioTrack.enableDucking(91, 70);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Enable ducking threshold > 90", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.enableDucking(90, 101);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Enable ducking volume > 100", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.enableDucking(91, 101);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Enable ducking volume > 100 and threshold > 91",
-            flagForException);
-        flagForException = false;
-        try {
-            audioTrack.enableDucking(-1, 100);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Enable ducking threshold < 0", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.enableDucking(1, -1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Enable ducking lowVolume < 0", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.enableDucking(0, 50);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertFalse("Enable ducking threshold = 0", flagForException);
-    }
-
-    /**
-     * To Test the Audio Track API: Looping
-     */
-    @LargeTest
-    public void testAudioTrackLooping() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-        assertFalse("Audio Looping", audioTrack.isLooping());
-        audioTrack.enableLoop();
-        assertTrue("Audio Looping", audioTrack.isLooping());
-        audioTrack.disableLoop();
-        assertFalse("Audio Looping", audioTrack.isLooping());
-    }
-
-    /**
-     * To Test the Audio Track API:Extract waveform data
-     */
-
-    @LargeTest
-    public void testAudioTrackWaveFormData() throws Exception {
-        /** Image item is added as dummy as Audio track cannot be added without
-         * a media item in the story board
-         */
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-
-        mVideoEditor.addAudioTrack(audioTrack);
-        assertNull("WaveForm data", audioTrack.getWaveformData());
-
-        final int[] progressUpdate = new int[105];
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            int i = 0;
-            public void onProgress(Object item, int action, int progress) {
-                progressUpdate[i++] = progress;
-            }
-        });
-
-        final int[] progressWaveform = new int[105];
-
-        audioTrack.extractAudioWaveform(
-            new ExtractAudioWaveformProgressListener() {
-                int i = 0;
-                public void onProgress(int progress) {
-                    Log.i("AudioWaveformData","progress=" +progress);
-                    progressWaveform[i++] = progress;
-            }
-        });
-        assertTrue("Progress of WaveForm data", mVideoEditorHelper
-            .checkProgressCBValues(progressWaveform));
-        assertNotNull("WaveForm data", audioTrack.getWaveformData());
-        assertTrue("WaveForm Frame Duration",
-            (audioTrack.getWaveformData().getFrameDuration() > 0 ?
-            true : false));
-        assertTrue("WaveForm Frame Count",
-            (audioTrack.getWaveformData().getFramesCount() > 0 ? true : false));
-        assertTrue("WaveForm Gain",
-            (audioTrack.getWaveformData().getFrameGains().length > 0 ?
-            true : false));
-    }
-
-    /**
-     * To Test the Audio Track API: Mute
-     */
-    @LargeTest
-    public void testAudioTrackMute() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        assertFalse("Audio Track UnMute", audioTrack.isMuted());
-        audioTrack.setMute(true);
-        assertTrue("Audio Track Mute", audioTrack.isMuted());
-        audioTrack.setMute(false);
-        assertFalse("Audio Track UnMute", audioTrack.isMuted());
-    }
-
-    /**
-     * To Test the Audio Track API: Get Volume and Set Volume
-     */
-    @LargeTest
-    public void testAudioTrackGetSetVolume() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        audioTrack.setVolume(0);
-        assertEquals("Audio Volume", 0, audioTrack.getVolume());
-        assertFalse("Audio Track UnMute", audioTrack.isMuted());
-        audioTrack.setVolume(45);
-        assertEquals("Audio Volume", 45, audioTrack.getVolume());
-        assertFalse("Audio Track UnMute", audioTrack.isMuted());
-        try {
-            audioTrack.setVolume(-1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Volume = -1", flagForException);
-        assertEquals("Audio Volume", 45, audioTrack.getVolume());
-        flagForException = false;
-        try {
-            audioTrack.setVolume(101);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Volume = 101", flagForException);
-        flagForException = false;
-        try {
-            audioTrack.setVolume(1000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Volume = 10000", flagForException);
-        assertEquals("Audio Volume", 45, audioTrack.getVolume());
-    }
-
-    /**
-     * To test Effect Color.
-     */
-    @LargeTest
-    public void testAllEffects() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect1", 1000, 1000, EffectColor.TYPE_COLOR,
-            EffectColor.PINK);
-        mediaVideoItem1.addEffect(effectColor1);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor1.getMediaItem());
-        assertTrue("Effect Id", effectColor1.getId().equals("effect1"));
-        assertEquals("Effect StartTime", 1000, effectColor1.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor1.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_COLOR,
-            effectColor1.getType());
-        assertEquals("Effect Color", EffectColor.PINK, effectColor1.getColor());
-
-        final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect2", 2000, 1000, EffectColor.TYPE_COLOR,
-            EffectColor.GRAY);
-        mediaVideoItem1.addEffect(effectColor2);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor2.getMediaItem());
-        assertTrue("Effect Id", effectColor2.getId().equals("effect2"));
-        assertEquals("Effect StartTime", 2000, effectColor2.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor2.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_COLOR,
-            effectColor2.getType());
-        assertEquals("Effect Color", EffectColor.GRAY, effectColor2.getColor());
-
-        final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect3", 3000, 1000, EffectColor.TYPE_COLOR,
-            EffectColor.GREEN);
-        mediaVideoItem1.addEffect(effectColor3);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor3.getMediaItem());
-        assertTrue("Effect Id", effectColor3.getId().equals("effect3"));
-        assertEquals("Effect StartTime", 3000, effectColor3.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor3.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_COLOR,
-            effectColor3.getType());
-        assertEquals("Effect Color", EffectColor.GREEN, effectColor3.getColor());
-
-        final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect4", 4000, 1000, EffectColor.TYPE_GRADIENT,
-            EffectColor.PINK);
-        mediaVideoItem1.addEffect(effectColor4);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor4.getMediaItem());
-        assertTrue("Effect Id", effectColor4.getId().equals("effect4"));
-        assertEquals("Effect StartTime", 4000, effectColor4.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor4.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_GRADIENT,
-            effectColor4.getType());
-        assertEquals("Effect Color", EffectColor.PINK, effectColor4.getColor());
-
-        final EffectColor effectColor5 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect5", 5000, 1000,
-            EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
-        mediaVideoItem1.addEffect(effectColor5);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor5.getMediaItem());
-        assertTrue("Effect Id", effectColor5.getId().equals("effect5"));
-        assertEquals("Effect StartTime", 5000, effectColor5.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor5.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_GRADIENT,
-            effectColor5.getType());
-        assertEquals("Effect Color", EffectColor.GRAY, effectColor5.getColor());
-
-        final EffectColor effectColor6 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect6", 6000, 1000,
-            EffectColor.TYPE_GRADIENT, EffectColor.GREEN);
-        mediaVideoItem1.addEffect(effectColor6);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor6.getMediaItem());
-        assertTrue("Effect Id", effectColor6.getId().equals("effect6"));
-        assertEquals("Effect StartTime", 6000, effectColor6.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor6.getDuration());
-        assertEquals("Effect Type",
-            EffectColor.TYPE_GRADIENT, effectColor6.getType());
-        assertEquals("Effect Color",
-            EffectColor.GREEN, effectColor6.getColor());
-
-        final EffectColor effectColor7 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect7", 7000, 1000,
-            EffectColor.TYPE_FIFTIES, 0);
-        mediaVideoItem1.addEffect(effectColor7);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor7.getMediaItem());
-        assertTrue("Effect Id", effectColor7.getId().equals("effect7"));
-        assertEquals("Effect StartTime", 7000, effectColor7.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor7.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_FIFTIES,
-            effectColor7.getType());
-        assertEquals("Effect Color", -1, effectColor7.getColor());
-
-        final EffectColor effectColor8 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect8", 8000, 1000, EffectColor.TYPE_SEPIA, 0);
-        mediaVideoItem1.addEffect(effectColor8);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor8.getMediaItem());
-        assertTrue("Effect Id", effectColor8.getId().equals("effect8"));
-        assertEquals("Effect StartTime", 8000, effectColor8.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor8.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_SEPIA,
-            effectColor8.getType());
-        assertEquals("Effect Color", -1, effectColor8.getColor());
-
-        final EffectColor effectColor9 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect9", 9000, 1000,
-            EffectColor.TYPE_NEGATIVE, 0);
-        mediaVideoItem1.addEffect(effectColor9);
-
-        assertEquals("Associated Media Item", mediaVideoItem1,
-            effectColor9.getMediaItem());
-        assertTrue("Effect Id", effectColor9.getId().equals("effect9"));
-        assertEquals("Effect StartTime", 9000, effectColor9.getStartTime());
-        assertEquals("Effect EndTime", 1000, effectColor9.getDuration());
-        assertEquals("Effect Type", EffectColor.TYPE_NEGATIVE,
-            effectColor9.getType());
-        assertEquals("Effect Color", -1, effectColor9.getColor());
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect9",
-                9000, 1000, EffectColor.TYPE_COLOR - 1, 0);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect type Invalid", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect9",
-                9000, 1000, EffectColor.TYPE_FIFTIES + 1, 0);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect type Invalid", flagForException);
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect10",
-                10000, 1000, EffectColor.TYPE_FIFTIES +
-                EffectColor.TYPE_GRADIENT, 0);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect type Invalid", flagForException);
-    }
-
-    /**
-     * To test Effect Color : Set duration and Get Duration
-     */
-    @LargeTest
-    public void testEffectSetgetDuration() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
-            mediaVideoItem1, "effect1", 1000, 2000,
-            EffectColor.TYPE_COLOR, EffectColor.PINK);
-        mediaVideoItem1.addEffect(effectColor1);
-
-        effectColor1.setDuration(5000);
-        assertEquals("Updated Effect Duration", 5000,
-            effectColor1.getDuration());
-        try {
-            effectColor1.setDuration(mediaVideoItem1.getDuration() + 1000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect Color duration > mediaVideoItemDuration",
-            flagForException);
-        assertEquals("Effect Duration", 5000, effectColor1.getDuration());
-        flagForException = false;
-        try {
-            effectColor1.setDuration(-1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect Color duration = -1", flagForException);
-    }
-
-    /**
-     * To test Effect Color : UNDEFINED color param value
-     */
-    @LargeTest
-    public void testEffectUndefinedColorParam() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        try{
-        mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1", 1000,
-            2000, EffectColor.TYPE_COLOR, 0xabcdabcd);
-        }catch (IllegalArgumentException e){
-            flagForException = true;
-        }
-        assertTrue("Invalid Effect added",flagForException);
-    }
-
-    /**
-     * To test Effect Color : with Invalid StartTime and Duration
-     */
-    @LargeTest
-    public void testEffectInvalidStartTimeAndDuration() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp";
-        final int videoItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-            videoItemFileName, videoItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1",
-                400000000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect with invalid StartTime", flagForException);
-
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1", -1,
-                2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect with invalid StartTime", flagForException);
-
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effect1",
-                2000, -1, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect with invalid Duration", flagForException);
-    }
-
-
-    /** Test cases 29, 30, 31, 32 and 33 are removed */
-
-
-    /**
-     * To test Effect : with NULL Media Item
-     */
-    @LargeTest
-    public void testEffectNullMediaItem() throws Exception {
-        boolean flagForException = false;
-        try {
-            mVideoEditorHelper.createEffectItem(null, "effect1", 1000, 4000,
-                EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Effect with null MediaItem", flagForException);
-    }
-
-    /**
-     * To test Effect : KenBurn Effect
-     */
-    @LargeTest
-    public void testEffectKenBurn() throws Exception {
-        // Test ken burn effect using a JPEG file.
-        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.jpg",
-         "mediaImageItem1");
-
-        // Test ken burn effect using a PNG file
-        testEffectKenBurn(INPUT_FILE_PATH + "IMG_640x480.png",
-         "mediaImageItem2");
-    }
-
-    private void testEffectKenBurn(final String imageItemFileName,
-     final String MediaId) throws Exception {
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, MediaId,
-            imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
-            (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
-            (mediaImageItem.getWidth() / 2));
-        final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
-            mediaImageItem.getHeight());
-
-        final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
-            mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
-
-        assertNotNull("EffectKenBurns: " + imageItemFileName,
-            kbEffectOnMediaItem);
-
-        mediaImageItem.addEffect(kbEffectOnMediaItem);
-        assertEquals("KenBurn Start Rect: " + imageItemFileName, startRect,
-            kbEffectOnMediaItem.getStartRect());
-
-        assertEquals("KenBurn End Rect: " + imageItemFileName, endRect,
-            kbEffectOnMediaItem.getEndRect());
-    }
-
-    /**
-     * To test KenBurnEffect : Set StartRect and EndRect
-     */
-
-    @LargeTest
-    public void testEffectKenBurnSet() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemRenderingMode =MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-            imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
-            (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
-            (mediaImageItem.getWidth() / 2));
-        final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
-            mediaImageItem.getHeight());
-
-        EffectKenBurns kbEffectOnMediaItem=null;
-        kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2",
-            startRect, endRect, 500, 3000);
-
-        assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
-        mediaImageItem.addEffect(kbEffectOnMediaItem);
-        assertEquals("KenBurn Start Rect", startRect,
-            kbEffectOnMediaItem.getStartRect());
-        assertEquals("KenBurn End Rect", endRect,
-            kbEffectOnMediaItem.getEndRect());
-
-        final Rect startRect1 = new Rect((mediaImageItem.getHeight() / 5),
-            (mediaImageItem.getWidth() / 5), (mediaImageItem.getHeight() / 4),
-            (mediaImageItem.getWidth() / 4));
-        final Rect endRect1 = new Rect(10, 10, mediaImageItem.getWidth() / 4,
-            mediaImageItem.getHeight() / 4);
-
-        /* Added newly to take care of removal set APIs */
-        kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_changed",
-            startRect1, endRect1, 500, 3000);
-
-        assertEquals("KenBurn Start Rect", startRect1,
-            kbEffectOnMediaItem.getStartRect());
-        assertEquals("KenBurn End Rect", endRect1,
-            kbEffectOnMediaItem.getEndRect());
-
-        final Rect zeroRect = new Rect(0, 0, 0, 0);
-        try {
-            kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroStart",
-                zeroRect, endRect, 500, 3000);
-
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid Start Rect", flagForException);
-
-        flagForException = false;
-        try {
-            kbEffectOnMediaItem = new EffectKenBurns(mediaImageItem, "KBOnM2_zeroEnd",
-                startRect, zeroRect, 500, 3000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid End Rect", flagForException);
-    }
-
-    /**
-     * To test Transition : Fade To Black with all behavior
-     * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
-     */
-
-    @LargeTest
-    public void testTransitionFadeBlack() throws Exception {
-
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String videoItemFilename2 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename3 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final String videoItemFilename4 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFilename5 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-            videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-            videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionFadeBlack transition1And2 = mVideoEditorHelper
-            .createTFadeBlack("transition1And2", mediaVideoItem1,
-            mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP);
-        mVideoEditor.addTransition(transition1And2);
-
-        assertTrue("Transition ID",
-            transition1And2.getId().equals("transition1And2"));
-        assertEquals("Transtion After Media item",
-            mediaVideoItem1, transition1And2.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem2,
-            transition1And2.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
-            transition1And2.getBehavior());
-
-        final MediaImageItem mediaImageItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem3);
-
-        final TransitionFadeBlack transition2And3 =
-            mVideoEditorHelper.createTFadeBlack("transition2And3", mediaVideoItem2,
-                mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN);
-        mVideoEditor.addTransition(transition2And3);
-
-        assertTrue("Transition ID",
-            transition2And3.getId().equals("transition2And3"));
-        assertEquals("Transtion After Media item", mediaVideoItem2,
-            transition2And3.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaImageItem3,
-            transition2And3.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
-            transition2And3.getBehavior());
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final TransitionFadeBlack transition3And4 =
-            mVideoEditorHelper.createTFadeBlack("transition3And4", mediaImageItem3,
-                mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR);
-        mVideoEditor.addTransition(transition3And4);
-
-        assertTrue("Transition ID",
-            transition3And4.getId().equals("transition3And4"));
-        assertEquals("Transtion After Media item", mediaImageItem3,
-            transition3And4.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem4,
-            transition3And4.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
-            transition3And4.getBehavior());
-
-        final MediaVideoItem mediaVideoItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem5);
-
-        final TransitionFadeBlack transition4And5 =
-            mVideoEditorHelper.createTFadeBlack("transition4And5", mediaVideoItem4,
-                mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition4And5);
-
-        assertTrue("Transition ID",
-            transition4And5.getId().equals("transition4And5"));
-        assertEquals("Transtion After Media item", mediaVideoItem4,
-            transition4And5.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem5,
-            transition4And5.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
-            transition4And5.getBehavior());
-
-        final MediaVideoItem mediaVideoItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem6.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem6);
-
-        final TransitionFadeBlack transition5And6 =
-            mVideoEditorHelper.createTFadeBlack("transition5And6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW);
-        mVideoEditor.addTransition(transition5And6);
-
-        assertTrue("Transition ID",
-            transition5And6.getId().equals("transition5And6"));
-        assertEquals("Transtion After Media item", mediaVideoItem5,
-            transition5And6.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem6,
-            transition5And6.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
-            transition5And6.getBehavior());
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTFadeBlack("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTFadeBlack("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-    }
-
-    /**
-     * To test Transition : CrossFade with all behavior
-     * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
-     */
-
-    @LargeTest
-    public void testTransitionCrossFade() throws Exception {
-
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String videoItemFilename2 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename3 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final String videoItemFilename4 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFilename5 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionCrossfade transition1And2 =
-            mVideoEditorHelper.createTCrossFade("transition1And2", mediaVideoItem1,
-                mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP);
-        mVideoEditor.addTransition(transition1And2);
-
-        assertTrue("Transition ID",
-            transition1And2.getId().equals("transition1And2"));
-        assertEquals("Transtion After Media item", mediaVideoItem1,
-            transition1And2.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem2,
-            transition1And2.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
-            transition1And2.getBehavior());
-
-        final MediaImageItem mediaImageItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem3);
-
-        final TransitionCrossfade transition2And3 =
-            mVideoEditorHelper.createTCrossFade("transition2And3", mediaVideoItem2,
-                mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN);
-        mVideoEditor.addTransition(transition2And3);
-
-        assertTrue("Transition ID",
-            transition2And3.getId().equals("transition2And3"));
-        assertEquals("Transtion After Media item", mediaVideoItem2,
-            transition2And3.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaImageItem3,
-            transition2And3.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
-            transition2And3.getBehavior());
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(0, 18000);
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final TransitionCrossfade transition3And4 =
-            mVideoEditorHelper.createTCrossFade("transition3And4", mediaImageItem3,
-                mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR);
-        mVideoEditor.addTransition(transition3And4);
-
-        assertTrue("Transition ID",
-            transition3And4.getId().equals("transition3And4"));
-        assertEquals("Transtion After Media item", mediaImageItem3,
-            transition3And4.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem4,
-            transition3And4.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
-            transition3And4.getBehavior());
-
-        final MediaVideoItem mediaVideoItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem5);
-
-        final TransitionCrossfade transition4And5 =
-            mVideoEditorHelper.createTCrossFade("transition4And5", mediaVideoItem4,
-                mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition4And5);
-
-        assertTrue("Transition ID",
-            transition4And5.getId().equals("transition4And5"));
-        assertEquals("Transtion After Media item", mediaVideoItem4,
-            transition4And5.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem5,
-            transition4And5.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
-            transition4And5.getBehavior());
-
-        final MediaVideoItem mediaVideoItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem6.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem6);
-
-        final TransitionCrossfade transition5And6 =
-            mVideoEditorHelper.createTCrossFade("transition5And6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW);
-        mVideoEditor.addTransition(transition5And6);
-
-        assertTrue("Transition ID",
-            transition5And6.getId().equals("transition5And6"));
-        assertEquals("Transtion After Media item", mediaVideoItem5,
-            transition5And6.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem6,
-            transition5And6.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
-            transition5And6.getBehavior());
-
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTCrossFade("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTCrossFade("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-    }
-
-    /**
-     * To test Transition : Sliding with all behavior
-     * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST and Direction =
-     * DIRECTION_RIGHT_OUT_LEFT_IN
-     * ,DIRECTION_LEFT_OUT_RIGHT_IN,DIRECTION_TOP_OUT_BOTTOM_IN
-     * ,DIRECTION_BOTTOM_OUT_TOP_IN
-     */
-
-    @LargeTest
-    public void testTransitionSliding() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String videoItemFilename2 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String videoItemFilename3 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final String videoItemFilename4 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFilename5 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionSliding transition1And2 =
-            mVideoEditorHelper.createTSliding("transition1And2", mediaVideoItem1,
-                mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        mVideoEditor.addTransition(transition1And2);
-
-        assertTrue("Transition ID",
-            transition1And2.getId().equals("transition1And2"));
-        assertEquals("Transtion After Media item", mediaVideoItem1,
-            transition1And2.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem2,
-            transition1And2.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
-            transition1And2.getBehavior());
-        assertEquals("Transition Sliding",
-            TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN,
-            transition1And2.getDirection());
-
-        final MediaImageItem mediaImageItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem3);
-
-        final TransitionSliding transition2And3 =
-            mVideoEditorHelper.createTSliding("transition2And3",
-                mediaVideoItem2, mediaImageItem3, 1000,
-                Transition.BEHAVIOR_SPEED_DOWN,
-                TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
-        mVideoEditor.addTransition(transition2And3);
-
-        assertTrue("Transition ID",
-            transition2And3.getId().equals("transition2And3"));
-        assertEquals("Transtion After Media item", mediaVideoItem2,
-            transition2And3.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaImageItem3,
-            transition2And3.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
-            transition2And3.getBehavior());
-        assertEquals("Transition Sliding",
-            TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN,
-            transition2And3.getDirection());
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(0, 18000);
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final TransitionSliding transition3And4 =
-            mVideoEditorHelper.createTSliding("transition3And4", mediaImageItem3,
-                mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR,
-                TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN);
-        mVideoEditor.addTransition(transition3And4);
-
-        assertTrue("Transition ID",
-            transition3And4.getId().equals("transition3And4"));
-        assertEquals("Transtion After Media item", mediaImageItem3,
-            transition3And4.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem4,
-            transition3And4.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
-            transition3And4.getBehavior());
-        assertEquals("Transition Sliding",
-            TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN,
-            transition3And4.getDirection());
-
-        final MediaVideoItem mediaVideoItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem5);
-
-        final TransitionSliding transition4And5 =
-            mVideoEditorHelper.createTSliding("transition4And5", mediaVideoItem4,
-                mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST,
-                TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN);
-        mVideoEditor.addTransition(transition4And5);
-
-        assertTrue("Transition ID",
-            transition4And5.getId().equals("transition4And5"));
-        assertEquals("Transtion After Media item", mediaVideoItem4,
-            transition4And5.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem5,
-            transition4And5.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
-            transition4And5.getBehavior());
-        assertEquals("Transition Sliding",
-            TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN,
-            transition4And5.getDirection());
-
-        final MediaVideoItem mediaVideoItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem6.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem6);
-
-        final TransitionSliding transition5And6 =
-            mVideoEditorHelper.createTSliding("transition5And6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        mVideoEditor.addTransition(transition5And6);
-
-        assertTrue("Transition ID",
-            transition5And6.getId().equals("transition5And6"));
-        assertEquals("Transtion After Media item", mediaVideoItem5,
-            transition5And6.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem6,
-            transition5And6.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 2000, transition5And6.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_SLOW,
-            transition5And6.getBehavior());
-        assertEquals("Transition Sliding",
-            TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN,
-            transition5And6.getDirection());
-
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN - 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition Sliding with Invalid Direction", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
-                TransitionSliding.DIRECTION_BOTTOM_OUT_TOP_IN + 1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition Sliding with Invalid behavior", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_SPEED_UP - 1,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition Sliding with Invalid behavior", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTSliding("transitiond6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition Sliding with Invalid behavior", flagForException);
-    }
-
-    /**
-     * To test Transition : Alpha with all behavior
-     * SPEED_UP/SPEED_DOWN/LINEAR/MIDDLE_SLOW/MIDDLE_FAST
-     */
-
-    @LargeTest
-    public void testTransitionAlpha() throws Exception {
-
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String videoItemFilename2 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String videoItemFilename3 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final String videoItemFilename4 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFilename5 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
-        final String maskFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionAlpha transition1And2 =
-            mVideoEditorHelper.createTAlpha("transition1And2", mediaVideoItem1,
-            mediaVideoItem2, 3000, Transition.BEHAVIOR_SPEED_UP, maskFilename,
-            10, false);
-        mVideoEditor.addTransition(transition1And2);
-
-        assertTrue("Transition ID",
-            transition1And2.getId().equals("transition1And2"));
-        assertEquals("Transtion After Media item", mediaVideoItem1,
-            transition1And2.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem2,
-            transition1And2.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 3000, transition1And2.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_UP,
-            transition1And2.getBehavior());
-        assertTrue("Transition maskFile",
-            transition1And2.getMaskFilename().equals(maskFilename));
-        assertEquals("Transition BlendingPercent", 10,
-            transition1And2.getBlendingPercent());
-        assertFalse("Transition Invert", transition1And2.isInvert());
-
-        final MediaImageItem mediaImageItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem3);
-
-        final TransitionAlpha transition2And3 =
-            mVideoEditorHelper.createTAlpha("transition2And3", mediaVideoItem2,
-                mediaImageItem3, 1000, Transition.BEHAVIOR_SPEED_DOWN,
-                maskFilename, 30, false);
-        mVideoEditor.addTransition(transition2And3);
-
-        assertTrue("Transition ID",
-            transition2And3.getId().equals("transition2And3"));
-        assertEquals("Transtion After Media item", mediaVideoItem2,
-            transition2And3.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaImageItem3,
-            transition2And3.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 1000, transition2And3.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_SPEED_DOWN,
-            transition2And3.getBehavior());
-        assertTrue("Transition maskFile",
-            transition2And3.getMaskFilename().equals(maskFilename));
-        assertEquals("Transition BlendingPercent", 30,
-            transition2And3.getBlendingPercent());
-        assertFalse("Transition Invert", transition2And3.isInvert());
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(0, 18000);
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final TransitionAlpha transition3And4 =
-            mVideoEditorHelper.createTAlpha("transition3And4", mediaImageItem3,
-            mediaVideoItem4, 5000, Transition.BEHAVIOR_LINEAR, maskFilename,
-            50, false);
-        mVideoEditor.addTransition(transition3And4);
-
-        assertTrue("Transition ID",
-            transition3And4.getId().equals("transition3And4"));
-        assertEquals("Transtion After Media item", mediaImageItem3,
-            transition3And4.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem4,
-            transition3And4.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 5000, transition3And4.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_LINEAR,
-            transition3And4.getBehavior());
-        assertTrue("Transition maskFile",
-            transition3And4.getMaskFilename().equals(maskFilename));
-        assertEquals("Transition BlendingPercent", 50,
-            transition3And4.getBlendingPercent());
-        assertFalse("Transition Invert", transition3And4.isInvert());
-
-        final MediaVideoItem mediaVideoItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                videoItemFilename4, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem5);
-
-        final TransitionAlpha transition4And5 =
-            mVideoEditorHelper.createTAlpha("transition4And5", mediaVideoItem4,
-            mediaVideoItem5, 8000, Transition.BEHAVIOR_MIDDLE_FAST,
-            maskFilename, 70, true);
-        mVideoEditor.addTransition(transition4And5);
-
-        assertTrue("Transition ID",
-            transition4And5.getId().equals("transition4And5"));
-        assertEquals("Transtion After Media item", mediaVideoItem4,
-            transition4And5.getAfterMediaItem());
-        assertEquals("Transtion Before Media item", mediaVideoItem5,
-            transition4And5.getBeforeMediaItem());
-        assertEquals("Transtion Duration", 8000, transition4And5.getDuration());
-        assertEquals("Transtion Behavior", Transition.BEHAVIOR_MIDDLE_FAST,
-            transition4And5.getBehavior());
-        assertTrue("Transition maskFile",
-            transition4And5.getMaskFilename().equals(maskFilename));
-        assertEquals("Transition BlendingPercent", 70,
-            transition4And5.getBlendingPercent());
-        assertTrue("Transition Invert", transition4And5.isInvert());
-
-        final MediaVideoItem mediaVideoItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                videoItemFilename5, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem6.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem6);
-
-        try {
-            mVideoEditorHelper.createTAlpha("transition5And6", mediaVideoItem5,
-                mediaVideoItem6, 2000, Transition.BEHAVIOR_MIDDLE_SLOW,
-                INPUT_FILE_PATH + "imDummyFile.jpg", 70,
-                true);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("MaskFile is not exsisting", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTAlpha("transition5And6", null, null, 2000,
-                Transition.BEHAVIOR_MIDDLE_SLOW, maskFilename, 101, true);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Invalid Blending Percent", flagForException);
-
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTAlpha("transitiond6", mediaVideoItem4,
-                mediaVideoItem5, 2000, Transition.BEHAVIOR_SPEED_UP - 1,
-                maskFilename, 30, false);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditorHelper.createTAlpha("transitiond6", mediaVideoItem4,
-                mediaVideoItem5, 2000, Transition.BEHAVIOR_MIDDLE_FAST + 1,
-                maskFilename, 30, false);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Transition FadeBlack with Invalid behavior", flagForException);
-    }
-
-    /**
-     * To test Frame Overlay for Media Video Item
-     */
-
-    @LargeTest
-    public void testFrameOverlayVideoItem() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_256kbps_0_25.3gp";
-        final String overlayFile1 = INPUT_FILE_PATH +  "IMG_176x144_Overlay1.png";
-        final String overlayFile2 = INPUT_FILE_PATH +  "IMG_176x144_Overlay2.png";
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final Bitmap mBitmap1 =  mVideoEditorHelper.getBitmap(overlayFile1,
-            176, 144);
-        final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
-            mediaVideoItem1, "overlayId1", mBitmap1, 5000, 5000);
-        mediaVideoItem1.addOverlay(overlayFrame1);
-
-        assertEquals("Overlay : Media Item", mediaVideoItem1,
-            overlayFrame1.getMediaItem());
-        assertTrue("Overlay Id", overlayFrame1.getId().equals("overlayId1"));
-        assertEquals("Overlay Bitmap", mBitmap1, overlayFrame1.getBitmap());
-        assertEquals("Overlay Start Time", 5000, overlayFrame1.getStartTime());
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
-        Bitmap upddateBmp = mVideoEditorHelper.getBitmap(overlayFile2, 176, 144);
-        overlayFrame1.setBitmap(upddateBmp);
-        assertEquals("Overlay Update Bitmap", upddateBmp, overlayFrame1.getBitmap());
-        upddateBmp.recycle();
-    }
-
-    /**
-     * To test Frame Overlay for Media Video Item : Set duration and Get
-     * Duration
-     */
-
-    @LargeTest
-    public void testFrameOverlaySetAndGet() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_30fps_512Kbps_0_27.mp4";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-            640, 480);
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-            videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
-            mediaVideoItem1, "overlayId1", mBitmap, 5000, 5000);
-        mediaVideoItem1.addOverlay(overlayFrame1);
-        overlayFrame1.setDuration(5000);
-
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-        try {
-            overlayFrame1.setDuration(mediaVideoItem1.getDuration() + 10000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay Duration > MediaVideo Item Duration",
-            flagForException);
-
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-        flagForException = false;
-
-        try {
-            overlayFrame1.setDuration(-1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay Duration = -1", flagForException);
-    }
-
-    /**
-     * To test Frame Overlay for Media Video Item : Set duration and Get
-     * Duration
-     */
-
-    @LargeTest
-    public void testFrameOverlayInvalidTime() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-                640, 480);
-            mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId1",
-                mBitmap, 400000000, 2000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-
-        flagForException = false;
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-                640, 480);
-            mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId2",
-                mBitmap, -1, 2000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-
-        flagForException = false;
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-            640, 480);
-            mVideoEditorHelper.createOverlay(mediaVideoItem1, "overlayId3",
-                mBitmap, 2000, -1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-    }
-
-    /**
-     * To test Frame Overlay for Media Image Item
-     */
-    @LargeTest
-    public void testFrameOverlayImageItem() throws Exception {
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        final String overlayFile2 = INPUT_FILE_PATH + "IMG_640x480_Overlay2.png";
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                imageItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1, 640,
-            480);
-        final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
-            mediaImageItem1, "overlayId1", mBitmap, 5000, 5000);
-        mediaImageItem1.addOverlay(overlayFrame1);
-
-        assertEquals("Overlay : Media Item", mediaImageItem1,
-            overlayFrame1.getMediaItem());
-        assertTrue("Overlay Id", overlayFrame1.getId().equals("overlayId1"));
-        assertEquals("Overlay Bitmap",mBitmap ,overlayFrame1.getBitmap());
-        assertEquals("Overlay Start Time", 5000, overlayFrame1.getStartTime());
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-        Bitmap upddateBmp = mVideoEditorHelper.getBitmap(overlayFile2, 640, 480);
-
-        overlayFrame1.setBitmap(upddateBmp);
-        assertEquals("Overlay Update Bitmap", upddateBmp, overlayFrame1.getBitmap());
-        upddateBmp.recycle();
-    }
-
-    /**
-     * To test Frame Overlay for Media Image Item : Set duration and Get
-     * Duration
-     */
-
-    @LargeTest
-    public void testFrameOverlaySetAndGetImage() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-            640, 480);
-        final OverlayFrame overlayFrame1 = mVideoEditorHelper.createOverlay(
-            mediaImageItem1, "overlayId1", mBitmap, 5000, 5000);
-        mediaImageItem1.addOverlay(overlayFrame1);
-
-        overlayFrame1.setDuration(5000);
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
-        try {
-            overlayFrame1.setDuration(mediaImageItem1.getDuration() + 10000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay Duration > Media Item Duration", flagForException);
-        assertEquals("Overlay Duration", 5000, overlayFrame1.getDuration());
-
-        flagForException = false;
-        try {
-            overlayFrame1.setDuration(-1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay Duration = -1", flagForException);
-    }
-
-    /**
-     * To test  Frame Overlay for  Media Image Item :Invalid StartTime and
-     * Duration
-     */
-
-    @LargeTest
-    public void testFrameOverlayInvalidTimeImage() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-                640, 480);
-            mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId1",
-                mBitmap, 400000000, 2000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-
-        flagForException = false;
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-                640, 480);
-            mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId2",
-                mBitmap, -1, 2000);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-
-        flagForException = false;
-        try {
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1,
-                640, 480);
-            mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId3",
-                mBitmap, 2000, -1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Overlay With Invalid Start Time", flagForException);
-    }
-
-    /**
-     * To Test Frame Overlay Media Image Item :JPG File
-     */
-
-    @LargeTest
-    public void testFrameOverlayJPGImage() throws Exception {
-
-        final String imageItemFilename = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String overlayFile1 = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                imageItemFilename, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile1, 640,
-            480);
-        mVideoEditorHelper.createOverlay(mediaImageItem1, "overlayId1",
-            mBitmap, 5000, 5000);
-    }
-
-    /**
-     * To test Video Editor API
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testVideoEditorAPI() throws Exception {
-
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String videoItemFileName3 = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
-        final String audioFilename1 = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        final String audioFilename2 = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        TransitionCrossfade transition2And4;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName1, renderingMode);
-        mediaVideoItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFileName2, renderingMode);
-        mediaVideoItem2.setExtractBoundaries(mediaVideoItem2.getDuration() / 4,
-            mediaVideoItem2.getDuration() / 2);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFileName3, renderingMode);
-        mediaVideoItem3.setExtractBoundaries(mediaVideoItem3.getDuration() / 2,
-            mediaVideoItem3.getDuration());
-        mVideoEditor.addMediaItem(mediaVideoItem3);
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                imageItemFileName1, 5000, renderingMode);
-
-        final MediaImageItem mediaImageItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                imageItemFileName2, 5000, renderingMode);
-
-        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 3, mediaList.size());
-
-        mVideoEditor.insertMediaItem(mediaImageItem1, mediaVideoItem2.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 4, mediaList.size());
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
-        assertEquals("Media item 4", mediaImageItem1, mediaList.get(2));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(3));
-
-        mVideoEditor.insertMediaItem(mediaImageItem2, mediaImageItem1.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 5, mediaList.size());
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
-        assertEquals("Media item 4", mediaImageItem1, mediaList.get(2));
-        assertEquals("Media item 5", mediaImageItem2, mediaList.get(3));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
-        mVideoEditor.moveMediaItem(mediaVideoItem1.getId(), mediaImageItem2.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 5, mediaList.size());
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(0));
-        assertEquals("Media item 4", mediaImageItem1, mediaList.get(1));
-        assertEquals("Media item 5", mediaImageItem2, mediaList.get(2));
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(3));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
-        assertEquals("Media Item 1", mediaVideoItem1,
-            mVideoEditor.getMediaItem(mediaVideoItem1.getId()));
-
-        flagForException = false;
-        transition2And4 = null;
-        try{
-            transition2And4 = mVideoEditorHelper.createTCrossFade(
-                "transition2And4", mediaVideoItem2, mediaImageItem1, 2000,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-            mVideoEditor.addTransition(transition2And4);
-        }
-        catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertFalse("Transition2and4 cannot be created", flagForException);
-
-
-        TransitionCrossfade transition1And3 = null;
-        flagForException = false;
-        try{
-            transition1And3 = mVideoEditorHelper.createTCrossFade(
-                "transition1And3", mediaVideoItem1, mediaVideoItem2, 5000,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-                mVideoEditor.addTransition(transition1And3);
-            }catch (IllegalArgumentException e) {
-                flagForException = true;
-            }
-        assertTrue("Transition1and3 cannot be created", flagForException);
-
-        List<Transition> transitionList = mVideoEditor.getAllTransitions();
-        assertEquals("Transition List", 1, transitionList.size());
-
-        assertEquals("Transition 2", transition2And4,
-            mVideoEditor.getTransition(transition2And4.getId()));
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFilename1);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        List<AudioTrack> audioList = mVideoEditor.getAllAudioTracks();
-        assertEquals("Audio List", 1, audioList.size());
-
-        final AudioTrack audioTrack1 = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack1", audioFilename2);
-        flagForException = false;
-        try {
-            mVideoEditor.addAudioTrack(audioTrack1);
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Audio Track support is 1 ", flagForException);
-
-        flagForException = false;
-        try {
-            mVideoEditor.insertAudioTrack(audioTrack1,"audioTrack");
-        } catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Audio Track supports is 1 ", flagForException);
-
-        assertEquals("Removing AudioTrack", audioTrack,
-            mVideoEditor.removeAudioTrack(audioTrack.getId()));
-
-        assertEquals("Removing transition", transition2And4,
-            mVideoEditor.removeTransition(transition2And4.getId()));
-
-        assertEquals("Removing Media Item", mediaVideoItem2,
-            mVideoEditor.removeMediaItem(mediaVideoItem2.getId()));
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_16_9);
-        assertEquals("Check Aspect Ratio", MediaProperties.ASPECT_RATIO_16_9,
-            mVideoEditor.getAspectRatio());
-
-        long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
-            + mediaVideoItem3.getTimelineDuration()
-            + mediaImageItem1.getDuration()
-            + mediaImageItem2.getDuration();
-        assertEquals("Story Board Duration", storyBoardDuration,
-            mVideoEditor.getDuration());
-    }
-
-    /**
-     * To add Audio Track Greater than MediaItem Duration
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testVideoLessThanAudio() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String audioTrackFilename = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrackId", audioTrackFilename);
-        mVideoEditor.addAudioTrack(audioTrack);
-        assertEquals("Storyboard = mediaItem Duration",
-            mediaVideoItem1.getDuration(), mVideoEditor.getDuration());
-        assertTrue("Audio Duration > mediaItem Duration",
-            (audioTrack.getDuration() > mediaVideoItem1.getDuration() ?
-            true : false));
-    }
-
-    /**
-     * To test Video Editor API with 1080 P
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testVideoContentHD() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "H264_BP_1920x1080_30fps_1200Kbps_1_10.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final MediaVideoItem mediaVideoItem1;
-        // 1080p resolution is supported on some devices
-        // but not on other devices.
-        // So this test case is not generic and
-        // hence we always assert true
-        boolean flagForException = true;
-        try {
-            mediaVideoItem1 = mVideoEditorHelper.createMediaItem(mVideoEditor,
-                "m1", videoItemFileName1, renderingMode);
-        } catch (IllegalArgumentException e) {
-        }
-        assertTrue("VideoContent 1920x1080", flagForException);
-    }
-
-
-    /**
-     * To test: Remove audio track
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testRemoveAudioTrack() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack1", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        assertEquals("Audio Track Item Duration", audioTrack.getDuration(),
-            audioTrack.getTimelineDuration());
-        assertTrue("Audio Track ID", audioTrack.getId().equals("audioTrack1"));
-        assertNotNull("Remove Audio Track",
-            mVideoEditor.removeAudioTrack("audioTrack1"));
-        try{
-            mVideoEditor.removeAudioTrack("audioTrack1");
-        }catch (IllegalArgumentException e){
-            flagForException = true;
-        }
-        assertTrue("Remove Audio Track not possible", flagForException);
-    }
-
-      /**
-     * To test: Disable ducking
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testAudioDuckingDisable() throws Exception {
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        audioTrack.disableDucking();
-        assertFalse("Audio Track Ducking is Disabled",
-            audioTrack.isDuckingEnabled());
-    }
-
-
-
-      /**
-     * To test: Need a basic test case for the get value for TransitionAlpha
-     *  ( ie. getBlendingPercent, getMaskFilename, isInvert)
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testTransitionAlphaBasic() throws Exception {
-
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String maskFilename = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2", maskFilename,
-                10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaImageItem.setDuration(15000);
-
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        mVideoEditor.addMediaItem(mediaImageItem);
-        final TransitionAlpha transition1And2 =
-            mVideoEditorHelper.createTAlpha("transition1And2", mediaVideoItem1,
-                mediaImageItem, 3000, Transition.BEHAVIOR_SPEED_UP,
-                maskFilename, 10, false);
-        mVideoEditor.addTransition(transition1And2);
-        assertTrue("Transition maskFile",
-            transition1And2.getMaskFilename().equals(maskFilename));
-        assertEquals("Transition BlendingPercent", 10,
-            transition1And2.getBlendingPercent());
-        assertFalse("Transition Invert", transition1And2.isInvert());
-    }
-
-    /**
-     * To test: NULL arguments to the Video Editor APIs
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testNullAPIs() throws Exception {
-
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String maskFilename = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final String audioFileName = INPUT_FILE_PATH +
-            "AACLC_48KHz_256Kbps_s_1_17.3gp";
-        boolean flagForException = false;
-
-        try {
-            mVideoEditor.addAudioTrack(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Video Editor with null Audio Track", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditor.addMediaItem(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Video Editor with NULL Image Item ", flagForException);
-        flagForException = false;
-        try {
-            mVideoEditor.addMediaItem(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Video Editor with NULL Video Item ", flagForException);
-
-        MediaVideoItem mediaVideoItem1 = null;
-        try {
-            mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        } catch (IllegalArgumentException e) {
-            assertTrue("Cannot Create Video Item", false);
-        }
-        mediaVideoItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        flagForException = false;
-        try {
-            mediaVideoItem1.addEffect(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Video with null effect ", flagForException);
-        flagForException = false;
-        try {
-            mediaVideoItem1.addOverlay(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Video with null overlay ", flagForException);
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2", maskFilename,
-                10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaImageItem.setDuration(15000);
-        mVideoEditor.addMediaItem(mediaImageItem);
-        flagForException = false;
-        try {
-            mediaImageItem.addEffect(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Image with null effect ", flagForException);
-        flagForException = false;
-        try {
-            mediaImageItem.addOverlay(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Image with null overlay ", flagForException);
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioFileName);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        flagForException = false;
-        try {
-            mVideoEditor.addTransition(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Added null transition ", flagForException);
-
-        flagForException = false;
-        try {
-            mVideoEditor.addTransition(null);
-        } catch(IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Added null transition ", flagForException);
-
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java
deleted file mode 100644
index 69ecf0d..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorExportTest.java
+++ /dev/null
@@ -1,812 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-
-
-import android.util.Log;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import android.test.suitebuilder.annotation.Suppress;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-public class VideoEditorExportTest extends
-    ActivityInstrumentationTestCase<MediaFrameworkTest> {
-    private final String TAG = "TransitionTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private VideoEditor mVideoEditor;
-
-    private VideoEditorHelper mVideoEditorHelper;
-
-    // Declares the annotation for Preview Test Cases
-    public @interface TransitionTests {
-    }
-
-    public VideoEditorExportTest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath =
-            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    /**
-     * To Test export : Merge and Trim different types of Video and Image files
-     */
-    @LargeTest
-    public void testExportMergeTrim() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename2 = INPUT_FILE_PATH
-            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final String videoItemFilename3 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
-        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/")
-            + ".3gp";
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(2000, 7000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaImageItem mediaImageItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem2);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem3.setExtractBoundaries(0, 2000);
-        mVideoEditor.addMediaItem(mediaVideoItem3);
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
-            mediaVideoItem4.getDuration());
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final MediaImageItem mediaImageItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem5);
-
-        final MediaImageItem mediaImageItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem6);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
-            + mediaImageItem2.getDuration() + mediaVideoItem3.getTimelineDuration()
-            + mediaVideoItem4.getTimelineDuration() + mediaImageItem5.getDuration()
-            + mediaImageItem6.getDuration();
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     *To Test export : With Effect and Overlays on Different Media Items
-     */
-    @LargeTest
-    public void testExportEffectOverlay() throws Exception {
-          final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename2 = INPUT_FILE_PATH
-              + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
-        final String videoItemFilename3 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
-        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
-        final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(2000, 7000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final EffectColor effectPink =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectPink",
-                0, 2000, EffectColor.TYPE_COLOR, EffectColor.PINK);
-        mediaVideoItem1.addEffect(effectPink);
-
-        final EffectColor effectNegative =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectNegative",
-                3000, 4000, EffectColor.TYPE_NEGATIVE, 0);
-        mediaVideoItem1.addEffect(effectNegative);
-
-        final MediaImageItem mediaImageItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem2);
-
-        final EffectColor effectFifties =
-            mVideoEditorHelper.createEffectItem(mediaImageItem2, "effectFifties",
-                0, 3000, EffectColor.TYPE_FIFTIES, 0);
-        mediaImageItem2.addEffect(effectFifties);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem3);
-        mediaVideoItem3.setExtractBoundaries(0, 8000);
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile,
-            640, 480);
-        final OverlayFrame overlayFrame =
-            mVideoEditorHelper.createOverlay(mediaVideoItem3, "overlay",
-                mBitmap, 2000, 5000);
-        mediaVideoItem3.addOverlay(overlayFrame);
-
-        final EffectColor effectGreen =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem3, "effectGreen",
-                0, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        mediaVideoItem3.addEffect(effectGreen);
-
-        final MediaVideoItem mediaVideoItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem4.setExtractBoundaries(mediaVideoItem4.getDuration()-5000,
-            mediaVideoItem4.getDuration());
-        mVideoEditor.addMediaItem(mediaVideoItem4);
-
-        final EffectColor effectSepia =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem4, "effectSepia",
-                0, 2000, EffectColor.TYPE_SEPIA, 0);
-        mediaVideoItem4.addEffect(effectSepia);
-
-        final MediaImageItem mediaImageItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                imageItemFilename2, 4000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem5);
-
-        final EffectColor effectGray =
-            mVideoEditorHelper.createEffectItem(mediaImageItem5, "effectGray",
-                0, 2000, EffectColor.TYPE_COLOR, EffectColor.GRAY);
-        mediaImageItem5.addEffect(effectGray);
-
-        final MediaImageItem mediaImageItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                imageItemFilename3, 2000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem6);
-
-        final EffectColor effectGradient =
-            mVideoEditorHelper.createEffectItem(mediaImageItem6,
-                "effectGradient", 0, 2000, EffectColor.TYPE_GRADIENT,
-                EffectColor.PINK);
-        mediaImageItem6.addEffect(effectGradient);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        final long storyBoardDuration = mediaVideoItem1.getTimelineDuration()
-            + mediaImageItem2.getDuration()
-            + mediaVideoItem3.getTimelineDuration()
-            + mediaVideoItem4.getTimelineDuration()
-            + mediaImageItem5.getDuration()
-            + mediaImageItem6.getDuration();
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     * To test export : with Image with KenBurnEffect
-     */
-    @LargeTest
-    public void testExportEffectKenBurn() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemRenderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaImageItem1",
-                imageItemFileName, 5000, imageItemRenderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
-            (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
-            (mediaImageItem.getWidth() / 2));
-
-        final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
-            mediaImageItem.getHeight());
-
-        final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
-            mediaImageItem, "KBOnM2", startRect, endRect, 500, 3000);
-        assertNotNull("EffectKenBurns", kbEffectOnMediaItem);
-        mediaImageItem.addEffect(kbEffectOnMediaItem);
-
-        assertEquals("KenBurn Start Rect", startRect,
-            kbEffectOnMediaItem.getStartRect());
-        assertEquals("KenBurn End Rect", endRect,
-            kbEffectOnMediaItem.getEndRect());
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, mediaImageItem.getDuration(),
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     * To Test Export : With Video and Image and An Audio BackGround Track
-     */
-    @LargeTest
-    public void testExportAudio() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-        final String audioTrackFilename = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFileName, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "a1", audioTrackFilename);
-        audioTrack.setExtractBoundaries(2000, 5000);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        audioTrack.disableDucking();
-        audioTrack.enableLoop();
-        audioTrack.setVolume(75);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, (mediaVideoItem.getTimelineDuration() +
-            mediaImageItem.getDuration()),
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     *To Test export : With Transition on Different Media Items
-     */
-    @LargeTest
-    public void testExportTransition() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename2 = INPUT_FILE_PATH
-            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final String videoItemFilename3 = INPUT_FILE_PATH +
-            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-
-        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
-        final String imageItemFilename3 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-        final String maskFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-
-        final MediaVideoItem mediaItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaItem1.setExtractBoundaries(2000, 7000);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final TransitionAlpha transition1 =
-            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
-                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
-        mVideoEditor.addTransition(transition1);
-
-        final MediaImageItem mediaItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem2);
-
-        final MediaVideoItem mediaItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaItem3.setExtractBoundaries(0, 8000);
-        mVideoEditor.addMediaItem(mediaItem3);
-
-        final TransitionSliding transition2And3 =
-            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
-                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        mVideoEditor.addTransition(transition2And3);
-
-        final MediaVideoItem mediaItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                videoItemFilename3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem4);
-        mediaItem4.setExtractBoundaries(0, 8000);
-
-        final TransitionCrossfade transition3And4 =
-            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
-                mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
-        mVideoEditor.addTransition(transition3And4);
-
-        final MediaImageItem mediaItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem5);
-
-        final TransitionFadeBlack transition4And5 =
-            mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
-                mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
-        mVideoEditor.addTransition(transition4And5);
-
-        final MediaImageItem mediaItem6 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m6",
-                imageItemFilename3, 3000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem6);
-
-        final TransitionSliding transition5And6 =
-            mVideoEditorHelper.createTSliding("transition5", mediaItem5,
-                mediaItem6, 1000/*4000*/, Transition.BEHAVIOR_SPEED_UP,
-                TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
-        mVideoEditor.addTransition(transition5And6);
-
-        final TransitionSliding transition6 =
-            mVideoEditorHelper.createTSliding("transition6", mediaItem6, null,
-                1000 /*4000*/, Transition.BEHAVIOR_SPEED_UP,
-                TransitionSliding.DIRECTION_TOP_OUT_BOTTOM_IN);
-        mVideoEditor.addTransition(transition6);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        final long storyBoardDuration = mediaItem1.getTimelineDuration()
-            + mediaItem2.getTimelineDuration()
-            + mediaItem3.getTimelineDuration() - transition2And3.getDuration()
-            + mediaItem4.getTimelineDuration() - transition3And4.getDuration()
-            + mediaItem5.getTimelineDuration() - transition4And5.getDuration()
-            + mediaItem6.getTimelineDuration() - transition5And6.getDuration();
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, storyBoardDuration,
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     * To Test Export : Without any Media Items in the story Board
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testExportWithoutMediaItems() throws Exception {
-        boolean flagForException = false;
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (IllegalStateException e) {
-            flagForException = true;
-        }
-        assertTrue("Export without any MediaItems", flagForException);
-    }
-
-    /**
-     * To Test Export : With Media Items add and removed in the story Board
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testExportWithoutMediaItemsAddRemove() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaItem1.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final MediaImageItem mediaItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 15000,
-                MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem2);
-
-        final TransitionAlpha transition1 =
-            mVideoEditorHelper.createTAlpha("transition1", mediaItem1, mediaItem2,
-                3000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, false);
-        mVideoEditor.addTransition(transition1);
-
-        final EffectColor effectColor =
-            mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 12000,
-                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
-        mediaItem2.addEffect(effectColor);
-
-        mVideoEditor.removeMediaItem(mediaItem1.getId());
-        mVideoEditor.removeMediaItem(mediaItem2.getId());
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export("/sdcard/Test.3gp", MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (IllegalStateException e) {
-            flagForException = true;
-        }
-        assertTrue("Export with MediaItem added and removed", flagForException);
-    }
-
-    /**
-     * To Test Export : With Video and Image : MMS use case
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testExportMMS() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFilename2 = INPUT_FILE_PATH
-            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final String maskFilename = INPUT_FILE_PATH + "TransitionSpiral_QVGA.jpg";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
-        final MediaVideoItem mediaItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaItem1.setExtractBoundaries(2000, 7000);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final TransitionAlpha transition1 =
-            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
-                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
-        mVideoEditor.addTransition(transition1);
-
-        final MediaImageItem mediaItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 8000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem2);
-
-        final MediaVideoItem mediaItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFilename2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaItem3.setExtractBoundaries(0, 8000);
-        mVideoEditor.addMediaItem(mediaItem3);
-
-        final TransitionSliding transition2And3 =
-            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
-                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        mVideoEditor.addTransition(transition2And3);
-
-        final TransitionCrossfade transition3 =
-            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3, null,
-                3500, Transition.BEHAVIOR_MIDDLE_SLOW);
-        mVideoEditor.addTransition(transition3);
-
-        final EffectColor effectColor =
-            mVideoEditorHelper.createEffectItem(mediaItem2, "effect", 0,
-                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
-        mediaItem2.addEffect(effectColor);
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_11_9);
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        final long storyBoardDuration = mediaItem1.getTimelineDuration()
-            + mediaItem2.getTimelineDuration() + mediaItem3.getTimelineDuration()
-            - transition2And3.getDuration();
-
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_144, 0, storyBoardDuration,
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-         mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     * To Test Export :Media Item having duration of 1 Hour
-     *
-     * @throws Exception
-     */
-    @Suppress
-    @LargeTest
-    public void testExportDuration1Hour() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_15fps_384kbps_60_0.mp4";
-        final String outFilename = mVideoEditorHelper.createRandomFile(
-            mVideoEditor.getPath() + "/") + ".3gp";
-
-        final MediaVideoItem mediaItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaItem1);
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        }catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0, mediaItem1.getDuration(),
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-
-    /**
-     * To Test Export : Storage location having very less space (Less than 100
-     * KB)
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testExportWithStorageFull() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-        boolean flagForException = false;
-
-        mVideoEditorHelper.createMediaItem(mVideoEditor, "m1", videoItemFilename1,
-            MediaItem.RENDERING_MODE_BLACK_BORDER);
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            flagForException = true;
-        }
-        assertTrue("Error in exporting file due to lack of storage space",
-            flagForException);
-    }
-
-     /**
-     * To Test Export :Two Media Items added
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testExportTwoVideos() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_12.5fps_256kbps_AACLC_16khz_24kbps_s_0_26.mp4";
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        try {
-            final int[] progressUpdate = new int[100];
-            mVideoEditor.export(outFilename, MediaProperties.HEIGHT_720,
-                MediaProperties.BITRATE_800K, new ExportProgressListener() {
-                    int i = 0;
-                    public void onProgress(VideoEditor ve, String outFileName,
-                        int progress) {
-                            progressUpdate[i++] = progress;
-                    }
-                });
-            mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        } catch (Exception e) {
-            assertTrue("Error in Export" + e.toString(), false);
-        }
-        mVideoEditorHelper.validateExport(mVideoEditor, outFilename,
-            MediaProperties.HEIGHT_720, 0,
-            (mediaVideoItem.getDuration()+ mediaVideoItem1.getDuration()),
-            MediaProperties.VCODEC_H264, MediaProperties.ACODEC_AAC_LC);
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
deleted file mode 100644
index 7965b0a..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/videoeditor/VideoEditorPreviewTest.java
+++ /dev/null
@@ -1,1156 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.functional.videoeditor;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-import java.util.concurrent.Semaphore;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.Effect;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.Overlay;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.media.videoeditor.VideoEditor.PreviewProgressListener;
-import android.media.videoeditor.VideoEditor.OverlayData;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.view.SurfaceHolder;
-
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-
-import java.util.concurrent.TimeUnit;
-
-import android.util.Log;
-
-public class VideoEditorPreviewTest extends
-    ActivityInstrumentationTestCase<MediaFrameworkTest> {
-    private final String TAG = "VideoEditorTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private final String PROJECT_CLASS_NAME =
-        "android.media.videoeditor.VideoEditorImpl";
-
-    private VideoEditor mVideoEditor;
-
-    private VideoEditorHelper mVideoEditorHelper;
-
-    private class EventHandler extends Handler {
-        public EventHandler( Looper lp)
-        {
-            super(lp);
-        }
-        public void handleMessage(Message msg)
-        {
-            switch (msg.what)
-            {
-                default:
-                MediaFrameworkTest.testInvalidateOverlay();
-            }
-        }
-    }
-    private EventHandler mEventHandler;
-
-    private boolean previewStart;
-    private boolean previewStop;
-    private boolean previewError;
-
-    /* Minimum waiting time for Semaphore to wait for release */
-    private final long minWaitingTime = 3000;
-
-    // Declares the annotation for Preview Test Cases
-    public @interface Preview {
-    }
-
-    public VideoEditorPreviewTest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mEventHandler = new EventHandler(looper);
-
-        } else {
-            //Handle error when looper can not be created.
-            ;
-        }
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath =
-            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    protected void setPreviewStart() {
-        previewStart = true;
-    }
-    protected void setPreviewStop() {
-        previewStop = true;
-    }
-    protected void setPreviewError() {
-        previewError = true;
-    }
-    protected void validatePreviewProgress(int startMs, int endMs,
-        boolean loop, long duration) throws Exception {
-
-        final int[] progressUpdate = new int[100];
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        previewError = false;
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            int i = 0;
-            public void onProgress(Object item, int action, int progress) {
-                progressUpdate[i++] = progress;
-            }
-        });
-        mVideoEditorHelper.checkProgressCBValues(progressUpdate);
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-
-        long waitingTime = minWaitingTime;
-        if (endMs == -1) {
-            waitingTime += duration;
-        }
-        else {
-            waitingTime += (endMs - startMs);
-        }
-        blockTillPreviewCompletes.acquire();
-        try {
-        mVideoEditor.startPreview(surfaceHolder, startMs, endMs, loop, 1,
-            new PreviewProgressListener() {
-                public void onProgress(VideoEditor videoEditor, long timeMs,
-                    OverlayData overlayData) {
-
-                        if ( overlayData != null) {
-                            if(overlayData.needsRendering()) {
-                                overlayData.renderOverlay(MediaFrameworkTest.mDestBitmap);
-                                mEventHandler.sendMessage(mEventHandler.obtainMessage(1, 2, 3));
-                            }
-                        }
-                }
-                public void onStart(VideoEditor videoEditor) {
-                    setPreviewStart();
-                }
-                public void onStop(VideoEditor videoEditor) {
-                    setPreviewStop();
-                    blockTillPreviewCompletes.release();
-                }
-                public void onError(VideoEditor videoEditor, int error) {
-                    setPreviewError();
-                    blockTillPreviewCompletes.release();
-                }
-        });
-        } catch (Exception e) {
-            blockTillPreviewCompletes.release();
-        }
-        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
-
-        mVideoEditor.stopPreview();
-        assertTrue("Preview Failed to start", previewStart);
-        assertTrue("Preview Failed to stop", previewStop);
-        assertFalse("Preview Error occurred", previewError);
-
-        blockTillPreviewCompletes.release();
-    }
-
-    // -----------------------------------------------------------------
-    // Preview
-    // -----------------------------------------------------------------
-
-    /**
-     *To test Preview : FULL Preview of current work (beginning till end)
-     */
-    @LargeTest
-    public void testPreviewTheStoryBoard() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFileName3 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        previewStart = false;
-        previewStop = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
-                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-        mediaVideoItem2.setExtractBoundaries(0, 10000);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
-                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem3.setExtractBoundaries(0, 10000);
-
-        mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
-        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
-        assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
-
-        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-        assertEquals("Media Item 1 Rendering Mode",
-            MediaItem.RENDERING_MODE_BLACK_BORDER,
-            mediaVideoItem1.getRenderingMode());
-
-        mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-        assertEquals("Media Item 2 Rendering Mode",
-            MediaItem.RENDERING_MODE_BLACK_BORDER,
-            mediaVideoItem2.getRenderingMode());
-
-        mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
-        assertEquals("Media Item 3 Rendering Mode",
-            MediaItem.RENDERING_MODE_STRETCH,
-            mediaVideoItem3.getRenderingMode());
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
-        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
-            mVideoEditor.getAspectRatio());
-
-        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test Preview : Preview of start + 10 sec till end of story board
-     */
-    @LargeTest
-    public void testPreviewTheStoryBoardFromDuration() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_256kbps_0_30.mp4";
-        final String videoItemFileName3 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_1_17.3gp";
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem2",
-                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem3",
-                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem3.setExtractBoundaries(0, 10000);
-
-        mVideoEditor.insertMediaItem(mediaVideoItem3, mediaVideoItem1.getId());
-
-        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media Item 3", mediaVideoItem3, mediaList.get(1));
-        assertEquals("Media Item 2", mediaVideoItem2, mediaList.get(2));
-        mediaVideoItem1.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        assertEquals("Media Item 1 Rendering Mode",
-            MediaItem.RENDERING_MODE_BLACK_BORDER,
-            mediaVideoItem1.getRenderingMode());
-        mediaVideoItem2.setRenderingMode(MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        assertEquals("Media Item 2 Rendering Mode",
-            MediaItem.RENDERING_MODE_BLACK_BORDER,
-            mediaVideoItem2.getRenderingMode());
-        mediaVideoItem3.setRenderingMode(MediaItem.RENDERING_MODE_STRETCH);
-
-        assertEquals("Media Item 3 Rendering Mode",
-            MediaItem.RENDERING_MODE_STRETCH,
-            mediaVideoItem3.getRenderingMode());
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_5_3);
-        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_5_3,
-            mVideoEditor.getAspectRatio());
-
-        validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test Preview : Preview of current Effects applied
-     */
-    @LargeTest
-    public void testPreviewOfEffects() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "mediaVideoItem1",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final EffectColor effectNegative =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1,
-                "effectNegative", 0, 2000, EffectColor.TYPE_NEGATIVE, 0);
-        mediaVideoItem1.addEffect(effectNegative);
-
-        final EffectColor effectGreen =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "effectGreen",
-                2000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        mediaVideoItem1.addEffect(effectGreen);
-
-        final EffectColor effectFifties =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1,
-                "effectFifties", 5000, 4000, EffectColor.TYPE_FIFTIES, 0);
-        mediaVideoItem1.addEffect(effectFifties);
-
-        List<Effect> effectList = mediaVideoItem1.getAllEffects();
-        assertEquals("Effect List Size", 3, effectList.size());
-        assertEquals("Effect negative", effectNegative, effectList.get(0));
-        assertEquals("Effect Green", effectGreen, effectList.get(1));
-        assertEquals("Effect Fifties", effectFifties, effectList.get(2));
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
-        assertEquals("Aspect Ratio", MediaProperties.ASPECT_RATIO_4_3,
-            mVideoEditor.getAspectRatio());
-
-        final long storyboardDuration = mVideoEditor.getDuration() ;
-        validatePreviewProgress(0, (int)(storyboardDuration/2), false, (storyboardDuration/2));
-
-        assertEquals("Removing Effect : Negative", effectNegative,
-            mediaVideoItem1.removeEffect(effectNegative.getId()));
-
-        effectList = mediaVideoItem1.getAllEffects();
-
-        assertEquals("Effect List Size", 2, effectList.size());
-        assertEquals("Effect Green", effectGreen, effectList.get(0));
-        assertEquals("Effect Fifties", effectFifties, effectList.get(1));
-
-        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     *To test Preview : Preview of current Transitions applied (with multiple
-     * generatePreview)
-     */
-    @LargeTest
-    public void testPreviewWithTransition() throws Exception {
-
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_10fps_96kbps_0_25.3gp";
-        final String imageItemFileName1 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
-        final String maskFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-        previewStart = false;
-        previewStop = false;
-        previewError = false;
-
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFileName1, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem2.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionCrossfade transition1And2CrossFade =
-            mVideoEditorHelper.createTCrossFade("transition_1_2_CF",
-                mediaVideoItem1, mediaImageItem1, 2000,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition1And2CrossFade);
-
-        final TransitionAlpha transition2And3Alpha =
-            mVideoEditorHelper.createTAlpha("transition_2_3", mediaImageItem1,
-                mediaVideoItem2, 4000, Transition.BEHAVIOR_SPEED_UP,
-                maskFilename, 50, true);
-        mVideoEditor.addTransition(transition2And3Alpha);
-
-        final TransitionFadeBlack transition1FadeBlack =
-            mVideoEditorHelper.createTFadeBlack("transition_1FB", null,
-                mediaVideoItem1, 2000, Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition1FadeBlack);
-
-        List<Transition> transitionList = mVideoEditor.getAllTransitions();
-        assertEquals("Transition List Size", 3, transitionList.size());
-        assertEquals("Transition 1", transition1And2CrossFade,
-            transitionList.get(0));
-        assertEquals("Transition 2", transition2And3Alpha, transitionList.get(1));
-        assertEquals("Transition 3", transition1FadeBlack, transitionList.get(2));
-
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_3_2);
-
-        final int[] progressValues = new int[300];
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            int i = 0;
-
-            public void onProgress(Object item, int action, int progress) {
-                if (item instanceof TransitionCrossfade) {
-                    progressValues[i] = progress;
-                    assertEquals("Object", item, transition1And2CrossFade);
-                    assertEquals("Action", action,
-                        MediaProcessingProgressListener.ACTION_ENCODE);
-                } else if (item instanceof TransitionAlpha) {
-                    progressValues[i] = progress;
-                    assertEquals("Object", item, transition2And3Alpha);
-                    assertEquals("Action", action,
-                        MediaProcessingProgressListener.ACTION_ENCODE);
-                } else if (item instanceof TransitionFadeBlack) {
-                    progressValues[i] = progress;
-                    assertEquals("Object", item, transition1FadeBlack);
-                    assertEquals("Action", action,
-                        MediaProcessingProgressListener.ACTION_ENCODE);
-                }
-                i++;
-            }
-        });
-
-        mVideoEditorHelper.checkProgressCBValues(progressValues);
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-        /* As transition takes more time buffer of 10 sec is added */
-        long waitingTime = minWaitingTime + 10000 + 10000;
-
-        blockTillPreviewCompletes.acquire();
-        try {
-        mVideoEditor.startPreview(surfaceHolder, 0, 10000, false, 1,
-            new PreviewProgressListener() {
-            public void onProgress(VideoEditor videoEditor, long timeMs,
-                OverlayData overlayData) {
-                }
-                public void onStart(VideoEditor videoEditor) {
-                    setPreviewStart();
-                }
-                public void onStop(VideoEditor videoEditor) {
-                    setPreviewStop();
-                    blockTillPreviewCompletes.release();
-                }
-                public void onError(VideoEditor videoEditor, int error) {
-                    setPreviewError();
-                    blockTillPreviewCompletes.release();
-                }
-        });
-        } catch (Exception e) {
-            blockTillPreviewCompletes.release();
-        }
-        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
-        mVideoEditor.stopPreview();
-        blockTillPreviewCompletes.release();
-        assertTrue("Preview Failed to start", previewStart);
-        assertTrue("Preview Failed to stop", previewStop);
-        assertFalse("Preview Error occurred", previewError);
-
-        assertEquals("Removing Transition " + transition1And2CrossFade.getId(),
-            transition1And2CrossFade,
-            mVideoEditor.removeTransition(transition1And2CrossFade.getId()));
-        transitionList = mVideoEditor.getAllTransitions();
-        assertEquals("Transition List Size", 2, transitionList.size());
-        assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
-        assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
-
-        validatePreviewProgress(0, -1, false, mVideoEditor.getDuration());
-
-
-        final TransitionSliding transition1And2Sliding =
-            mVideoEditorHelper.createTSliding("transition_1_2Sliding",
-                mediaVideoItem1, mediaImageItem1, 4000,
-                Transition.BEHAVIOR_MIDDLE_FAST,
-                TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
-        mVideoEditor.addTransition(transition1And2Sliding);
-
-        transitionList = mVideoEditor.getAllTransitions();
-        assertEquals("Transition List Size", 3, transitionList.size());
-        assertEquals("Transition 1", transition2And3Alpha, transitionList.get(0));
-        assertEquals("Transition 2", transition1FadeBlack, transitionList.get(1));
-        assertEquals("Transition 3", transition1And2Sliding,
-            transitionList.get(2));
-
-        validatePreviewProgress(5000, -1, false, (mVideoEditor.getDuration()));
-
-    }
-
-    /**
-     * To test Preview : Preview of current Overlay applied
-     */
-    @LargeTest
-    public void testPreviewWithOverlay() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String overlayFilename1 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final String overlayFilename2 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay2.png";
-        final int previewFrom = 5000;
-        final int previewTo = 10000;
-        final boolean previewLoop = false;
-        final int previewCallbackFrameCount = 1;
-        final int setAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        boolean flagForException = false;
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-        mediaVideoItem.setExtractBoundaries(0, 10000);
-
-        final Bitmap mBitmap1 =  mVideoEditorHelper.getBitmap(overlayFilename1,
-            640, 480);
-        final OverlayFrame overlayOnMvi1 =
-            mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi1",
-                mBitmap1, 0, 5000);
-        mediaVideoItem.addOverlay(overlayOnMvi1);
-
-        final Bitmap mBitmap2 =  mVideoEditorHelper.getBitmap(overlayFilename2,
-            640, 480);
-        final OverlayFrame overlayOnMvi2 =
-            mVideoEditorHelper.createOverlay(mediaVideoItem, "OverlayOnMvi2",
-                mBitmap2, 5000, 9000);
-        mediaVideoItem.addOverlay(overlayOnMvi2);
-
-        List<Overlay> overlayList = mediaVideoItem.getAllOverlays();
-        assertEquals("Overlay Size", 2, overlayList.size());
-        assertEquals("Overlay 1", overlayOnMvi1, overlayList.get(0));
-        assertEquals("Overlay 2", overlayOnMvi2, overlayList.get(1));
-
-        mVideoEditor.setAspectRatio(setAspectRatio);
-
-        validatePreviewProgress(0 /* previewFrom */, -1, previewLoop,
-            mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test Preview : Preview of current Trim applied (with default aspect
-     * ratio)
-     */
-    @LargeTest
-    public void testPreviewWithTrim() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, MediaItem.RENDERING_MODE_CROPPING);
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        boolean flagForException = false;
-        previewStart = false;
-        previewStop = false;
-        mediaVideoItem.setExtractBoundaries(mediaVideoItem.getDuration() / 2,
-            mediaVideoItem.getDuration());
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        validatePreviewProgress(1000, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test Preview : Preview of current work having Overlay and Effect
-     * applied
-     */
-
-    @LargeTest
-    public void testPreviewWithOverlayEffectKenBurn() throws Exception {
-
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final String overlayFilename = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaImageItem mediaImageItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFileName, 10000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem2);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem3);
-
-        final EffectColor effectColor =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem1, "Effect1",
-                1000, 3000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-        mediaVideoItem1.addEffect(effectColor);
-
-        final Rect startRect = new Rect((mediaImageItem2.getHeight() / 3),
-            (mediaImageItem2.getWidth() / 3), (mediaImageItem2.getHeight() / 2),
-            (mediaImageItem2.getWidth() / 2));
-        final Rect endRect = new Rect(0, 0, mediaImageItem2.getWidth(),
-            mediaImageItem2.getHeight());
-
-        final EffectKenBurns kbeffectOnMI2 = new EffectKenBurns(mediaImageItem2,
-            "KBOnM2", startRect, endRect, 0, 10000);
-        assertNotNull("EffectKenBurns", kbeffectOnMI2);
-        mediaImageItem2.addEffect(kbeffectOnMI2);
-
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFilename,
-            640, 480);
-        final OverlayFrame overlayFrame =
-            mVideoEditorHelper.createOverlay(mediaVideoItem3, "OverlayID",
-                mBitmap, (mediaImageItem2.getDuration() / 4),
-                (mediaVideoItem3.getDuration() / 3));
-        mediaVideoItem3.addOverlay(overlayFrame);
-
-        validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     *To test Preview : Export during preview
-     */
-    @LargeTest
-    public void testPreviewDuringExport() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        previewStart = false;
-        previewStop = false;
-        previewError = false;
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        long waitingTime = minWaitingTime + mVideoEditor.getDuration();
-
-
-        blockTillPreviewCompletes.acquire();
-                    final String fileName = mVideoEditor.getPath() + "/test.3gp";
-                    final int height = MediaProperties.HEIGHT_480;
-                    final int bitrate = MediaProperties.BITRATE_512K;
-
-            try {
-                mVideoEditor.export(fileName, height, bitrate,
-                    new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve,
-                            String outFileName,int progress) {
-
-                        }
-                    });
-            } catch (IOException e) {
-                assertTrue("UnExpected Error in Export" +
-                    e.toString(), false);
-            }
-
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-        try {
-
-            mVideoEditor.startPreview(surfaceHolder, 5000, -1, false, 1,
-                new PreviewProgressListener() {
-
-                    public void onProgress(VideoEditor videoEditor, long timeMs,
-                        OverlayData overlayData) {
-                    }
-                public void onStart(VideoEditor videoEditor) {
-                    setPreviewStart();
-                }
-                public void onStop(VideoEditor videoEditor) {
-                    setPreviewStop();
-                    blockTillPreviewCompletes.release();
-                }
-                public void onError(VideoEditor videoEditor, int error) {
-                    setPreviewError();
-                    blockTillPreviewCompletes.release();
-                }
-            });
-
-        } catch (Exception e) {
-            blockTillPreviewCompletes.release();
-        }
-        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
-        mVideoEditor.stopPreview();
-        assertTrue("Preview Failed to start", previewStart);
-        assertTrue("Preview Failed to stop", previewStop);
-        assertFalse("Preview Error occurred", previewError);
-
-        blockTillPreviewCompletes.release();
-    }
-
-    /**
-     * To test Preview : Preview of current Effects applied (with from time >
-     * total duration)
-     */
-    @LargeTest
-    public void testPreviewWithDurationGreaterThanMediaDuration()
-        throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_192kbps_1_5.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        boolean flagForException = false;
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName, renderingMode);
-        try {
-            mediaVideoItem1.setExtractBoundaries(0, 20000);
-        } catch (Exception e) {
-            assertTrue("Exception during setExtract Boundaries", false);
-        }
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-        long waitingTime = minWaitingTime + (mVideoEditor.getDuration() - 30000);
-        if(waitingTime < 0)
-        {
-            waitingTime = minWaitingTime;
-        }
-
-        blockTillPreviewCompletes.acquire();
-        try {
-            mVideoEditor.startPreview(surfaceHolder, 30000, -1, true, 1,
-            new PreviewProgressListener() {
-                public void onProgress(VideoEditor videoEditor, long timeMs,
-                    OverlayData overlayData) {
-            }
-                public void onStart(VideoEditor videoEditor) {
-                    setPreviewStart();
-                }
-                public void onStop(VideoEditor videoEditor) {
-                    setPreviewStop();
-                    blockTillPreviewCompletes.release();
-                }
-                public void onError(VideoEditor videoEditor, int error) {
-                    setPreviewError();
-                    blockTillPreviewCompletes.release();
-                }
-        });
-
-        } catch (IllegalArgumentException e) {
-            blockTillPreviewCompletes.release();
-            flagForException = true;
-        }
-        blockTillPreviewCompletes.tryAcquire(waitingTime, TimeUnit.MILLISECONDS);
-        assertTrue("Expected Error in Preview", flagForException);
-        mVideoEditor.stopPreview();
-        blockTillPreviewCompletes.release();
-    }
-
-    /**
-     * To test Preview : Preview of current Effects applied (with Render Preview
-     * Frame)
-     */
-    @LargeTest
-    public void testPreviewWithRenderPreviewFrame() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final Semaphore blockTillPreviewCompletes = new Semaphore(1);
-        boolean flagForException = false;
-        OverlayData overlayData1 = new OverlayData();
-        previewStart = false;
-        previewStop = false;
-
-        final String overlayFilename1 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor,
-            "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final EffectColor effectPink =
-            mVideoEditorHelper.createEffectItem(mediaVideoItem,
-                "effectNegativeOnMvi", 1000, 3000, EffectColor.TYPE_COLOR,
-                 EffectColor.PINK);
-        mediaVideoItem.addEffect(effectPink);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-
-        assertEquals("Render preview Frame at 5 Sec", 5000,
-            mVideoEditor.renderPreviewFrame(surfaceHolder, 5000,
-            overlayData1));
-
-        assertEquals("Render preview Frame at 7 Sec", 7000,
-            mVideoEditor.renderPreviewFrame(surfaceHolder, 7000,
-            overlayData1));
-
-        validatePreviewProgress(5000, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test Preview : Preview of current work from selected jump location
-     * till end with Audio Track
-     */
-    @LargeTest
-    public void testPreviewWithEndAudioTrack() throws Exception {
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String imageItemFilename2 = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final String audioFilename = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-
-        boolean flagForException = false;
-        previewStart = false;
-        previewStop = false;
-        final MediaImageItem mediaImageItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                imageItemFilename1, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem1);
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem.setExtractBoundaries(1000, 8000);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaImageItem mediaImageItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                imageItemFilename2, 7000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem2);
-
-        final AudioTrack audioTrack =
-            mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        List<AudioTrack> audioList = mVideoEditor.getAllAudioTracks();
-        assertEquals("Audio Track List size", 1, audioList.size());
-        assertEquals("Audio Track", audioTrack, audioList.get(0));
-        mVideoEditor.setAspectRatio(MediaProperties.ASPECT_RATIO_4_3);
-
-        validatePreviewProgress(10000, -1, false, mVideoEditor.getDuration());
-    }
-
-    /**
-     * To test render Preview Frame
-     */
-    @LargeTest
-    public void testRenderPreviewFrame() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH
-            + "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH
-            + "MPEG4_SP_800x480_515kbps_15fps_AMR_NB_8KHz_12.2kbps_m_0_26.mp4";
-        final String videoItemFileName3 = INPUT_FILE_PATH
-            + "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String imageItemFilename1 = INPUT_FILE_PATH
-            + "IMG_1600x1200.jpg";
-        final String imageItemFilename2 = INPUT_FILE_PATH
-            + "IMG_176x144.jpg";
-        final String audioFilename = INPUT_FILE_PATH
-            + "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        OverlayData overlayData1 = new OverlayData();
-        previewStart = false;
-        previewStop = false;
-        final MediaVideoItem mediaVideoItem1 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFileName1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                videoItemFileName2, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 4,
-            mediaVideoItem2.getDuration() / 2);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final MediaVideoItem mediaVideoItem3 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m3",
-                videoItemFileName3, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem1.setExtractBoundaries(mediaVideoItem2.getDuration() / 2,
-            mediaVideoItem2.getDuration());
-        mVideoEditor.addMediaItem(mediaVideoItem3);
-
-        final MediaImageItem mediaImageItem4 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m4",
-                imageItemFilename1, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        final MediaImageItem mediaImageItem5 =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m5",
-                imageItemFilename2, 5000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-
-        List<MediaItem> mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 3, mediaList.size());
-
-        mVideoEditor.insertMediaItem(mediaImageItem4, mediaVideoItem2.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 4, mediaList.size());
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
-        assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(3));
-
-        mVideoEditor.insertMediaItem(mediaImageItem5, mediaImageItem4.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 5, mediaList.size());
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(0));
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(1));
-        assertEquals("Media item 4", mediaImageItem4, mediaList.get(2));
-        assertEquals("Media item 5", mediaImageItem5, mediaList.get(3));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
-        mVideoEditor.moveMediaItem(mediaVideoItem1.getId(),
-            mediaImageItem5.getId());
-        mediaList = mVideoEditor.getAllMediaItems();
-        assertEquals("Media Item List Size", 5, mediaList.size());
-        assertEquals("Media item 2", mediaVideoItem2, mediaList.get(0));
-        assertEquals("Media item 4", mediaImageItem4, mediaList.get(1));
-        assertEquals("Media item 5", mediaImageItem5, mediaList.get(2));
-        assertEquals("Media item 1", mediaVideoItem1, mediaList.get(3));
-        assertEquals("Media item 3", mediaVideoItem3, mediaList.get(4));
-
-        final TransitionCrossfade transition2And4CrossFade =
-            mVideoEditorHelper.createTCrossFade("transition2And4CrossFade",
-                mediaVideoItem2, mediaImageItem4, 2000,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition2And4CrossFade);
-
-        final TransitionCrossfade transition1And3CrossFade =
-            mVideoEditorHelper.createTCrossFade("transition1And3CrossFade",
-                mediaVideoItem1, mediaVideoItem3, 5000,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(transition1And3CrossFade);
-
-        final AudioTrack audioTrack =
-            mVideoEditorHelper.createAudio(mVideoEditor, "a1", audioFilename);
-        audioTrack.setExtractBoundaries(0, 2000);
-        mVideoEditor.addAudioTrack(audioTrack);
-
-        audioTrack.enableLoop();
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-
-        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/4, overlayData1);
-        Thread.sleep(1000);
-        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration()/2, overlayData1);
-        Thread.sleep(1000);
-        mVideoEditor.renderPreviewFrame(surfaceHolder, mVideoEditor.getDuration(), overlayData1);
-
-    }
-
-    /**
-     * To Test Preview : Without any Media Items in the story Board
-     */
-    @LargeTest
-    public void testStartPreviewWithoutMediaItems() throws Exception {
-        boolean flagForException = false;
-
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-        try{
-            mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
-                new PreviewProgressListener() {
-                    public void onProgress(VideoEditor videoEditor, long timeMs,
-                        OverlayData overlayData) {
-                    }
-                    public void onStart(VideoEditor videoEditor) {
-                        setPreviewStart();
-                    }
-                    public void onStop(VideoEditor videoEditor) {
-                        setPreviewStop();
-                    }
-                    public void onError(VideoEditor videoEditor, int error) {
-                        setPreviewError();
-                    }
-            });
-        }catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Preview without Media Items", flagForException);
-    }
-
-    /**
-     * To Test Preview : Add Media and Remove Media Item (Without any Media
-     * Items in the story Board)
-     */
-    @LargeTest
-    public void testStartPreviewAddRemoveMediaItems() throws Exception {
-        final String videoItemFilename1 = INPUT_FILE_PATH
-            + "H263_profile0_176x144_15fps_256kbps_AACLC_32kHz_128kbps_s_0_26.3gp";
-        final String imageItemFilename1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String alphaFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-        boolean flagForException = false;
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m1",
-                videoItemFilename1, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mediaVideoItem.setExtractBoundaries(0, 15000);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaImageItem mediaImageItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor, "m2",
-                imageItemFilename1, 15000, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final TransitionAlpha transition1And2 =
-            mVideoEditorHelper.createTAlpha("transition", mediaVideoItem,
-                mediaImageItem, 3000, Transition.BEHAVIOR_SPEED_UP,
-                alphaFilename, 10, false);
-        mVideoEditor.addTransition(transition1And2);
-
-        final EffectColor effectColor =
-            mVideoEditorHelper.createEffectItem(mediaImageItem, "effect", 5000,
-                3000, EffectColor.TYPE_COLOR, EffectColor.PINK);
-        mediaImageItem.addEffect(effectColor);
-
-        assertEquals("removing Media item 1", mediaVideoItem,
-            mVideoEditor.removeMediaItem(mediaVideoItem.getId()));
-        assertEquals("removing Media item 2", mediaImageItem,
-            mVideoEditor.removeMediaItem(mediaImageItem.getId()));
-
-        try{
-            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-            final SurfaceHolder surfaceHolder =
-                MediaFrameworkTest.mSurfaceView.getHolder();
-            mVideoEditor.startPreview(surfaceHolder, 0, -1, false, 1,
-                new PreviewProgressListener() {
-                    public void onProgress(VideoEditor videoEditor, long timeMs,
-                        OverlayData overlayData) {
-                    }
-                    public void onStart(VideoEditor videoEditor) {
-                        setPreviewStart();
-                    }
-                    public void onStop(VideoEditor videoEditor) {
-                        setPreviewStop();
-                    }
-                    public void onError(VideoEditor videoEditor, int error) {
-                        setPreviewError();
-                    }
-            });
-        }catch (IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue("Preview with removed Media Items", flagForException);
-
-    }
-
-    /**
-     * To test Preview : Preview of current Effects applied (with Render Preview
-     * Frame)
-     */
-    @LargeTest
-    public void testPreviewWithRenderPreviewFrameWithoutGenerate() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        boolean flagForException = false;
-        long duration = 0;
-        OverlayData overlayData1 = new OverlayData();
-
-        final MediaVideoItem mediaVideoItem =
-            mVideoEditorHelper.createMediaItem(mVideoEditor,
-            "m1", videoItemFileName, MediaItem.RENDERING_MODE_BLACK_BORDER);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final SurfaceHolder surfaceHolder =
-            MediaFrameworkTest.mSurfaceView.getHolder();
-        duration = mVideoEditor.getDuration();
-        /* RenderPreviewFrame returns -1 to indicate last frame */
-        try {
-            mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
-            overlayData1);
-        } catch ( IllegalStateException e) {
-            flagForException = true;
-        }
-        assertTrue (" Render Preview Frame without generate", flagForException);
-        duration = mVideoEditor.getDuration() + 1000;
-        try {
-            mVideoEditor.renderPreviewFrame(surfaceHolder, duration,
-            overlayData1);
-        } catch ( IllegalArgumentException e) {
-            flagForException = true;
-        }
-        assertTrue (" Preview time greater than duration", flagForException);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
index d157478..89886ef 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraBinderTest.java
@@ -23,6 +23,7 @@
 import android.hardware.IProCameraCallbacks;
 import android.hardware.IProCameraUser;
 import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureResultExtras;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.impl.CameraMetadataNative;
@@ -151,21 +152,50 @@
 
     static class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
 
-        @Override
-        public void onCameraError(int errorCode) {
-        }
-
-        @Override
-        public void onCameraIdle() {
-        }
-
-        @Override
-        public void onCaptureStarted(int requestId, long timestamp) {
-        }
-
-        @Override
-        public void onResultReceived(int frameId, CameraMetadataNative result)
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
+         * android.hardware.camera2.CaptureResultExtras)
+         */
+        public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
                 throws RemoteException {
+            // TODO Auto-generated method stub
+
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
+         * android.hardware.camera2.CaptureResultExtras, long)
+         */
+        public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
+                throws RemoteException {
+            // TODO Auto-generated method stub
+
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
+         * android.hardware.camera2.impl.CameraMetadataNative,
+         * android.hardware.camera2.CaptureResultExtras)
+         */
+        public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras)
+                throws RemoteException {
+            // TODO Auto-generated method stub
+
+        }
+
+        /*
+         * (non-Javadoc)
+         * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
+         */
+        public void onCameraIdle() throws RemoteException {
+            // TODO Auto-generated method stub
+
         }
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
index 5f3ba74..74ce997 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/integration/CameraDeviceBinderTest.java
@@ -21,6 +21,7 @@
 import android.hardware.camera2.CameraMetadata;
 import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CaptureRequest;
+import android.hardware.camera2.CaptureResultExtras;
 import android.hardware.camera2.ICameraDeviceCallbacks;
 import android.hardware.camera2.ICameraDeviceUser;
 import android.hardware.camera2.impl.CameraMetadataNative;
@@ -84,20 +85,50 @@
 
     public class DummyCameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
 
-        @Override
-        public void onCameraError(int errorCode) {
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onCameraError(int,
+         * android.hardware.camera2.CaptureResultExtras)
+         */
+        public void onCameraError(int errorCode, CaptureResultExtras resultExtras)
+                throws RemoteException {
+            // TODO Auto-generated method stub
+
         }
 
-        @Override
-        public void onCameraIdle() {
+        /*
+         * (non-Javadoc)
+         * @see android.hardware.camera2.ICameraDeviceCallbacks#onCameraIdle()
+         */
+        public void onCameraIdle() throws RemoteException {
+            // TODO Auto-generated method stub
+
         }
 
-        @Override
-        public void onCaptureStarted(int requestId, long timestamp) {
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onCaptureStarted(
+         * android.hardware.camera2.CaptureResultExtras, long)
+         */
+        public void onCaptureStarted(CaptureResultExtras resultExtras, long timestamp)
+                throws RemoteException {
+            // TODO Auto-generated method stub
+
         }
 
-        @Override
-        public void onResultReceived(int frameId, CameraMetadataNative result) {
+        /*
+         * (non-Javadoc)
+         * @see
+         * android.hardware.camera2.ICameraDeviceCallbacks#onResultReceived(
+         * android.hardware.camera2.impl.CameraMetadataNative,
+         * android.hardware.camera2.CaptureResultExtras)
+         */
+        public void onResultReceived(CameraMetadataNative result, CaptureResultExtras resultExtras)
+                throws RemoteException {
+            // TODO Auto-generated method stub
+
         }
     }
 
@@ -139,7 +170,7 @@
     }
 
     private int submitCameraRequest(CaptureRequest request, boolean streaming) throws Exception {
-        int requestId = mCameraUser.submitRequest(request, streaming);
+        int requestId = mCameraUser.submitRequest(request, streaming, null);
         assertTrue(
                 "Request IDs should be non-negative (expected: >= 0, actual: " + requestId + ")",
                 requestId >= 0);
@@ -252,13 +283,13 @@
 
         CaptureRequest.Builder builder = createDefaultBuilder(/* needStream */false);
         CaptureRequest request1 = builder.build();
-        int status = mCameraUser.submitRequest(request1, /* streaming */false);
+        int status = mCameraUser.submitRequest(request1, /* streaming */false, null);
         assertEquals("Expected submitRequest to return BAD_VALUE " +
                 "since we had 0 surface targets set.", CameraBinderTestUtils.BAD_VALUE, status);
 
         builder.addTarget(mSurface);
         CaptureRequest request2 = builder.build();
-        status = mCameraUser.submitRequest(request2, /* streaming */false);
+        status = mCameraUser.submitRequest(request2, /* streaming */false, null);
         assertEquals("Expected submitRequest to return BAD_VALUE since " +
                 "the target surface wasn't registered with createStream.",
                 CameraBinderTestUtils.BAD_VALUE, status);
@@ -292,15 +323,15 @@
         assertNotSame("Request IDs should be unique for multiple requests", requestId1,
                 requestIdStreaming);
 
-        int status = mCameraUser.cancelRequest(-1);
+        int status = mCameraUser.cancelRequest(-1, null);
         assertEquals("Invalid request IDs should not be cancellable",
                 CameraBinderTestUtils.BAD_VALUE, status);
 
-        status = mCameraUser.cancelRequest(requestId1);
+        status = mCameraUser.cancelRequest(requestId1, null);
         assertEquals("Non-streaming request IDs should not be cancellable",
                 CameraBinderTestUtils.BAD_VALUE, status);
 
-        status = mCameraUser.cancelRequest(requestIdStreaming);
+        status = mCameraUser.cancelRequest(requestIdStreaming, null);
         assertEquals("Streaming request IDs should be cancellable", CameraBinderTestUtils.NO_ERROR,
                 status);
 
@@ -339,7 +370,7 @@
             CameraBinderTestUtils.INVALID_OPERATION, status);
 
         // Test good case, waitUntilIdle when there is no active repeating request
-        status = mCameraUser.cancelRequest(requestIdStreaming);
+        status = mCameraUser.cancelRequest(requestIdStreaming, null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
         status = mCameraUser.waitUntilIdle();
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
@@ -351,16 +382,14 @@
         CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
 
         // Test both single request and streaming request.
-        int requestId1 = submitCameraRequest(request, /* streaming */false);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onResultReceived(
-                eq(requestId1),
-                argThat(matcher));
+                argThat(matcher),
+                any(CaptureResultExtras.class));
 
-        int streamingId = submitCameraRequest(request, /* streaming */true);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                 .onResultReceived(
-                        eq(streamingId),
-                        argThat(matcher));
+                        argThat(matcher),
+                        any(CaptureResultExtras.class));
     }
 
     @SmallTest
@@ -372,13 +401,13 @@
         // Test both single request and streaming request.
         int requestId1 = submitCameraRequest(request, /* streaming */false);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).times(1)).onCaptureStarted(
-                eq(requestId1),
+                any(CaptureResultExtras.class),
                 anyLong());
 
         int streamingId = submitCameraRequest(request, /* streaming */true);
         verify(mMockCb, timeout(WAIT_FOR_COMPLETE_TIMEOUT_MS).atLeast(NUM_CALLBACKS_CHECKED))
                 .onCaptureStarted(
-                        eq(streamingId),
+                        any(CaptureResultExtras.class),
                         timestamps.capture());
 
         long timestamp = 0; // All timestamps should be larger than 0.
@@ -401,7 +430,7 @@
         SystemClock.sleep(WAIT_FOR_WORK_MS);
 
         // Cancel and make sure we eventually quiesce
-        status = mCameraUser.cancelRequest(streamingId);
+        status = mCameraUser.cancelRequest(streamingId, null);
 
         verify(mMockCb, timeout(WAIT_FOR_IDLE_TIMEOUT_MS).times(1)).onCameraIdle();
 
@@ -422,14 +451,14 @@
         int status;
 
         // Initial flush should work
-        status = mCameraUser.flush();
+        status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
         // Then set up a stream
         CaptureRequest request = createDefaultBuilder(/* needStream */true).build();
 
         // Flush should still be a no-op, really
-        status = mCameraUser.flush();
+        status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
         // Submit a few capture requests
@@ -440,7 +469,7 @@
         int requestId5 = submitCameraRequest(request, /* streaming */false);
 
         // Then flush and wait for idle
-        status = mCameraUser.flush();
+        status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
         verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(1)).onCameraIdle();
@@ -452,7 +481,7 @@
         SystemClock.sleep(WAIT_FOR_WORK_MS);
 
         // Then flush and wait for the idle callback
-        status = mCameraUser.flush();
+        status = mCameraUser.flush(null);
         assertEquals(CameraBinderTestUtils.NO_ERROR, status);
 
         verify(mMockCb, timeout(WAIT_FOR_FLUSH_TIMEOUT_MS).times(2)).onCameraIdle();
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
deleted file mode 100644
index d15a535..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/performance/VideoEditorPerformance.java
+++ /dev/null
@@ -1,1073 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.performance;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileWriter;
-import java.io.Writer;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-
-import android.util.Log;
-
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-
-/**
- * Junit / Instrumentation - performance measurement for media player and
- * recorder
- */
-public class VideoEditorPerformance extends
-    ActivityInstrumentationTestCase<MediaFrameworkTest> {
-
-    private final String TAG = "VideoEditorPerformance";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
-        "VideoEditorPerformance.txt";
-
-    public VideoEditorPerformance() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-    }
-
-    private final String PROJECT_CLASS_NAME =
-        "android.media.videoeditor.VideoEditorImpl";
-    private VideoEditor mVideoEditor;
-    private VideoEditorHelper mVideoEditorHelper;
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath =
-            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    private void writeTimingInfo(String testCaseName, String[] information)
-        throws Exception {
-        File outFile = new File(VIDEOEDITOR_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(outFile, true));
-        output.write(testCaseName + "\n\t");
-        for (int i = 0; i < information.length; i++) {
-            output.write(information[i]);
-        }
-        output.write("\n\n");
-        output.close();
-    }
-
-    private final int NUM_OF_ITERATIONS=20;
-
-    private int calculateTimeTaken(long beginTime, int numIterations)
-        throws Exception {
-        final long duration2 = SystemClock.uptimeMillis();
-        final long durationToCreateMediaItem = (duration2 - beginTime);
-        final int timeTaken1 = (int)(durationToCreateMediaItem / numIterations);
-        return (timeTaken1);
-    }
-
-    private void createVideoItems(MediaVideoItem[] mediaVideoItem,
-        String videoItemFileName, int renderingMode, int startTime, int endTime) throws Exception {
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-                mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
-                    videoItemFileName, renderingMode);
-                mediaVideoItem[i].setExtractBoundaries(startTime, endTime);
-            } catch (Exception e1) {
-                assertTrue(
-                    "Can not create an object of Video Item with file name = "
-                    + videoItemFileName + "------ID:m" + i + "       Issue = "
-                    + e1.toString(), false);
-            }
-        }
-    }
-
-    private void addVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-                mVideoEditor.addMediaItem(mediaVideoItem[i]);
-            } catch (Exception e1) {
-                assertTrue(
-                    "Can not add an object of Video Item with ID:m" + i +
-                    "    Issue = " + e1.toString(), false);
-            }
-        }
-    }
-
-    private void removeVideoItems(MediaVideoItem[] mediaVideoItem) throws Exception {
-            for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-            mVideoEditor.removeMediaItem(mediaVideoItem[i].getId());
-            } catch (Exception e1) {
-                assertTrue(
-                    "Can not Remove an object of Video Item with ID:m" + i +
-                    "    Issue = " + e1.toString(), false);
-            }
-        }
-    }
-
-    private void createImageItems(MediaImageItem[] mIi,
-        String imageItemFileName, int renderingMode, int duration) throws Exception {
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-                mIi[i] = new MediaImageItem(mVideoEditor, "m" + i,
-                    imageItemFileName, duration, renderingMode);
-            } catch (Exception e1) {
-                assertTrue( " Cannot create Image Item", false);
-            }
-        }
-    }
-
-    private void addImageItems(MediaImageItem[] mIi) throws Exception {
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-                mVideoEditor.addMediaItem(mIi[i]);
-            } catch (Exception e1) {
-                assertTrue("Cannot add Image item", false);
-            }
-        }
-    }
-
-    private void removeImageItems(MediaImageItem[] mIi) throws Exception {
-            for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            try {
-            mVideoEditor.removeMediaItem(mIi[i].getId());
-            } catch (Exception e1) {
-                assertTrue("Cannot remove image item", false);
-            }
-        }
-    }
-    /**
-     * To test the performance of adding and removing the video media item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceAddRemoveVideoItem() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int videoItemStartTime = 0;
-        final int videoItemEndTime = 5000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[3];
-        final MediaVideoItem[] mediaVideoItem =
-            new MediaVideoItem[NUM_OF_ITERATIONS];
-        int timeTaken = 0;
-        long startTime = 0;
-
-        /** Time Take for creation of Media Video Item */
-        startTime = SystemClock.uptimeMillis();
-        createVideoItems(mediaVideoItem, videoItemFileName, renderingMode,
-            videoItemStartTime, videoItemEndTime);
-
-        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
-        loggingInfo[0] = "Time taken to Create Media Video Item :" +
-            timeTaken;
-
-        /** Time Take for Addition of Media Video Item */
-        startTime = SystemClock.uptimeMillis();
-        addVideoItems(mediaVideoItem);
-        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
-        loggingInfo[1] = "\n\tTime taken to Add  Media Video Item :"
-            + timeTaken;
-
-        /** Time Take for Removal of Media Video Item */
-        startTime = SystemClock.uptimeMillis();
-        removeVideoItems(mediaVideoItem);
-        timeTaken = calculateTimeTaken (startTime, NUM_OF_ITERATIONS);
-        loggingInfo[2] = "\n\tTime taken to remove  Media Video Item :"
-            + timeTaken;
-
-        writeTimingInfo("testPerformanceAddRemoveVideoItem (in mSec)", loggingInfo);
-    }
-
-    /**
-     * To test the performance of adding and removing the image media item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceAddRemoveImageItem() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final int imageItemDuration = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[3];
-        final MediaImageItem[] mediaImageItem =
-            new MediaImageItem[NUM_OF_ITERATIONS];
-        int timeTaken = 0;
-
-        long beginTime = SystemClock.uptimeMillis();
-        createImageItems(mediaImageItem, imageItemFileName, renderingMode,
-            imageItemDuration);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[0] = "Time taken to Create  Media Image Item :" +
-            timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        addImageItems(mediaImageItem);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[1] = "\n\tTime taken to add  Media Image Item :" +
-            timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        removeImageItems(mediaImageItem);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[2] = "\n\tTime taken to remove  Media Image Item :"
-            + timeTaken;
-
-        writeTimingInfo("testPerformanceAddRemoveImageItem (in mSec)",
-            loggingInfo);
-    }
-
-    /**
-     * To test the performance of adding and removing the transition
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceAddRemoveTransition() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-        "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int videoItemStartTime1 = 0;
-        final int videoItemEndTime1 = 20000;
-        final String videoItemFileName2 = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int videoItemStartTime2 = 0;
-        final int videoItemEndTime2 = 20000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int transitionDuration = 5000;
-        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
-        final String[] loggingInfo = new String[3];
-        int timeTaken = 0;
-
-        final MediaVideoItem[] mediaVideoItem =
-            new MediaVideoItem[(NUM_OF_ITERATIONS *10) + 1];
-
-        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i+=2) {
-            try {
-                mediaVideoItem[i] = new MediaVideoItem(mVideoEditor, "m" + i,
-                    videoItemFileName1, renderingMode);
-                mediaVideoItem[i+1] = new MediaVideoItem(mVideoEditor,
-                    "m" + (i+1), videoItemFileName2, renderingMode);
-                mediaVideoItem[i].setExtractBoundaries(videoItemStartTime1,
-                    videoItemEndTime1);
-                mediaVideoItem[i+1].setExtractBoundaries(videoItemStartTime2,
-                    videoItemEndTime2);
-            } catch (Exception e1) {
-                assertTrue("Can not create Video Object Item with file name = "
-                    + e1.toString(), false);
-            }
-            mVideoEditor.addMediaItem(mediaVideoItem[i]);
-            mVideoEditor.addMediaItem(mediaVideoItem[i+1]);
-        }
-        mediaVideoItem[(NUM_OF_ITERATIONS *10)] = new MediaVideoItem(mVideoEditor,
-            "m" + (NUM_OF_ITERATIONS *10), videoItemFileName1, renderingMode);
-        mediaVideoItem[(NUM_OF_ITERATIONS *10)].setExtractBoundaries(
-            videoItemStartTime1, videoItemEndTime1);
-        mVideoEditor.addMediaItem(mediaVideoItem[(NUM_OF_ITERATIONS *10)]);
-        final TransitionCrossfade tranCrossfade[] =
-            new TransitionCrossfade[(NUM_OF_ITERATIONS *10)];
-
-        long beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
-            tranCrossfade[i] = new TransitionCrossfade("transition" + i,
-                mediaVideoItem[i], mediaVideoItem[i+1], transitionDuration,
-                transitionBehavior);
-        }
-        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
-        loggingInfo[0] = "Time taken to Create CrossFade Transition :" +
-            timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
-            mVideoEditor.addTransition(tranCrossfade[i]);
-        }
-        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
-        loggingInfo[1] = "\n\tTime taken to add CrossFade Transition :" +
-            timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < (NUM_OF_ITERATIONS *10); i++) {
-            assertEquals("Removing Transitions", tranCrossfade[i], mVideoEditor
-                .removeTransition(tranCrossfade[i].getId()));
-        }
-        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS * 10));
-        loggingInfo[2] = "\n\tTime taken to remove CrossFade Transition :" +
-            timeTaken;
-
-        writeTimingInfo("testPerformanceAddRemoveTransition (in mSec)", loggingInfo);
-    }
-
-    /**
-     * To test performance of Export
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceExport() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int outHeight = MediaProperties.HEIGHT_480;
-        final int outBitrate = MediaProperties.BITRATE_256K;
-        final int outVcodec = MediaProperties.VCODEC_H264;
-        final String[] loggingInfo = new String[1];
-        final String outFilename = mVideoEditorHelper
-            .createRandomFile(mVideoEditor.getPath() + "/") + ".3gp";
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_12Mbps_AACLC_44.1khz_64kbps_s_1_17.mp4";
-        final String imageItemFileName1 = INPUT_FILE_PATH + "IMG_1600x1200.jpg";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_32kbps_m_1_17.3gp";
-        final String imageItemFileName2 = INPUT_FILE_PATH + "IMG_176x144.jpg";
-        final String videoItemFileName3 = INPUT_FILE_PATH +
-            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
-        final String overlayFile = INPUT_FILE_PATH + "IMG_640x480_Overlay1.png";
-        final String audioTrackFilename = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        final String maskFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFileName1, renderingMode);
-        mediaItem1.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-            "m2", imageItemFileName1, 10000, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem2);
-
-        final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-            "m3", videoItemFileName2, renderingMode);
-        mediaItem3.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaItem3);
-
-        final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
-            "m4", imageItemFileName2, 10000, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem4);
-
-        final MediaVideoItem mediaItem5 = new MediaVideoItem(mVideoEditor,
-            "m5", videoItemFileName3, renderingMode);
-        mediaItem5.setExtractBoundaries(0, 20000);
-        mVideoEditor.addMediaItem(mediaItem5);
-        /**
-         * 7.Add TransitionAlpha, Apply this  Transition as Begin for Media Item 1
-         *  with duration = 2 sec behavior = BEHAVIOR_LINEAR, mask file name =
-         * TransitionSpiral_QVGA.jpg , blending percent = 50%, invert = true;
-         * */
-        final TransitionAlpha transition1 =
-            mVideoEditorHelper.createTAlpha("transition1", null, mediaItem1,
-                2000, Transition.BEHAVIOR_LINEAR, maskFilename, 50, true);
-        mVideoEditor.addTransition(transition1);
-
-        /**
-         * 8.Add Transition Sliding between MediaItem 2 and 3 ,
-         *  Sliding Direction  = DIRECTION_RIGHT_OUT_LEFT_IN,
-         *  behavior  = BEHAVIOR_MIDDLE_FAST and duration = 4sec
-         * */
-        final TransitionSliding transition2And3 =
-            mVideoEditorHelper.createTSliding("transition2", mediaItem2,
-                mediaItem3, 4000, Transition.BEHAVIOR_MIDDLE_FAST,
-                TransitionSliding.DIRECTION_RIGHT_OUT_LEFT_IN);
-        mVideoEditor.addTransition(transition2And3);
-
-        /**
-         * 9.Add Transition Crossfade between  Media Item 3 and 4,
-         *  behavior = BEHAVIOR_MIDDLE_SLOW, duration = 3.5 sec
-         * */
-        final TransitionCrossfade transition3And4 =
-            mVideoEditorHelper.createTCrossFade("transition3", mediaItem3,
-                mediaItem4, 3500, Transition.BEHAVIOR_MIDDLE_SLOW);
-        mVideoEditor.addTransition(transition3And4);
-
-        /**
-         * 10.Add Transition Fadeblack between  Media Item 4 and 5,
-         *  behavior = BEHAVIOR_SPEED_DOWN, duration = 3.5 sec
-         * */
-        final TransitionFadeBlack transition4And5 =
-            mVideoEditorHelper.createTFadeBlack("transition4", mediaItem4,
-                mediaItem5, 3500, Transition.BEHAVIOR_SPEED_DOWN);
-        mVideoEditor.addTransition(transition4And5);
-
-        /**
-         * 11.Add Effect 1 type="TYPE_SEPIA" to the MediaItem 1,
-         *  start time=1sec and duration =4secs
-         * */
-        final EffectColor effectColor1 = mVideoEditorHelper.createEffectItem(
-            mediaItem1, "effect1", 1000, 4000, EffectColor.TYPE_SEPIA, 0);
-        mediaItem1.addEffect(effectColor1);
-
-        /**
-         * 12.Add Overlay 1  to the MediaItem 3: Frame Overlay with start time = 1 sec
-         * duration = 4 sec with item  = IMG_640x480_Overlay1.png
-         * */
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFile, 640,
-            480);
-        final OverlayFrame overlayFrame =
-            mVideoEditorHelper.createOverlay(mediaItem3, "overlay",
-                mBitmap, 1000, 4000);
-        mediaItem3.addOverlay(overlayFrame);
-        /**
-         * 13.Add Effect 2 type="TYPE_NEGATIVE" to the MediaItem 2,
-         *  start time=8sec and duration =2secs
-         * */
-        final EffectColor effectColor2 = mVideoEditorHelper.createEffectItem(
-            mediaItem2, "effect2", 8000, 2000, EffectColor.TYPE_NEGATIVE, 0);
-        mediaItem2.addEffect(effectColor2);
-        /**
-         * 14.Add Effect 3 type="TYPE_COLOR" to the MediaItem 3, color param = "PINK",
-         *  start time=5 sec and duration =3secs
-         * */
-        final EffectColor effectColor3 = mVideoEditorHelper.createEffectItem(
-            mediaItem3, "effect3", 5000, 3000, EffectColor.TYPE_COLOR,
-            EffectColor.PINK);
-        mediaItem3.addEffect(effectColor3);
-        /**
-         * 15.Add Effect 4 type="TYPE_FIFTIES" to the MediaItem 4,
-         *  start time=2 sec and duration =1secs
-        * */
-        final EffectColor effectColor4 = mVideoEditorHelper.createEffectItem(
-            mediaItem4, "effect4", 2000, 1000, EffectColor.TYPE_FIFTIES, 0);
-        mediaItem4.addEffect(effectColor4);
-        /**
-         * 16.Add KenBurnsEffect for MediaItem 4 with
-         *  duration = 3 sec and startTime = 4 sec
-         *  StartRect
-         *  left = org_height/3  ;  top = org_width/3
-         *  bottom = org_width/2  ;  right = org_height/2
-         *  EndRect
-         *  left = 0  ;  top = 0
-         *  bottom =  org_height;  right =  org_width
-         * */
-
-        final Rect startRect = new Rect((mediaItem4.getHeight() / 3),
-            (mediaItem4.getWidth() / 3), (mediaItem4.getHeight() / 2),
-            (mediaItem4.getWidth() / 2));
-        final Rect endRect = new Rect(0, 0, mediaItem4.getWidth(),
-            mediaItem4.getHeight());
-        final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
-            mediaItem4, "KBOnM2", startRect, endRect,4000 , 3000);
-        mediaItem4.addEffect(kbEffectOnMediaItem);
-
-        /** 17.Add Audio Track,Set extract boundaries o to 10 sec.
-         * */
-        final AudioTrack audioTrack = mVideoEditorHelper.createAudio(
-            mVideoEditor, "audioTrack", audioTrackFilename);
-        mVideoEditor.addAudioTrack(audioTrack);
-        /** 18.Enable Looping for Audio Track.
-         * */
-        audioTrack.enableLoop();
-        int timeTaken = 0;
-        final long beginTime = SystemClock.uptimeMillis();
-            try {
-                mVideoEditor.export(outFilename, outHeight, outBitrate,
-                    new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve,
-                            String outFileName, int progress) {
-                        }
-                    });
-            } catch (Exception e) {
-                assertTrue("Error in Export" + e.toString(), false);
-            }
-        mVideoEditorHelper.checkDeleteExistingFile(outFilename);
-
-        timeTaken = calculateTimeTaken(beginTime, 1);
-        loggingInfo[0] = "Time taken to do ONE export of storyboard duration "
-            + mVideoEditor.getDuration() + " is :" + timeTaken;
-
-        writeTimingInfo("testPerformanceExport (in mSec)", loggingInfo);
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-    }
-
-
-    /**
-     * To test the performance of thumbnail extraction
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceThumbnailVideoItem() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int videoItemStartTime = 0;
-        final int videoItemEndTime = 20000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[1];
-
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFileName, renderingMode);
-        mediaVideoItem.setExtractBoundaries(videoItemStartTime,
-            videoItemEndTime);
-
-        int timeTaken = 0;
-        long beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            mediaVideoItem.getThumbnail(mediaVideoItem.getWidth() / 2,
-                mediaVideoItem.getHeight() / 2, i);
-        }
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[0] = "Duration taken to get Video Thumbnails :" +
-            timeTaken;
-
-        writeTimingInfo("testPerformanceThumbnailVideoItem (in mSec)", loggingInfo);
-    }
-
-    /**
-     * To test the performance of adding and removing the overlay to media item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceOverlayVideoItem() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int videoItemStartTime1 = 0;
-        final int videoItemEndTime1 = 10000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String overlayFilename = INPUT_FILE_PATH
-            + "IMG_640x480_Overlay1.png";
-        final int overlayStartTime = 1000;
-        final int overlayDuration = 5000;
-
-        final String[] loggingInfo = new String[2];
-        MediaVideoItem mediaVideoItem = null;
-
-        try {
-            mediaVideoItem = new MediaVideoItem(mVideoEditor, "m0",
-                videoItemFileName1, renderingMode);
-            mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
-                videoItemEndTime1);
-        } catch (Exception e1) {
-            assertTrue("Can not create Video Item with file name = "
-                + e1.toString(), false);
-        }
-        final OverlayFrame overlayFrame[] = new OverlayFrame[NUM_OF_ITERATIONS];
-        final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(overlayFilename,
-            640, 480);
-        int timeTaken = 0;
-        long beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            overlayFrame[i] = new OverlayFrame(mediaVideoItem, "overlay" + i,
-            mBitmap, overlayStartTime, overlayDuration);
-            mediaVideoItem.addOverlay(overlayFrame[i]);
-        }
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[0] = "Time taken to add & create Overlay :" + timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            assertEquals("Removing Overlays", overlayFrame[i],
-                mediaVideoItem.removeOverlay((overlayFrame[i].getId())));
-        }
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[1] = "\n\tTime taken to remove  Overlay :" +
-            timeTaken;
-
-        writeTimingInfo("testPerformanceOverlayVideoItem (in mSec)", loggingInfo);
-    }
-
-    /**
-     * To test the performance of get properties of a Video media item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceVideoItemProperties() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int videoItemStartTime1 = 0;
-        final int videoItemEndTime1 = 10100;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int fileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int duration = 77366;
-        final int videoBitrate = 3169971;
-        final int fps = 30;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int width = 1080;
-        final int height = MediaProperties.HEIGHT_720;
-        int timeTaken = 0;
-        final String[] loggingInfo = new String[1];
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "m0", videoItemFileName1, renderingMode);
-        mediaVideoItem.setExtractBoundaries(videoItemStartTime1,
-            videoItemEndTime1);
-        long beginTime = SystemClock.uptimeMillis();
-        for (int i = 0; i < (NUM_OF_ITERATIONS*10); i++) {
-            try {
-                assertEquals("Aspect Ratio Mismatch",
-                    aspectRatio, mediaVideoItem.getAspectRatio());
-                assertEquals("File Type Mismatch",
-                    fileType, mediaVideoItem.getFileType());
-                assertEquals("VideoCodec Mismatch",
-                    videoCodecType, mediaVideoItem.getVideoType());
-                assertEquals("duration Mismatch",
-                    duration, mediaVideoItem.getDuration());
-                assertEquals("Video Profile ",
-                    videoProfile, mediaVideoItem.getVideoProfile());
-                assertEquals("Video Level ",
-                    videoLevel, mediaVideoItem.getVideoLevel());
-                assertEquals("Video height ",
-                    height, mediaVideoItem.getHeight());
-                assertEquals("Video width ",
-                    width, mediaVideoItem.getWidth());
-            } catch (Exception e1) {
-                assertTrue("Can not create Video Item with file name = "
-                    + e1.toString(), false);
-            }
-        }
-        timeTaken = calculateTimeTaken(beginTime, (NUM_OF_ITERATIONS*10));
-        loggingInfo[0] = "Time taken to get Media Properties :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceVideoItemProperties:", loggingInfo);
-    }
-
-    /**
-     * To test the performance of generatePreview : with Transitions
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceGeneratePreviewWithTransitions()
-        throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String imageItemFileName = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
-        long averageTime = 0;
-        final String[] loggingInfo = new String[1];
-
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName, renderingMode);
-        mediaVideoItem.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
-            "mediaItem2", imageItemFileName, 10000, renderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
-            "transitionCrossFade", mediaVideoItem, mediaImageItem,
-            5000, transitionBehavior);
-        mVideoEditor.addTransition(transitionCrossFade);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-            final long duration2 = SystemClock.uptimeMillis();
-            mVideoEditor.removeTransition(transitionCrossFade.getId());
-            mVideoEditor.addTransition(transitionCrossFade);
-            averageTime += (duration2 - duration1);
-        }
-        final long durationToAddObjects = averageTime;
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] = "Time taken to Generate Preview with transition :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceGeneratePreviewWithTransitions:",
-            loggingInfo);
-    }
-
-    /**
-     * To test the performance of generatePreview : with KenBurn
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceWithKenBurn() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String imageItemFileName = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        long averageTime = 0;
-        final String[] loggingInfo = new String[1];
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName, renderingMode);
-        mediaVideoItem.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
-            "mediaItem2", imageItemFileName, 10000, renderingMode);
-        mVideoEditor.addMediaItem(mediaImageItem);
-
-        final Rect startRect = new Rect((mediaImageItem.getHeight() / 3),
-            (mediaImageItem.getWidth() / 3), (mediaImageItem.getHeight() / 2),
-            (mediaImageItem.getWidth() / 2));
-        final Rect endRect = new Rect(0, 0, mediaImageItem.getWidth(),
-            mediaImageItem.getHeight());
-        final EffectKenBurns kbEffectOnMediaItem =
-            new EffectKenBurns(mediaImageItem, "KBOnM2", startRect, endRect,
-                500, 3000);
-        mediaImageItem.addEffect(kbEffectOnMediaItem);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-            final long duration2 = SystemClock.uptimeMillis();
-            mediaImageItem.removeEffect(kbEffectOnMediaItem.getId());
-            mediaImageItem.addEffect(kbEffectOnMediaItem);
-            averageTime += duration2 - duration1;
-        }
-
-        final long durationToAddObjects = (averageTime);
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] = "Time taken to Generate KenBurn Effect :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceWithKenBurn", loggingInfo);
-    }
-
-    /**
-     * To test the performance of generatePreview : with Transitions and
-     * Effect,Overlapping scenario
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceEffectOverlappingTransition() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int videoStartTime1 = 0;
-        final int videoEndTime1 = 10000;
-        final int videoStartTime2 = 0;
-        final int videoEndTime2 = 10000;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int transitionDuration = 5000;
-        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
-        final int effectItemStartTime = 5000;
-        final int effectItemDurationTime = 5000;
-        final int effectType = EffectColor.TYPE_COLOR;
-        final int effectColorType = EffectColor.GREEN;
-        long averageDuration = 0;
-
-        final String[] loggingInfo = new String[1];
-        final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName1, renderingMode);
-        mediaVideoItem1.setExtractBoundaries(videoStartTime1, videoEndTime1);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
-            "mediaItem2", videoItemFileName2, renderingMode);
-        mediaVideoItem2.setExtractBoundaries(videoStartTime2, videoEndTime2);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
-            "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
-            transitionDuration, transitionBehavior);
-        mVideoEditor.addTransition(transitionCrossFade);
-
-        final EffectColor effectColor = new EffectColor(mediaVideoItem1,
-            "effect", effectItemStartTime, effectItemDurationTime, effectType,
-             effectColorType);
-        mediaVideoItem1.addEffect(effectColor);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-            final long duration2 = SystemClock.uptimeMillis();
-            mVideoEditor.removeTransition(transitionCrossFade.getId());
-            mVideoEditor.addTransition(transitionCrossFade);
-            averageDuration += (duration2 - duration1);
-        }
-        SystemClock.uptimeMillis();
-        final long durationToAddObjects = (averageDuration);
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] =
-            "Time taken to testPerformanceEffectOverlappingTransition :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceEffectOverlappingTransition:",
-            loggingInfo);
-    }
-
-    /**
-     * To test creation of story board with Transition and Two Effects, Effect
-     * overlapping transitions
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceTransitionWithEffectOverlapping() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH
-            + "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int transitionDuration = 5000;
-        final int transitionBehavior = Transition.BEHAVIOR_MIDDLE_FAST;
-        final int effectItemStartTime1 = 5000;
-        final int effectItemDurationTime1 = 5000;
-        final int effectType1 = EffectColor.TYPE_COLOR;
-        final int effectColorType1 = EffectColor.GREEN;
-        final int effectItemStartTime2 = 5000;
-        final int effectItemDurationTime2 = 5000;
-        final int effectType2 = EffectColor.TYPE_COLOR;
-        final int effectColorType2 = EffectColor.GREEN;
-        int averageTime = 0;
-        final String[] loggingInfo = new String[1];
-
-        final MediaVideoItem mediaVideoItem1 = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem1);
-
-        final MediaVideoItem mediaVideoItem2 = new MediaVideoItem(mVideoEditor,
-            "mediaItem2", videoItemFileName2, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem2);
-
-        final TransitionCrossfade transitionCrossFade = new TransitionCrossfade(
-            "transitionCrossFade", mediaVideoItem1, mediaVideoItem2,
-            transitionDuration, transitionBehavior);
-        mVideoEditor.addTransition(transitionCrossFade);
-
-        final EffectColor effectColor1 = new EffectColor(mediaVideoItem1,
-            "effect1", effectItemStartTime1, effectItemDurationTime1,
-            effectType1, effectColorType1);
-        mediaVideoItem1.addEffect(effectColor1);
-
-        final EffectColor effectColor2 = new EffectColor(mediaVideoItem2,
-            "effect2", effectItemStartTime2, effectItemDurationTime2,
-            effectType2, effectColorType2);
-        mediaVideoItem2.addEffect(effectColor2);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-            final long duration2 = SystemClock.uptimeMillis();
-            mVideoEditor.removeTransition(transitionCrossFade.getId());
-            mVideoEditor.addTransition(transitionCrossFade);
-            averageTime += duration2 - duration1;
-        }
-        final long durationToAddObjects = (averageTime);
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] = "Time taken to TransitionWithEffectOverlapping :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceTransitionWithEffectOverlapping",
-            loggingInfo);
-    }
-
-    /**
-     *To test ThumbnailList for H264
-     */
-    @LargeTest
-    public void testThumbnailH264NonIFrame() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int outWidth = 1080;
-        final int outHeight = 720;
-        final int atTime = 2400;
-        long durationToAddObjects = 0;
-        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[1];
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFilename, renderingMode);
-        assertNotNull("MediaVideoItem", mediaVideoItem);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
-            final long duration2 = SystemClock.uptimeMillis();
-            durationToAddObjects += (duration2 - duration1);
-        }
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] = "Time taken for Thumbnail generation :"
-            + timeTaken;
-        writeTimingInfo("testThumbnailH264NonIFrame", loggingInfo);
-    }
-
-    /**
-     *To test ThumbnailList for H264
-     */
-    @LargeTest
-    public void testThumbnailH264AnIFrame() throws Exception {
-        final String videoItemFilename = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final int outWidth = 1080;
-        final int outHeight = 720;
-        final int atTime = 3000;
-        int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[1];
-        long durationToAddObjects = 0;
-
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFilename, renderingMode);
-        assertNotNull("MediaVideoItem", mediaVideoItem);
-
-        for (int i = 0; i < NUM_OF_ITERATIONS; i++) {
-            final long duration1 = SystemClock.uptimeMillis();
-            mediaVideoItem.getThumbnail(outWidth, outHeight, atTime + i);
-            final long duration2 = SystemClock.uptimeMillis();
-            durationToAddObjects += (duration2 - duration1);
-        }
-        final float timeTaken = (float)durationToAddObjects *
-            1.0f/(float)NUM_OF_ITERATIONS;
-        loggingInfo[0] = "Time taken Thumbnail generation :"
-            + timeTaken;
-        writeTimingInfo("testThumbnailH264AnIFrame", loggingInfo);
-    }
-
-    /**
-     * To test the performance : With an audio track
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceWithAudioTrack() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String audioFilename1 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        final String audioFilename2 = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int audioVolume = 50;
-        final String[] loggingInfo = new String[2];
-        int timeTaken = 0;
-
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
-            "Audio Track1", audioFilename1);
-        audioTrack1.disableDucking();
-        audioTrack1.setVolume(audioVolume);
-        mVideoEditor.addAudioTrack(audioTrack1);
-
-        long beginTime = SystemClock.uptimeMillis();
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-        timeTaken = calculateTimeTaken(beginTime, 1);
-        loggingInfo[0] = "Time taken for 1st Audio Track (AACLC) :"
-            + timeTaken;
-
-        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
-            "Audio Track2", audioFilename2);
-        audioTrack2.enableLoop();
-
-        beginTime = SystemClock.uptimeMillis();
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-        timeTaken = calculateTimeTaken(beginTime, 1);
-        loggingInfo[1] = "\n\tTime taken for 2nd Audio Track(AMRNB) :"
-            + timeTaken;
-
-        writeTimingInfo("testPerformanceWithAudioTrack", loggingInfo);
-    }
-
-    /**
-     * To test the performance of adding and removing the
-     * image media item with 640 x 480
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testPerformanceAddRemoveImageItem640x480() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int imageItemDuration = 0;
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[3];
-
-        int timeTaken = 0;
-
-        final MediaImageItem[] mediaImageItem =
-            new MediaImageItem[NUM_OF_ITERATIONS];
-        long beginTime = SystemClock.uptimeMillis();
-        createImageItems(mediaImageItem, imageItemFileName, renderingMode,
-            imageItemDuration);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[0] = "Time taken to Create  Media Image Item (640x480) :"
-            + timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        addImageItems(mediaImageItem);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[1] = "\n\tTime taken to add  Media Image Item (640x480) :"
-            + timeTaken;
-
-        beginTime = SystemClock.uptimeMillis();
-        removeImageItems(mediaImageItem);
-        timeTaken = calculateTimeTaken(beginTime, NUM_OF_ITERATIONS);
-        loggingInfo[2] = "\n\tTime taken to remove  Media Image Item (640x480) :"
-            + timeTaken;
-        writeTimingInfo("testPerformanceAddRemoveImageItem640x480 (in mSec)", loggingInfo);
-    }
-
-
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
deleted file mode 100644
index 7784c7b..0000000
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/stress/VideoEditorStressTest.java
+++ /dev/null
@@ -1,1309 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.mediaframeworktest.stress;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileWriter;
-import java.io.Writer;
-import java.util.List;
-
-import android.graphics.Bitmap;
-import android.graphics.Rect;
-import android.media.videoeditor.AudioTrack;
-import android.media.videoeditor.EffectColor;
-import android.media.videoeditor.EffectKenBurns;
-import android.media.videoeditor.MediaImageItem;
-import android.media.videoeditor.MediaItem;
-import android.media.videoeditor.MediaProperties;
-import android.media.videoeditor.MediaVideoItem;
-import android.media.videoeditor.OverlayFrame;
-import android.media.videoeditor.Transition;
-import android.media.videoeditor.TransitionCrossfade;
-import android.media.videoeditor.TransitionAlpha;
-import android.media.videoeditor.TransitionFadeBlack;
-import android.media.videoeditor.TransitionSliding;
-import android.media.videoeditor.VideoEditor;
-import android.os.Environment;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.MediaProcessingProgressListener;
-import android.os.Environment;
-import android.os.SystemClock;
-import android.test.ActivityInstrumentationTestCase;
-import android.media.videoeditor.VideoEditor.ExportProgressListener;
-import android.media.videoeditor.VideoEditorFactory;
-import android.media.videoeditor.ExtractAudioWaveformProgressListener;
-
-import android.os.Debug;
-import android.util.Log;
-import com.android.mediaframeworktest.MediaFrameworkPerfTestRunner;
-import com.android.mediaframeworktest.MediaFrameworkTest;
-import android.test.suitebuilder.annotation.LargeTest;
-import com.android.mediaframeworktest.VideoEditorHelper;
-import com.android.mediaframeworktest.MediaTestUtil;
-
-/**
- * Junit / Instrumentation - performance measurement for media player and
- * recorder
- */
-public class VideoEditorStressTest
-        extends ActivityInstrumentationTestCase<MediaFrameworkTest> {
-
-    private final String TAG = "VideoEditorStressTest";
-
-    private final String PROJECT_LOCATION = VideoEditorHelper.PROJECT_LOCATION_COMMON;
-
-    private final String INPUT_FILE_PATH = VideoEditorHelper.INPUT_FILE_PATH_COMMON;
-
-    private final String VIDEOEDITOR_OUTPUT = PROJECT_LOCATION +
-        "VideoEditorStressMemOutput.txt";
-
-    private long BeginJavaMemory;
-    private long AfterJavaMemory;
-
-    private long BeginNativeMemory;
-    private long AfterNativeMemory;
-
-    public VideoEditorStressTest() {
-        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
-        new File(VIDEOEDITOR_OUTPUT).delete();
-    }
-
-    private final String PROJECT_CLASS_NAME =
-        "android.media.videoeditor.VideoEditorImpl";
-    private VideoEditor mVideoEditor;
-    private MediaTestUtil mMediaTestUtil;
-    private VideoEditorHelper mVideoEditorHelper;
-
-    @Override
-    protected void setUp() throws Exception {
-        // setup for each test case.
-        super.setUp();
-        getActivity();
-        mMediaTestUtil = new MediaTestUtil(
-            "/sdcard/VideoEditorMediaServerMemoryLog.txt",
-             this.getName(), "mediaserver");
-        mVideoEditorHelper = new VideoEditorHelper();
-        // Create a random String which will be used as project path, where all
-        // project related files will be stored.
-        final String projectPath =
-            mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
-        mVideoEditor = mVideoEditorHelper.createVideoEditor(projectPath);
-    }
-
-    @Override
-    protected void tearDown() throws Exception {
-        final String[] loggingInfo = new String[1];
-        mMediaTestUtil.getMemorySummary();
-        loggingInfo[0] = "\n" +this.getName();
-        writeTimingInfo(loggingInfo);
-        loggingInfo[0] = " diff :  " + (AfterNativeMemory - BeginNativeMemory);
-        writeTimingInfo(loggingInfo);
-        mVideoEditorHelper.destroyVideoEditor(mVideoEditor);
-        // Clean the directory created as project path
-        mVideoEditorHelper.deleteProject(new File(mVideoEditor.getPath()));
-        System.gc();
-        super.tearDown();
-    }
-
-    private void writeTimingInfo(String[] information)
-        throws Exception {
-        File outFile = new File(VIDEOEDITOR_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(outFile, true));
-        for (int i = 0; i < information.length; i++) {
-            output.write(information[i]);
-        }
-        output.close();
-    }
-
-    private void writeTestCaseHeader(String testCaseName)
-        throws Exception {
-        File outFile = new File(VIDEOEDITOR_OUTPUT);
-        Writer output = new BufferedWriter(new FileWriter(outFile, true));
-        output.write("\n\n" + testCaseName + "\n");
-        output.close();
-    }
-
-    private void getBeginMemory() throws Exception {
-        System.gc();
-        Thread.sleep(2500);
-        BeginNativeMemory = Debug.getNativeHeapAllocatedSize();
-        mMediaTestUtil.getStartMemoryLog();
-    }
-    private void getAfterMemory_updateLog(String[] loggingInfo, boolean when,
-        int iteration)
-        throws Exception {
-        System.gc();
-        Thread.sleep(2500);
-        AfterNativeMemory = Debug.getNativeHeapAllocatedSize();
-        if(when == false){
-            loggingInfo[0] = "\n Before Remove: iteration No.= " + iteration +
-                "\t " + (AfterNativeMemory - BeginNativeMemory);
-        } else {
-            loggingInfo[0] = "\n After Remove: iteration No.= " + iteration +
-                "\t " + (AfterNativeMemory - BeginNativeMemory);
-        }
-        writeTimingInfo(loggingInfo);
-        mMediaTestUtil.getMemoryLog();
-    }
-
-    /**
-     * To stress test MediaItem(Video Item) adding functionality
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAddRemoveVideoItem() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_176x144_15fps_144kbps_AMRNB_8kHz_12.2kbps_m_1_17.3gp";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_96kbps_s_0_21.mp4";
-        final String videoItemFileName3 = INPUT_FILE_PATH +
-            "H263_profile0_176x144_15fps_128kbps_1_35.3gp";
-        final String videoItemFileName4 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String[] loggingInfo = new String[1];
-        writeTestCaseHeader("testStressAddRemoveVideoItem");
-        int i = 0;
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-                    "m1" + i, videoItemFileName1, renderingMode);
-                mediaItem1.setExtractBoundaries(0, 5000);
-                mVideoEditor.addMediaItem(mediaItem1);
-            }
-            if (i % 4 == 1) {
-                final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
-                    "m2" + i, videoItemFileName2, renderingMode);
-                mediaItem2.setExtractBoundaries(0, 10000);
-                mVideoEditor.addMediaItem(mediaItem2);
-            }
-            if (i % 4 == 2) {
-                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-                    "m3" + i, videoItemFileName3, renderingMode);
-                mediaItem3.setExtractBoundaries(30000, 45000);
-                mVideoEditor.addMediaItem(mediaItem3);
-            }
-            if (i % 4 == 3) {
-                final MediaVideoItem mediaItem4 = new MediaVideoItem(mVideoEditor,
-                    "m4" + i, videoItemFileName4, renderingMode);
-                mediaItem4.setExtractBoundaries(10000, 30000);
-                mVideoEditor.addMediaItem(mediaItem4);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                mVideoEditor.removeMediaItem("m1" + i);
-            }
-            if (i % 4 == 1) {
-                mVideoEditor.removeMediaItem("m2" + i);
-            }
-            if (i % 4 == 2) {
-                mVideoEditor.removeMediaItem("m3" + i);
-            }
-            if (i % 4 == 3) {
-                mVideoEditor.removeMediaItem("m4" + i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, true, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test MediaItem(Image Item) adding functionality
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAddRemoveImageItem() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String ImageItemFileName1 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String ImageItemFileName3 = INPUT_FILE_PATH +
-            "IMG_320x240.jpg";
-        final String ImageItemFileName4 = INPUT_FILE_PATH +
-            "IMG_176x144.jpg";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        writeTestCaseHeader("testStressAddRemoveImageItem");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                final MediaImageItem mediaItem1 = new MediaImageItem(mVideoEditor,
-                    "m1"+ i, ImageItemFileName1, 5000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem1);
-            }
-            if (i % 4 == 1) {
-                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-                    "m2"+ i, ImageItemFileName2, 10000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem2);
-            }
-            if (i % 4 == 2) {
-                final MediaImageItem mediaItem3 = new MediaImageItem(mVideoEditor,
-                    "m3"+ i, ImageItemFileName3, 15000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem3);
-            }
-            if (i % 4 == 3) {
-                final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
-                    "m4"+ i, ImageItemFileName4, 20000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem4);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                mVideoEditor.removeMediaItem("m1"+i);
-            }
-            if (i % 4 == 1) {
-                mVideoEditor.removeMediaItem("m2"+i);
-            }
-            if (i % 4 == 2) {
-                mVideoEditor.removeMediaItem("m3"+i);
-            }
-            if (i % 4 == 3) {
-                mVideoEditor.removeMediaItem("m4"+i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, true, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test transition
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAddRemoveTransition() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String VideoItemFileName3 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final String maskFilename = INPUT_FILE_PATH +
-            "TransitionSpiral_QVGA.jpg";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        writeTestCaseHeader("testStressAddRemoveTransition");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-                    "m1"+i, VideoItemFileName1, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem1);
-                mediaItem1.setExtractBoundaries(0, 10000);
-                final TransitionCrossfade tranCrossfade =
-                    new TransitionCrossfade("transCF" + i, null,
-                        mediaItem1, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
-                mVideoEditor.addTransition(tranCrossfade);
-            }
-            if (i % 4 == 1) {
-                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-                    "m1"+i, VideoItemFileName1, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem1);
-                mediaItem1.setExtractBoundaries(0, 10000);
-
-                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-                    "m2" +i, ImageItemFileName2, 10000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem2);
-
-                final TransitionAlpha transitionAlpha =
-                    mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem1,
-                        mediaItem2, 5000, Transition.BEHAVIOR_SPEED_UP,
-                        maskFilename, 10, false);
-                transitionAlpha.setDuration(4000);
-                mVideoEditor.addTransition(transitionAlpha);
-            }
-            if (i % 4 == 2) {
-                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-                    "m2" + i, ImageItemFileName2, 10000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem2);
-
-                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-                    "m3" + i, VideoItemFileName3, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem3);
-
-                mediaItem3.setExtractBoundaries(0, 10000);
-                final TransitionAlpha transitionAlpha =
-                    mVideoEditorHelper.createTAlpha("transAlpha" + i, mediaItem2,
-                        mediaItem3, 5000, Transition.BEHAVIOR_SPEED_UP,
-                        maskFilename, 10, false);
-                transitionAlpha.setDuration(4000);
-                mVideoEditor.addTransition(transitionAlpha);
-
-                mediaItem3.setExtractBoundaries(0, 6000);
-
-                final TransitionSliding transition2And3 =
-                    mVideoEditorHelper.createTSliding("transSlide" +i, mediaItem2,
-                        mediaItem3, 3000, Transition.BEHAVIOR_MIDDLE_FAST,
-                        TransitionSliding.DIRECTION_LEFT_OUT_RIGHT_IN);
-                mVideoEditor.addTransition(transition2And3);
-            }
-            if (i % 4 == 3) {
-                final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-                    "m3" + i, VideoItemFileName3, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem3);
-                mediaItem3.setExtractBoundaries(0, 5000);
-
-                final TransitionFadeBlack transition3 =
-                    mVideoEditorHelper.createTFadeBlack("transFB" +i, mediaItem3,
-                        null, 2500, Transition.BEHAVIOR_SPEED_UP);
-                transition3.setDuration(500);
-                mVideoEditor.addTransition(transition3);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                mVideoEditor.removeTransition("transCF" + i);
-                mVideoEditor.removeMediaItem("m1" + i);
-            }
-            if (i % 4 == 1) {
-                mVideoEditor.removeTransition("transAlpha" + i);
-                mVideoEditor.removeMediaItem("m1" + i);
-                mVideoEditor.removeMediaItem("m2" + i);
-            }
-            if (i % 4 == 2) {
-                mVideoEditor.removeTransition("transSlide" +i);
-                mVideoEditor.removeMediaItem("m2" + i);
-                mVideoEditor.removeMediaItem("m3" + i);
-            }
-            if (i % 4 == 3) {
-                mVideoEditor.removeMediaItem("m3" + i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, true, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test overlay
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAddRemoveOverlay() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String OverlayFile3 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final String OverlayFile4 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay2.png";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", VideoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-            "m2", ImageItemFileName2, 10000, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem2);
-        writeTestCaseHeader("testStressAddRemoveOverlay");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 3 == 0) {
-                mediaItem1.setExtractBoundaries(0, 10000);
-                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
-                    OverlayFile3, 640, 480);
-                final OverlayFrame overlayFrame =
-                    mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
-                        mBitmap, 1000, 5000);
-                mediaItem1.addOverlay(overlayFrame);
-                mediaItem1.removeOverlay("overlay"+i);
-            }
-            if (i % 3 == 1) {
-                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
-                    OverlayFile4, 640, 480);
-                final OverlayFrame overlayFrame =
-                    mVideoEditorHelper.createOverlay(mediaItem2, "overlay" + i,
-                        mBitmap, 1000, 5000);
-                mediaItem2.addOverlay(overlayFrame);
-                mediaItem2.removeOverlay("overlay"+i);
-            }
-            if (i % 3 == 2) {
-                mediaItem1.setExtractBoundaries(0, 10000);
-                final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(
-                    OverlayFile4, 640, 480);
-                final OverlayFrame overlayFrame =
-                    mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
-                        mBitmap, 0, mediaItem1.getDuration());
-                mediaItem1.addOverlay(overlayFrame);
-                mediaItem1.removeOverlay("overlay"+i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-    }
-
-    /**
-     * To stress test Effects
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAddRemoveEffects() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String[] loggingInfo = new String[1];
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", VideoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem1);
-        final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-            "m2", ImageItemFileName2, 10000, renderingMode);
-        int i = 0;
-        mVideoEditor.addMediaItem(mediaItem2);
-        writeTestCaseHeader("testStressAddRemoveEffects");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 5 == 0) {
-                mediaItem1.setExtractBoundaries(10000, 30000);
-                final EffectColor effectColor1 =
-                    mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
-                        10000, (mediaItem1.getTimelineDuration()-1000),
-                        EffectColor.TYPE_COLOR, EffectColor.GREEN);
-                mediaItem1.addEffect(effectColor1);
-            }
-            if (i % 5 == 1) {
-                mediaItem2.setDuration(20000);
-                final EffectColor effectColor1 =
-                    mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
-                        0, 4000, EffectColor.TYPE_GRADIENT, EffectColor.GRAY);
-                mediaItem2.addEffect(effectColor1);
-            }
-            if (i % 5 == 2) {
-                mediaItem1.setExtractBoundaries(10000, 30000);
-                final EffectColor effectColor1 =
-                    mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
-                        (mediaItem1.getTimelineDuration() - 4000), 4000,
-                        EffectColor.TYPE_SEPIA, 0);
-                mediaItem1.addEffect(effectColor1);
-            }
-            if (i % 5 == 3) {
-                mediaItem2.setDuration(20000);
-                final EffectColor effectColor1 =
-                    mVideoEditorHelper.createEffectItem(mediaItem2, "effect1"+i,
-                        10000, 4000, EffectColor.TYPE_NEGATIVE, 0);
-                mediaItem2.addEffect(effectColor1);
-            }
-            if (i % 5 == 4) {
-                mediaItem2.setDuration(20000);
-                final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
-                    (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
-                    (mediaItem2.getWidth() / 2));
-                final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
-                    mediaItem2.getHeight());
-                final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
-                    mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
-                    (mediaItem2.getDuration() - 500));
-                mediaItem2.addEffect(kbEffectOnMediaItem);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 50; i++) {
-            if (i % 5 == 0) {
-                mediaItem1.removeEffect("effect1"+i);
-            }
-            if (i % 5 == 1) {
-                mediaItem1.removeEffect("effect1"+i);
-            }
-            if (i % 5 == 2) {
-                mediaItem1.removeEffect("effect1"+i);
-            }
-            if (i % 5 == 3) {
-                mediaItem1.removeEffect("effect1"+i);
-            }
-            if (i % 5 == 4) {
-                mediaItem1.removeEffect("KBOnM2"+i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, true, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * This method will test thumbnail list extraction in a loop = 200 for Video
-     * Item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressThumbnailVideoItem() throws Exception {
-        final String videoItemFileName = INPUT_FILE_PATH
-                + "H264_BP_640x480_15fps_1200Kbps_AACLC_48KHz_64kps_m_0_27.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFileName, renderingMode);
-        writeTestCaseHeader("testStressThumbnailVideoItem");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                final Bitmap[] thumbNails =
-                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*3,
-                        mediaVideoItem.getHeight()/2, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 1) {
-                final Bitmap[] thumbNails =
-                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()/2,
-                        mediaVideoItem.getHeight() * 3, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 2) {
-                final Bitmap[] thumbNails =
-                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth()*2,
-                        mediaVideoItem.getHeight() / 3, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 3) {
-                final Bitmap[] thumbNails =
-                    mediaVideoItem.getThumbnailList(mediaVideoItem.getWidth(),
-                        mediaVideoItem.getHeight(), i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-    }
-
-    /**
-     * To stress test media properties
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressMediaProperties() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String AudioItemFileName3 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        final int videoAspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-        final int videoFileType = MediaProperties.FILE_MP4;
-        final int videoCodecType = MediaProperties.VCODEC_H264;
-        final int videoDuration = 77366;
-        final int videoProfile = MediaProperties.H264Profile.H264ProfileBaseline;
-        final int videoLevel = MediaProperties.H264Level.H264Level13;
-        final int videoHeight = MediaProperties.HEIGHT_720;
-        final int videoWidth = 1080;
-
-        final int imageAspectRatio = MediaProperties.ASPECT_RATIO_4_3;
-        final int imageFileType = MediaProperties.FILE_JPEG;
-        final int imageWidth = 640;
-        final int imageHeight = MediaProperties.HEIGHT_480;
-
-        final int audioDuration = 77554;
-        final int audioCodecType = MediaProperties.ACODEC_AAC_LC;
-        final int audioSamplingFrequency = 44100;
-        final int audioChannel = 2;
-        writeTestCaseHeader("testStressMediaProperties");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 3 == 0) {
-                final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-                    "m1" + i, VideoItemFileName1, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem1);
-                mediaItem1.setExtractBoundaries(0, 20000);
-                assertEquals("Aspect Ratio Mismatch",
-                    videoAspectRatio, mediaItem1.getAspectRatio());
-                assertEquals("File Type Mismatch",
-                    videoFileType, mediaItem1.getFileType());
-                assertEquals("VideoCodec Mismatch",
-                    videoCodecType, mediaItem1.getVideoType());
-                assertEquals("duration Mismatch",
-                    videoDuration, mediaItem1.getDuration());
-                assertEquals("Video Profile ",
-                    videoProfile, mediaItem1.getVideoProfile());
-                assertEquals("Video Level ",
-                    videoLevel, mediaItem1.getVideoLevel());
-                assertEquals("Video height ",
-                    videoHeight, mediaItem1.getHeight());
-                assertEquals("Video width ",
-                    videoWidth, mediaItem1.getWidth());
-                mVideoEditor.removeMediaItem("m1" + i);
-            }
-            if (i % 3 == 1) {
-                final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-                    "m2" + i, ImageItemFileName2, 10000, renderingMode);
-                mVideoEditor.addMediaItem(mediaItem2);
-                assertEquals("Aspect Ratio Mismatch",
-                    imageAspectRatio, mediaItem2.getAspectRatio());
-                assertEquals("File Type Mismatch",
-                    imageFileType, mediaItem2.getFileType());
-                assertEquals("Image height",
-                    imageHeight, mediaItem2.getHeight());
-                assertEquals("Image width",
-                    imageWidth, mediaItem2.getWidth());
-                mVideoEditor.removeMediaItem("m2" + i);
-            }
-            if (i % 3 == 2) {
-                final AudioTrack mediaItem3 = new AudioTrack(mVideoEditor,
-                    "m3" + i, AudioItemFileName3);
-                mVideoEditor.addAudioTrack(mediaItem3);
-                assertEquals("AudioType Mismatch", audioCodecType,
-                    mediaItem3.getAudioType());
-                assertEquals("Audio Sampling", audioSamplingFrequency,
-                    mediaItem3.getAudioSamplingFrequency());
-                assertEquals("Audio Channels",
-                    audioChannel, mediaItem3.getAudioChannels());
-                assertEquals("duration Mismatch", audioDuration,
-                    mediaItem3.getDuration());
-                mVideoEditor.removeAudioTrack("m3" + i);
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-    }
-
-    /**
-     * To stress test insert and move of mediaitems
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressInsertMovieItems() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String VideoItemFileName2 = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
-        final String VideoItemFileName3 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        writeTestCaseHeader("testStressInsertMovieItems");
-
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", VideoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem1);
-        mediaItem1.setExtractBoundaries(0, 10000);
-
-        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
-            "m2", VideoItemFileName2, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem2);
-        mediaItem2.setExtractBoundaries(0, 15000);
-
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-                "m3" + i, VideoItemFileName3, renderingMode);
-            mediaItem3.setExtractBoundaries(0, 15000);
-            mVideoEditor.insertMediaItem(mediaItem3, "m1");
-            mVideoEditor.moveMediaItem("m2", "m3" + i);
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 50; i++) {
-            mVideoEditor.removeMediaItem("m3" + i);
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, true, i);
-            }
-        }
-        mVideoEditor.removeMediaItem("m2");
-        mVideoEditor.removeMediaItem("m1");
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test : load and save
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressLoadAndSave() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String VideoItemFileName2 = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
-        final String VideoItemFileName3 = INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_1200kbps_AACLC_48khz_64kbps_m_1_17.3gp";
-        final String ImageItemFileName4 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String ImageItemFileName5 = INPUT_FILE_PATH +
-            "IMG_176x144.jpg";
-        final String OverlayFile6 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        final String[] projectPath = new String[10];
-        writeTestCaseHeader("testStressLoadAndSave");
-        getBeginMemory();
-        for( i=0; i < 10; i++){
-
-            projectPath[i] =
-                mVideoEditorHelper.createRandomFile(PROJECT_LOCATION);
-            final VideoEditor mVideoEditor1 =
-                mVideoEditorHelper.createVideoEditor(projectPath[i]);
-
-            final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor1,
-                "m1", VideoItemFileName1, renderingMode);
-            mVideoEditor1.addMediaItem(mediaItem1);
-            mediaItem1.setExtractBoundaries(0, 10000);
-
-            final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor1,
-                "m2", VideoItemFileName2, renderingMode);
-            mVideoEditor1.addMediaItem(mediaItem2);
-            mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
-                mediaItem2.getDuration()/2);
-
-            final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor1,
-                "m3", VideoItemFileName3, renderingMode);
-            mVideoEditor1.addMediaItem(mediaItem3);
-            mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
-                mediaItem3.getDuration());
-
-            final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor1,
-                "m4", ImageItemFileName4, 5000, renderingMode);
-            mVideoEditor1.addMediaItem(mediaItem4);
-
-            final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor1,
-                "m5", ImageItemFileName5, 5000, renderingMode);
-            mVideoEditor1.addMediaItem(mediaItem5);
-
-            final EffectColor effectColor1 =
-                mVideoEditorHelper.createEffectItem(mediaItem3, "effect1",
-                    10000, 2000, EffectColor.TYPE_COLOR, EffectColor.GREEN);
-            mediaItem3.addEffect(effectColor1);
-
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(OverlayFile6,
-                640, 480);
-            final OverlayFrame overlayFrame =
-                mVideoEditorHelper.createOverlay(mediaItem4, "overlay",
-                    mBitmap, 4000, 1000);
-            mediaItem4.addOverlay(overlayFrame);
-
-            final TransitionCrossfade tranCrossfade =
-                new TransitionCrossfade("transCF", mediaItem1,
-                    mediaItem2, 5000, Transition.BEHAVIOR_MIDDLE_FAST);
-            mVideoEditor1.addTransition(tranCrossfade);
-
-            final EffectColor effectColor2 =
-                mVideoEditorHelper.createEffectItem(mediaItem4, "effect2", 0,
-                    mediaItem4.getDuration(), EffectColor.TYPE_COLOR,
-                    EffectColor.PINK);
-            mediaItem4.addEffect(effectColor2);
-
-            mVideoEditor1.generatePreview(new MediaProcessingProgressListener() {
-                public void onProgress(Object item, int action, int progress) {
-                }
-            });
-
-            mVideoEditor1.save();
-            mVideoEditor1.release();
-
-            getAfterMemory_updateLog(loggingInfo, false, i);
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for( i=0; i<10; i++){
-            final VideoEditor mVideoEditor1b =
-                VideoEditorFactory.load(projectPath[i], true);
-            List<MediaItem> mediaList = mVideoEditor1b.getAllMediaItems();
-            assertEquals("Media Item List Size", 5, mediaList.size());
-
-            mediaList.get(3).removeEffect("effect1");
-            mediaList.get(3).removeEffect("effect2");
-            mediaList.get(2).removeOverlay("overlay");
-            mVideoEditor1b.removeTransition("transCF");
-            mVideoEditor1b.removeMediaItem("m5");
-            mVideoEditor1b.removeMediaItem("m4");
-            mVideoEditor1b.removeMediaItem("m3");
-            mVideoEditor1b.removeMediaItem("m2");
-            mVideoEditor1b.removeMediaItem("m1");
-            mVideoEditor1b.release();
-            getAfterMemory_updateLog(loggingInfo, true, i);
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test : Multiple Export
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressMultipleExport() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String VideoItemFileName2 = INPUT_FILE_PATH +
-            "H264_BP_800x480_15fps_512kbps_1_17.mp4";
-        final String[] loggingInfo = new String[1];
-        final String outFilename = mVideoEditorHelper.createRandomFile(
-            mVideoEditor.getPath() + "/") + ".3gp";
-        int i = 0;
-        writeTestCaseHeader("testStressMultipleExport");
-        getBeginMemory();
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", VideoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem1);
-        mediaItem1.setExtractBoundaries(0, 10000);
-
-        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
-            "m2", VideoItemFileName2, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem2);
-        mediaItem2.setExtractBoundaries(0, 15000);
-
-        for ( i = 0; i < 50; i++) {
-            if(i%4 ==0){
-                final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
-                mVideoEditor.setAspectRatio(aspectRatio);
-                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_288,
-                    MediaProperties.BITRATE_256K,MediaProperties.ACODEC_AAC_LC,
-                        MediaProperties.VCODEC_H263,
-                        new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve, String outFileName,
-                            int progress) {
-                        }
-                    });
-            }
-            if(i%4 ==1){
-                final int aspectRatio = MediaProperties.ASPECT_RATIO_5_3;
-                mVideoEditor.setAspectRatio(aspectRatio);
-                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
-                    MediaProperties.BITRATE_384K,MediaProperties.ACODEC_AAC_LC,
-                        MediaProperties.VCODEC_MPEG4,
-                        new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve, String outFileName,
-                            int progress) {
-                        }
-                    });
-            }
-            if(i%4 ==2){
-                final int aspectRatio = MediaProperties.ASPECT_RATIO_11_9;
-                mVideoEditor.setAspectRatio(aspectRatio);
-                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_144,
-                    MediaProperties.BITRATE_512K,MediaProperties.ACODEC_AAC_LC,
-                        MediaProperties.VCODEC_H264,
-                        new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve, String outFileName,
-                            int progress) {
-                        }
-                    });
-            }
-            if(i%4 ==3){
-                final int aspectRatio = MediaProperties.ASPECT_RATIO_3_2;
-                mVideoEditor.setAspectRatio(aspectRatio);
-                mVideoEditor.export(outFilename, MediaProperties.HEIGHT_480,
-                    MediaProperties.BITRATE_800K,MediaProperties.ACODEC_AAC_LC,
-                        MediaProperties.VCODEC_H264,
-                        new ExportProgressListener() {
-                        public void onProgress(VideoEditor ve, String outFileName,
-                            int progress) {
-                        }
-                    });
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        mVideoEditor.removeMediaItem("m2");
-        mVideoEditor.removeMediaItem("m1");
-
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To stress test Media Item,Overlays,Transitions and Ken Burn
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressOverlayTransKenBurn() throws Exception {
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String VideoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_640x480_30fps_256kbps_1_17.mp4";
-        final String ImageItemFileName2 = INPUT_FILE_PATH +
-            "IMG_640x480.jpg";
-        final String OverlayFile3 = INPUT_FILE_PATH +
-            "IMG_640x480_Overlay1.png";
-        final String audioFilename4 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        int i = 0;
-        final String[] loggingInfo = new String[1];
-        writeTestCaseHeader("testStressOverlayTransKenBurn");
-        getBeginMemory();
-        for ( i = 0; i < 10; i++) {
-            final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-                "m1" + i, VideoItemFileName1, renderingMode);
-            mVideoEditor.addMediaItem(mediaItem1);
-            mediaItem1.setExtractBoundaries(0, 10000);
-
-            final MediaImageItem mediaItem2 = new MediaImageItem(mVideoEditor,
-                "m2" + i, ImageItemFileName2, 10000, renderingMode);
-            mVideoEditor.addMediaItem(mediaItem2);
-
-            final EffectColor effectColor1 =
-                mVideoEditorHelper.createEffectItem(mediaItem1, "effect1"+i,
-                    (mediaItem1.getDuration() - 4000), 4000,
-                    EffectColor.TYPE_SEPIA, 0);
-            mediaItem1.addEffect(effectColor1);
-
-            final TransitionCrossfade tranCrossfade =
-                new TransitionCrossfade("transCF" + i, mediaItem1,
-                    mediaItem2, 4000, Transition.BEHAVIOR_MIDDLE_FAST);
-            mVideoEditor.addTransition(tranCrossfade);
-
-            final Bitmap mBitmap =  mVideoEditorHelper.getBitmap(OverlayFile3,
-                640, 480);
-            final OverlayFrame overlayFrame =
-                mVideoEditorHelper.createOverlay(mediaItem1, "overlay" + i,
-                    mBitmap, 1000, 5000);
-            mediaItem1.addOverlay(overlayFrame);
-
-            final Rect startRect = new Rect((mediaItem2.getHeight() / 3),
-                (mediaItem2.getWidth() / 3), (mediaItem2.getHeight() / 2),
-                (mediaItem2.getWidth() / 2));
-            final Rect endRect = new Rect(0, 0, mediaItem2.getWidth(),
-                mediaItem2.getHeight());
-
-            final EffectKenBurns kbEffectOnMediaItem = new EffectKenBurns(
-                mediaItem2, "KBOnM2" + i, startRect, endRect, 500,
-                (mediaItem2.getDuration()-500));
-            mediaItem2.addEffect(kbEffectOnMediaItem);
-
-            if(i == 5) {
-                final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
-                    "Audio Track1", audioFilename4);
-                mVideoEditor.addAudioTrack(audioTrack1);
-            }
-            getAfterMemory_updateLog(loggingInfo, false, i);
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        for ( i = 0; i < 10; i++) {
-            MediaImageItem m2 = (MediaImageItem)mVideoEditor.getMediaItem("m2"+i);
-            MediaVideoItem m1 = (MediaVideoItem)mVideoEditor.getMediaItem("m1"+i);
-            m2.removeEffect("KBOnM2" + i);
-            m1.removeOverlay("overlay" + i);
-            mVideoEditor.removeTransition("transCF" + i);
-            m1.removeEffect("effect1" + i);
-            mVideoEditor.removeMediaItem("m2" + i);
-            mVideoEditor.removeMediaItem("m1" + i);
-            if(i == 5) {
-                mVideoEditor.removeAudioTrack("Audio Track1");
-            }
-            getAfterMemory_updateLog(loggingInfo, true, i);
-        }
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To test the performance : With an audio track with Video
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAudioTrackVideo() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "H264_BP_1080x720_30fps_800kbps_1_17.mp4";
-        final String audioFilename1 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        final String audioFilename2 = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int audioVolume = 50;
-        final String[] loggingInfo = new String[1];
-        int i = 1;
-        writeTestCaseHeader("testStressAudioTrackVideo");
-        getBeginMemory();
-        final MediaVideoItem mediaVideoItem = new MediaVideoItem(mVideoEditor,
-            "mediaItem1", videoItemFileName1, renderingMode);
-        mVideoEditor.addMediaItem(mediaVideoItem);
-
-        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
-            "Audio Track1", audioFilename1);
-        audioTrack1.disableDucking();
-        audioTrack1.setVolume(audioVolume);
-        mVideoEditor.addAudioTrack(audioTrack1);
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-
-        mVideoEditor.removeAudioTrack("Audio Track1");
-
-        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
-            "Audio Track2", audioFilename2);
-        audioTrack2.enableLoop();
-
-        mVideoEditor.generatePreview(new MediaProcessingProgressListener() {
-            public void onProgress(Object item, int action, int progress) {
-            }
-        });
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        mVideoEditor.removeMediaItem("mediaItem1");
-
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-    /**
-     * To Test Stress : Story Board creation with out preview or export
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressStoryBoard() throws Exception {
-        final String videoItemFileName1 = INPUT_FILE_PATH +
-            "MPEG4_SP_720x480_30fps_280kbps_AACLC_48kHz_161kbps_s_0_26.mp4";
-        final String videoItemFileName2 = INPUT_FILE_PATH +
-            "MPEG4_SP_854x480_15fps_256kbps_AACLC_16khz_48kbps_s_0_26.mp4";
-        final String videoItemFileName3= INPUT_FILE_PATH +
-            "MPEG4_SP_640x480_15fps_512kbps_AACLC_48khz_132kbps_s_0_26.mp4";
-        final String imageItemFileName4 = INPUT_FILE_PATH +
-            "IMG_1600x1200.jpg";
-        final String imageItemFileName5 = INPUT_FILE_PATH +
-            "IMG_176x144.jpg";
-        final String audioFilename6 = INPUT_FILE_PATH +
-            "AMRNB_8KHz_12.2Kbps_m_1_17.3gp";
-        final String audioFilename7 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final int audioVolume = 50;
-        final String[] loggingInfo = new String[1];
-        int i = 1;
-
-        writeTestCaseHeader("testStressStoryBoard");
-        getBeginMemory();
-        final MediaVideoItem mediaItem1 = new MediaVideoItem(mVideoEditor,
-            "m1", videoItemFileName1, renderingMode);
-        mediaItem1.setExtractBoundaries(0, 10000);
-        mVideoEditor.addMediaItem(mediaItem1);
-
-        final MediaVideoItem mediaItem2 = new MediaVideoItem(mVideoEditor,
-            "m2", videoItemFileName2, renderingMode);
-        mediaItem2.setExtractBoundaries(mediaItem2.getDuration()/4,
-            mediaItem2.getDuration()/2);
-        mVideoEditor.addMediaItem(mediaItem2);
-
-        final MediaVideoItem mediaItem3 = new MediaVideoItem(mVideoEditor,
-            "m3", videoItemFileName3, renderingMode);
-        mediaItem3.setExtractBoundaries(mediaItem3.getDuration()/2,
-            mediaItem3.getDuration());
-        mVideoEditor.addMediaItem(mediaItem3);
-
-        final MediaImageItem mediaItem4 = new MediaImageItem(mVideoEditor,
-            "m4", imageItemFileName4, 5000, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem4);
-
-        final MediaImageItem mediaItem5 = new MediaImageItem(mVideoEditor,
-            "m5", imageItemFileName5, 5000, renderingMode);
-        mVideoEditor.addMediaItem(mediaItem5);
-
-        final TransitionCrossfade tranCrossfade =
-            new TransitionCrossfade("transCF", mediaItem2, mediaItem3, 2500,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(tranCrossfade);
-
-        final TransitionCrossfade tranCrossfade1 =
-            new TransitionCrossfade("transCF1", mediaItem3, mediaItem4, 2500,
-                Transition.BEHAVIOR_MIDDLE_FAST);
-        mVideoEditor.addTransition(tranCrossfade1);
-
-        final AudioTrack audioTrack1 = new AudioTrack(mVideoEditor,
-            "Audio Track1", audioFilename6);
-        mVideoEditor.addAudioTrack(audioTrack1);
-
-        mVideoEditor.removeAudioTrack("Audio Track1");
-        final AudioTrack audioTrack2 = new AudioTrack(mVideoEditor,
-            "Audio Track2", audioFilename7);
-        mVideoEditor.addAudioTrack(audioTrack2);
-        audioTrack2.enableLoop();
-        getAfterMemory_updateLog(loggingInfo, false, i);
-
-        /** Remove items and check for memory leak if any */
-        getBeginMemory();
-        mVideoEditor.removeAudioTrack("Audio Track2");
-        mVideoEditor.removeTransition("transCF");
-        mVideoEditor.removeTransition("transCF1");
-        mVideoEditor.removeMediaItem("m5");
-        mVideoEditor.removeMediaItem("m4");
-        mVideoEditor.removeMediaItem("m3");
-        mVideoEditor.removeMediaItem("m2");
-        mVideoEditor.removeMediaItem("m1");
-
-        getAfterMemory_updateLog(loggingInfo, true, i);
-    }
-
-     /**
-     * To test the performance : With an audio track Only
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressAudioTrackOnly() throws Exception {
-
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String AudioItemFileName1 = INPUT_FILE_PATH +
-            "AACLC_44.1kHz_256kbps_s_1_17.mp4";
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        writeTestCaseHeader("testStressAudioTrackOnly");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            final AudioTrack mediaItem1 = new AudioTrack(mVideoEditor,
-                "m1" + i, AudioItemFileName1);
-            mVideoEditor.addAudioTrack(mediaItem1);
-            mediaItem1.enableLoop();
-            mVideoEditor.removeAudioTrack("m1" + i);
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-    }
-
-    /**
-     * This method will test thumbnail list extraction in a loop = 200 for Image
-     * Item
-     *
-     * @throws Exception
-     */
-    @LargeTest
-    public void testStressThumbnailImageItem() throws Exception {
-        final String imageItemFileName = INPUT_FILE_PATH + "IMG_640x480.jpg";
-        final int renderingMode = MediaItem.RENDERING_MODE_BLACK_BORDER;
-        final String[] loggingInfo = new String[1];
-        int i = 0;
-        final MediaImageItem mediaImageItem = new MediaImageItem(mVideoEditor,
-            "m1", imageItemFileName, 5000, renderingMode);
-        writeTestCaseHeader("testStressThumbnailImageItem");
-        getBeginMemory();
-        for ( i = 0; i < 50; i++) {
-            if (i % 4 == 0) {
-                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
-                    mediaImageItem.getWidth() / 2 ,
-                    mediaImageItem.getHeight() / 2, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 1) {
-                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
-                    mediaImageItem.getWidth() / 2,
-                    mediaImageItem.getHeight() * 3, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 2) {
-                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
-                    mediaImageItem.getWidth() * 2,
-                    mediaImageItem.getHeight() / 3, i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 4 == 3) {
-                final Bitmap[] thumbNails = mediaImageItem.getThumbnailList(
-                    mediaImageItem.getWidth(),
-                    mediaImageItem.getHeight(), i, 5000, 2);
-                // Recycle this Bitmap array
-                for (int i1 = 0; i1 < thumbNails.length; i1++) {
-                    thumbNails[i1].recycle();
-                }
-            }
-            if (i % 10 == 0) {
-                getAfterMemory_updateLog(loggingInfo, false, i);
-            }
-        }
-        getAfterMemory_updateLog(loggingInfo, false, i);
-    }
-}
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
index edfa36a..45df065 100644
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/unit/CameraMetadataTest.java
@@ -309,7 +309,7 @@
                 });
 
         // rational (n) -- in particular rational x 9
-        checkKeyGetAndSetArray("android.sensor.calibrationTransform", Rational[].class,
+        checkKeyGetAndSetArray("android.sensor.calibrationTransform1", Rational[].class,
                 new Rational[] {
                         new Rational(1, 2), new Rational(3, 4), new Rational(5, 6),
                         new Rational(7, 8), new Rational(9, 10), new Rational(10, 11),
diff --git a/native/android/sensor.cpp b/native/android/sensor.cpp
index 76c6eda..acfcd83 100644
--- a/native/android/sensor.cpp
+++ b/native/android/sensor.cpp
@@ -123,10 +123,13 @@
 ssize_t ASensorEventQueue_getEvents(ASensorEventQueue* queue,
                 ASensorEvent* events, size_t count)
 {
-    return static_cast<SensorEventQueue*>(queue)->read(events, count);
+    ssize_t actual = static_cast<SensorEventQueue*>(queue)->read(events, count);
+    if (actual > 0) {
+        static_cast<SensorEventQueue*>(queue)->sendAck(events, actual);
+    }
+    return actual;
 }
 
-
 /*****************************************************************************/
 
 const char* ASensor_getName(ASensor const* sensor)
@@ -153,3 +156,23 @@
 {
     return static_cast<Sensor const*>(sensor)->getMinDelay();
 }
+
+int ASensor_getFifoMaxEventCount(ASensor const* sensor)
+{
+    return static_cast<Sensor const*>(sensor)->getFifoMaxEventCount();
+}
+
+int ASensor_getFifoReservedEventCount(ASensor const* sensor)
+{
+    return static_cast<Sensor const*>(sensor)->getFifoReservedEventCount();
+}
+
+const char* ASensor_getStringType(ASensor const* sensor)
+{
+    return static_cast<Sensor const*>(sensor)->getStringType().string();
+}
+
+const char* ASensor_getRequiredPermission(ASensor const* sensor)
+{
+    return static_cast<Sensor const*>(sensor)->getRequiredPermission().string();
+}
diff --git a/opengl/java/android/opengl/GLSurfaceView.java b/opengl/java/android/opengl/GLSurfaceView.java
index a9322b9..1406f6b 100644
--- a/opengl/java/android/opengl/GLSurfaceView.java
+++ b/opengl/java/android/opengl/GLSurfaceView.java
@@ -878,7 +878,7 @@
         protected int[] mConfigSpec;
 
         private int[] filterConfigSpec(int[] configSpec) {
-            if (mEGLContextClientVersion != 2) {
+            if (mEGLContextClientVersion != 2 && mEGLContextClientVersion != 3) {
                 return configSpec;
             }
             /* We know none of the subclasses define EGL_RENDERABLE_TYPE.
@@ -888,7 +888,11 @@
             int[] newConfigSpec = new int[len + 2];
             System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
             newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
-            newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
+            if (mEGLContextClientVersion == 2) {
+                newConfigSpec[len] = EGL14.EGL_OPENGL_ES2_BIT;  /* EGL_OPENGL_ES2_BIT */
+            } else {
+                newConfigSpec[len] = EGLExt.EGL_OPENGL_ES3_BIT_KHR; /* EGL_OPENGL_ES3_BIT_KHR */
+            }
             newConfigSpec[len+1] = EGL10.EGL_NONE;
             return newConfigSpec;
         }
diff --git a/packages/DefaultContainerService/Android.mk b/packages/DefaultContainerService/Android.mk
index 9961168..0de2c1f 100644
--- a/packages/DefaultContainerService/Android.mk
+++ b/packages/DefaultContainerService/Android.mk
@@ -7,7 +7,7 @@
 
 LOCAL_PACKAGE_NAME := DefaultContainerService
 
-LOCAL_REQUIRED_MODULES := libdefcontainer_jni
+LOCAL_JNI_SHARED_LIBRARIES := libdefcontainer_jni
 
 LOCAL_CERTIFICATE := platform
 
diff --git a/packages/DefaultContainerService/res/values-th/strings.xml b/packages/DefaultContainerService/res/values-th/strings.xml
index 3a7080c..621d7ed 100644
--- a/packages/DefaultContainerService/res/values-th/strings.xml
+++ b/packages/DefaultContainerService/res/values-th/strings.xml
@@ -20,5 +20,5 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="service_name" msgid="4841491635055379553">"ตัวช่วยเหลือของการเข้าถึงแพคเกจ"</string>
+    <string name="service_name" msgid="4841491635055379553">"ตัวช่วยเหลือของการเข้าถึงแพ็กเกจ"</string>
 </resources>
diff --git a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
index f68d1a9..36c1d5c 100644
--- a/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
+++ b/packages/DefaultContainerService/src/com/android/defcontainer/DefaultContainerService.java
@@ -30,6 +30,7 @@
 import android.content.res.ObbInfo;
 import android.content.res.ObbScanner;
 import android.net.Uri;
+import android.os.Build;
 import android.os.Environment;
 import android.os.Environment.UserEnvironment;
 import android.os.FileUtils;
@@ -40,6 +41,9 @@
 import android.os.ServiceManager;
 import android.os.StatFs;
 import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStatVfs;
 import android.util.DisplayMetrics;
 import android.util.Slog;
 
@@ -65,11 +69,8 @@
 import javax.crypto.Mac;
 import javax.crypto.NoSuchPaddingException;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 import libcore.io.Streams;
-import libcore.io.StructStatVfs;
 
 /*
  * This service copies a downloaded apk to a file passed in as
@@ -244,7 +245,7 @@
             Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
 
             try {
-                final StructStatVfs stat = Libcore.os.statvfs(path);
+                final StructStatVfs stat = Os.statvfs(path);
                 final long totalSize = stat.f_blocks * stat.f_bsize;
                 final long availSize = stat.f_bavail * stat.f_bsize;
                 return new long[] { totalSize, availSize };
@@ -341,11 +342,13 @@
         // The .apk file
         String codePath = packageURI.getPath();
         File codeFile = new File(codePath);
+        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(codePath);
+        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
 
         // Calculate size of container needed to hold base APK.
         final int sizeMb;
         try {
-            sizeMb = calculateContainerSize(codeFile, isForwardLocked);
+            sizeMb = calculateContainerSize(handle, codeFile, abi, isForwardLocked);
         } catch (IOException e) {
             Slog.w(TAG, "Problem when trying to copy " + codeFile.getPath());
             return null;
@@ -376,7 +379,7 @@
         }
 
         try {
-            Libcore.os.chmod(resFile.getAbsolutePath(), 0640);
+            Os.chmod(resFile.getAbsolutePath(), 0640);
         } catch (ErrnoException e) {
             Slog.e(TAG, "Could not chown APK: " + e.getMessage());
             PackageHelper.destroySdDir(newCid);
@@ -398,7 +401,7 @@
             }
 
             try {
-                Libcore.os.chmod(publicZipFile.getAbsolutePath(), 0644);
+                Os.chmod(publicZipFile.getAbsolutePath(), 0644);
             } catch (ErrnoException e) {
                 Slog.e(TAG, "Could not chown public resource file: " + e.getMessage());
                 PackageHelper.destroySdDir(newCid);
@@ -408,7 +411,14 @@
 
         final File sharedLibraryDir = new File(newCachePath, LIB_DIR_NAME);
         if (sharedLibraryDir.mkdir()) {
-            int ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(codeFile, sharedLibraryDir);
+            int ret = PackageManager.INSTALL_SUCCEEDED;
+            if (abi >= 0) {
+                ret = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+                        sharedLibraryDir, Build.SUPPORTED_ABIS[abi]);
+            } else if (abi != PackageManager.NO_NATIVE_LIBRARIES) {
+                ret = abi;
+            }
+
             if (ret != PackageManager.INSTALL_SUCCEEDED) {
                 Slog.e(TAG, "Could not copy native libraries to " + sharedLibraryDir.getPath());
                 PackageHelper.destroySdDir(newCid);
@@ -822,6 +832,17 @@
         return availSdMb > sizeMb;
     }
 
+    private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+        NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(apkFile);
+        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+
+        try {
+            return calculateContainerSize(handle, apkFile, abi, forwardLocked);
+        } finally {
+            handle.close();
+        }
+    }
+
     /**
      * Calculate the container size for an APK. Takes into account the
      * 
@@ -829,7 +850,8 @@
      * @return size in megabytes (2^20 bytes)
      * @throws IOException when there is a problem reading the file
      */
-    private int calculateContainerSize(File apkFile, boolean forwardLocked) throws IOException {
+    private int calculateContainerSize(NativeLibraryHelper.ApkHandle apkHandle,
+            File apkFile, int abiIndex, boolean forwardLocked) throws IOException {
         // Calculate size of container needed to hold base APK.
         long sizeBytes = apkFile.length();
         if (sizeBytes == 0 && !apkFile.exists()) {
@@ -838,7 +860,10 @@
 
         // Check all the native files that need to be copied and add that to the
         // container size.
-        sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkFile);
+        if (abiIndex >= 0) {
+            sizeBytes += NativeLibraryHelper.sumNativeBinariesLI(apkHandle,
+                    Build.SUPPORTED_ABIS[abiIndex]);
+        }
 
         if (forwardLocked) {
             sizeBytes += PackageHelper.extractPublicFiles(apkFile.getPath(), null);
diff --git a/packages/DocumentsUI/AndroidManifest.xml b/packages/DocumentsUI/AndroidManifest.xml
index 6b77a7c..159ee66 100644
--- a/packages/DocumentsUI/AndroidManifest.xml
+++ b/packages/DocumentsUI/AndroidManifest.xml
@@ -9,18 +9,17 @@
         android:label="@string/app_label"
         android:supportsRtl="true">
 
-        <!-- TODO: allow rotation when state saving is in better shape -->
         <activity
             android:name=".DocumentsActivity"
             android:theme="@style/Theme"
             android:icon="@drawable/ic_doc_text">
-            <intent-filter android:priority="100">
+            <intent-filter>
                 <action android:name="android.intent.action.OPEN_DOCUMENT" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.OPENABLE" />
                 <data android:mimeType="*/*" />
             </intent-filter>
-            <intent-filter android:priority="100">
+            <intent-filter>
                 <action android:name="android.intent.action.CREATE_DOCUMENT" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <category android:name="android.intent.category.OPENABLE" />
@@ -33,6 +32,10 @@
                 <data android:mimeType="*/*" />
             </intent-filter>
             <intent-filter>
+                <action android:name="android.intent.action.PICK_DIRECTORY" />
+                <category android:name="android.intent.category.DEFAULT" />
+            </intent-filter>
+            <intent-filter>
                 <action android:name="android.provider.action.MANAGE_ROOT" />
                 <category android:name="android.intent.category.DEFAULT" />
                 <data android:mimeType="vnd.android.document/root" />
@@ -57,14 +60,5 @@
                 <data android:scheme="package" />
             </intent-filter>
         </receiver>
-
-        <!-- TODO: remove when we have real clients -->
-        <activity android:name=".TestActivity" android:enabled="false">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-                <category android:name="android.intent.category.DEFAULT" />
-                <category android:name="android.intent.category.LAUNCHER" />
-            </intent-filter>
-        </activity>
     </application>
 </manifest>
diff --git a/packages/DocumentsUI/res/layout/fragment_pick.xml b/packages/DocumentsUI/res/layout/fragment_pick.xml
new file mode 100644
index 0000000..4a2fd03
--- /dev/null
+++ b/packages/DocumentsUI/res/layout/fragment_pick.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
+
+    <!-- Le sigh, this really should be an asset -->
+    <View
+        android:layout_width="match_parent"
+        android:layout_height="1dp"
+        android:background="#ccc" />
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="horizontal"
+        android:baselineAligned="false"
+        android:gravity="center_vertical"
+        android:background="#ddd"
+        android:minHeight="?android:attr/listPreferredItemHeightSmall">
+
+        <Button
+            android:id="@android:id/button1"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent"
+            android:background="?android:attr/selectableItemBackground"
+            android:textAppearance="?android:attr/textAppearanceSmall"
+            android:textAllCaps="false"
+            android:padding="8dp" />
+
+    </LinearLayout>
+
+</LinearLayout>
diff --git a/packages/DocumentsUI/res/values-af/strings.xml b/packages/DocumentsUI/res/values-af/strings.xml
index 41fd63a..ca76a7d 100644
--- a/packages/DocumentsUI/res/values-af/strings.xml
+++ b/packages/DocumentsUI/res/values-af/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Stoor"</string>
     <string name="menu_share" msgid="3075149983979628146">"Deel"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Vee uit"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Kies \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> gekies"</string>
     <string name="sort_name" msgid="9183560467917256779">"Volgens naam"</string>
     <string name="sort_date" msgid="586080032956151448">"Volgens datum gewysig"</string>
diff --git a/packages/DocumentsUI/res/values-am/strings.xml b/packages/DocumentsUI/res/values-am/strings.xml
index c77a8ee..84879d5 100644
--- a/packages/DocumentsUI/res/values-am/strings.xml
+++ b/packages/DocumentsUI/res/values-am/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"አስቀምጥ"</string>
     <string name="menu_share" msgid="3075149983979628146">"አጋራ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ሰርዝ"</string>
+    <string name="menu_select" msgid="8711270657353563424">"«<xliff:g id="DIRECTORY">^1</xliff:g>»ን ይምረጡ"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> ተመርጠዋል"</string>
     <string name="sort_name" msgid="9183560467917256779">"በስም"</string>
     <string name="sort_date" msgid="586080032956151448">"በተለወጠበት ቀን"</string>
diff --git a/packages/DocumentsUI/res/values-ar/strings.xml b/packages/DocumentsUI/res/values-ar/strings.xml
index c59c0ee..5c5d863 100644
--- a/packages/DocumentsUI/res/values-ar/strings.xml
+++ b/packages/DocumentsUI/res/values-ar/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"حفظ"</string>
     <string name="menu_share" msgid="3075149983979628146">"مشاركة"</string>
     <string name="menu_delete" msgid="8138799623850614177">"حذف"</string>
+    <string name="menu_select" msgid="8711270657353563424">"تحديد \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"تم تحديد <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"بحسب الاسم"</string>
     <string name="sort_date" msgid="586080032956151448">"بحسب تاريخ التعديل"</string>
diff --git a/packages/DocumentsUI/res/values-bg/strings.xml b/packages/DocumentsUI/res/values-bg/strings.xml
index c3242b2..d1da879 100644
--- a/packages/DocumentsUI/res/values-bg/strings.xml
+++ b/packages/DocumentsUI/res/values-bg/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Запазване"</string>
     <string name="menu_share" msgid="3075149983979628146">"Споделяне"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Изтриване"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Избиране на „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Избрахте <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"По име"</string>
     <string name="sort_date" msgid="586080032956151448">"По дата на промяната"</string>
diff --git a/packages/DocumentsUI/res/values-ca/strings.xml b/packages/DocumentsUI/res/values-ca/strings.xml
index 68c7b0e..23e7284 100644
--- a/packages/DocumentsUI/res/values-ca/strings.xml
+++ b/packages/DocumentsUI/res/values-ca/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Desa"</string>
     <string name="menu_share" msgid="3075149983979628146">"Comparteix"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Suprimeix"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Selecciona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Seleccionats: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Per nom"</string>
     <string name="sort_date" msgid="586080032956151448">"Per data de modificació"</string>
diff --git a/packages/DocumentsUI/res/values-cs/strings.xml b/packages/DocumentsUI/res/values-cs/strings.xml
index f089c8b..ad8897a 100644
--- a/packages/DocumentsUI/res/values-cs/strings.xml
+++ b/packages/DocumentsUI/res/values-cs/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Uložit"</string>
     <string name="menu_share" msgid="3075149983979628146">"Sdílet"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Smazat"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Vyberte adresář <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Vybráno: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Podle názvu"</string>
     <string name="sort_date" msgid="586080032956151448">"Podle data úpravy"</string>
diff --git a/packages/DocumentsUI/res/values-da/strings.xml b/packages/DocumentsUI/res/values-da/strings.xml
index 816f9a7..7ae5d1e 100644
--- a/packages/DocumentsUI/res/values-da/strings.xml
+++ b/packages/DocumentsUI/res/values-da/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Gem"</string>
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Slet"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Vælg \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> er valgt"</string>
     <string name="sort_name" msgid="9183560467917256779">"Efter navn"</string>
     <string name="sort_date" msgid="586080032956151448">"Efter ændringsdato"</string>
diff --git a/packages/DocumentsUI/res/values-de/strings.xml b/packages/DocumentsUI/res/values-de/strings.xml
index e43a1e2..98c1787 100644
--- a/packages/DocumentsUI/res/values-de/strings.xml
+++ b/packages/DocumentsUI/res/values-de/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Speichern"</string>
     <string name="menu_share" msgid="3075149983979628146">"Teilen"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Löschen"</string>
+    <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" auswählen"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> ausgewählt"</string>
     <string name="sort_name" msgid="9183560467917256779">"Nach Name"</string>
     <string name="sort_date" msgid="586080032956151448">"Nach Änderungsdatum"</string>
diff --git a/packages/DocumentsUI/res/values-el/strings.xml b/packages/DocumentsUI/res/values-el/strings.xml
index 5a91484..f0f7e10 100644
--- a/packages/DocumentsUI/res/values-el/strings.xml
+++ b/packages/DocumentsUI/res/values-el/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Αποθήκευση"</string>
     <string name="menu_share" msgid="3075149983979628146">"Κοινοποίηση"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Διαγραφή"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Επιλογή \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Επιλέχθηκαν <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Κατά όνομα"</string>
     <string name="sort_date" msgid="586080032956151448">"Κατά ημερομηνία τροποποίησης"</string>
diff --git a/packages/DocumentsUI/res/values-en-rGB/strings.xml b/packages/DocumentsUI/res/values-en-rGB/strings.xml
index a95e7f1..d2af473 100644
--- a/packages/DocumentsUI/res/values-en-rGB/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rGB/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Delete"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Select \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selected"</string>
     <string name="sort_name" msgid="9183560467917256779">"By name"</string>
     <string name="sort_date" msgid="586080032956151448">"By date modified"</string>
diff --git a/packages/DocumentsUI/res/values-en-rIN/strings.xml b/packages/DocumentsUI/res/values-en-rIN/strings.xml
index a95e7f1..d2af473 100644
--- a/packages/DocumentsUI/res/values-en-rIN/strings.xml
+++ b/packages/DocumentsUI/res/values-en-rIN/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Share"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Delete"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Select \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selected"</string>
     <string name="sort_name" msgid="9183560467917256779">"By name"</string>
     <string name="sort_date" msgid="586080032956151448">"By date modified"</string>
diff --git a/packages/DocumentsUI/res/values-es-rUS/strings.xml b/packages/DocumentsUI/res/values-es-rUS/strings.xml
index 4a3ff33..daf18cf 100644
--- a/packages/DocumentsUI/res/values-es-rUS/strings.xml
+++ b/packages/DocumentsUI/res/values-es-rUS/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Seleccionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> seleccionado(s)"</string>
     <string name="sort_name" msgid="9183560467917256779">"Por nombre"</string>
     <string name="sort_date" msgid="586080032956151448">"Por fecha de modificación"</string>
diff --git a/packages/DocumentsUI/res/values-es/strings.xml b/packages/DocumentsUI/res/values-es/strings.xml
index 1682542..573ee41 100644
--- a/packages/DocumentsUI/res/values-es/strings.xml
+++ b/packages/DocumentsUI/res/values-es/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartir"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Selecciona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Seleccionado: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Por nombre"</string>
     <string name="sort_date" msgid="586080032956151448">"Por fecha de modificación"</string>
diff --git a/packages/DocumentsUI/res/values-et-rEE/strings.xml b/packages/DocumentsUI/res/values-et-rEE/strings.xml
index 5412956..dae965a0 100644
--- a/packages/DocumentsUI/res/values-et-rEE/strings.xml
+++ b/packages/DocumentsUI/res/values-et-rEE/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Salvesta"</string>
     <string name="menu_share" msgid="3075149983979628146">"Jaga"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Kustuta"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Kataloogi „<xliff:g id="DIRECTORY">^1</xliff:g>” valimine"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> on valitud"</string>
     <string name="sort_name" msgid="9183560467917256779">"Nime järgi"</string>
     <string name="sort_date" msgid="586080032956151448">"Muutmiskuupäeva järgi"</string>
diff --git a/packages/DocumentsUI/res/values-fa/strings.xml b/packages/DocumentsUI/res/values-fa/strings.xml
index c922b37..a646eda 100644
--- a/packages/DocumentsUI/res/values-fa/strings.xml
+++ b/packages/DocumentsUI/res/values-fa/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"ذخیره"</string>
     <string name="menu_share" msgid="3075149983979628146">"اشتراک‌گذاری"</string>
     <string name="menu_delete" msgid="8138799623850614177">"حذف"</string>
+    <string name="menu_select" msgid="8711270657353563424">"انتخاب «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> انتخاب شد"</string>
     <string name="sort_name" msgid="9183560467917256779">"بر اساس نام"</string>
     <string name="sort_date" msgid="586080032956151448">"بر اساس تاریخ اصلاح"</string>
diff --git a/packages/DocumentsUI/res/values-fi/strings.xml b/packages/DocumentsUI/res/values-fi/strings.xml
index 5e40ecd..aa118ed 100644
--- a/packages/DocumentsUI/res/values-fi/strings.xml
+++ b/packages/DocumentsUI/res/values-fi/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Tallenna"</string>
     <string name="menu_share" msgid="3075149983979628146">"Jaa"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Poista"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Valitse <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> valittua"</string>
     <string name="sort_name" msgid="9183560467917256779">"Nimen mukaan"</string>
     <string name="sort_date" msgid="586080032956151448">"Muokkauspäivän mukaan"</string>
diff --git a/packages/DocumentsUI/res/values-fr-rCA/strings.xml b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
index a837379..b370a1e 100644
--- a/packages/DocumentsUI/res/values-fr-rCA/strings.xml
+++ b/packages/DocumentsUI/res/values-fr-rCA/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Enregistrer"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Supprimer"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Sélectionner « <xliff:g id="DIRECTORY">^1</xliff:g> »"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> sélectionné(s)"</string>
     <string name="sort_name" msgid="9183560467917256779">"Par nom"</string>
     <string name="sort_date" msgid="586080032956151448">"Par date de modification"</string>
diff --git a/packages/DocumentsUI/res/values-fr/strings.xml b/packages/DocumentsUI/res/values-fr/strings.xml
index ff9aeda..070b130 100644
--- a/packages/DocumentsUI/res/values-fr/strings.xml
+++ b/packages/DocumentsUI/res/values-fr/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Enregistrer"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partager"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Supprimer"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Sélectionner \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> élément(s) sélectionné(s)"</string>
     <string name="sort_name" msgid="9183560467917256779">"Par nom"</string>
     <string name="sort_date" msgid="586080032956151448">"Par date de modification"</string>
diff --git a/packages/DocumentsUI/res/values-hi/strings.xml b/packages/DocumentsUI/res/values-hi/strings.xml
index 8d7fcba..66c707e 100644
--- a/packages/DocumentsUI/res/values-hi/strings.xml
+++ b/packages/DocumentsUI/res/values-hi/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"सहेजें"</string>
     <string name="menu_share" msgid="3075149983979628146">"साझा करें"</string>
     <string name="menu_delete" msgid="8138799623850614177">"हटाएं"</string>
+    <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" चुनें"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> चयनित"</string>
     <string name="sort_name" msgid="9183560467917256779">"नाम के अनुसार"</string>
     <string name="sort_date" msgid="586080032956151448">"बदलाव के दिनांक के अनुसार"</string>
diff --git a/packages/DocumentsUI/res/values-hr/strings.xml b/packages/DocumentsUI/res/values-hr/strings.xml
index 73c2f04..3438e73 100644
--- a/packages/DocumentsUI/res/values-hr/strings.xml
+++ b/packages/DocumentsUI/res/values-hr/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Spremi"</string>
     <string name="menu_share" msgid="3075149983979628146">"Dijeli"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Izbriši"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Odaberi \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Odabrano: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Po korisniku"</string>
     <string name="sort_date" msgid="586080032956151448">"Po datumu izmjene"</string>
diff --git a/packages/DocumentsUI/res/values-hu/strings.xml b/packages/DocumentsUI/res/values-hu/strings.xml
index db7854b..2af559b 100644
--- a/packages/DocumentsUI/res/values-hu/strings.xml
+++ b/packages/DocumentsUI/res/values-hu/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Mentés"</string>
     <string name="menu_share" msgid="3075149983979628146">"Megosztás"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Törlés"</string>
+    <string name="menu_select" msgid="8711270657353563424">"A(z) „<xliff:g id="DIRECTORY">^1</xliff:g>” mappa kiválasztása"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> kiválasztva"</string>
     <string name="sort_name" msgid="9183560467917256779">"Név szerint"</string>
     <string name="sort_date" msgid="586080032956151448">"Módosítás dátuma szerint"</string>
diff --git a/packages/DocumentsUI/res/values-hy-rAM/strings.xml b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
index c683f3e..67a1f7e 100644
--- a/packages/DocumentsUI/res/values-hy-rAM/strings.xml
+++ b/packages/DocumentsUI/res/values-hy-rAM/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Պահել"</string>
     <string name="menu_share" msgid="3075149983979628146">"Համօգտագործել"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ջնջել"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Ընտրել «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> ընտրված"</string>
     <string name="sort_name" msgid="9183560467917256779">"Ըստ անվան"</string>
     <string name="sort_date" msgid="586080032956151448">"Ըստ փոփոխման ամսաթվի"</string>
diff --git a/packages/DocumentsUI/res/values-in/strings.xml b/packages/DocumentsUI/res/values-in/strings.xml
index d9f4475..62057c7 100644
--- a/packages/DocumentsUI/res/values-in/strings.xml
+++ b/packages/DocumentsUI/res/values-in/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Simpan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Bagikan"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Hapus"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Pilih \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> dipilih"</string>
     <string name="sort_name" msgid="9183560467917256779">"Menurut nama"</string>
     <string name="sort_date" msgid="586080032956151448">"Menurut tanggal diubah"</string>
diff --git a/packages/DocumentsUI/res/values-it/strings.xml b/packages/DocumentsUI/res/values-it/strings.xml
index baca387..bec4d00 100644
--- a/packages/DocumentsUI/res/values-it/strings.xml
+++ b/packages/DocumentsUI/res/values-it/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Salva"</string>
     <string name="menu_share" msgid="3075149983979628146">"Condividi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Elimina"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Seleziona \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selezionati"</string>
     <string name="sort_name" msgid="9183560467917256779">"Per nome"</string>
     <string name="sort_date" msgid="586080032956151448">"Per data di modifica"</string>
diff --git a/packages/DocumentsUI/res/values-iw/strings.xml b/packages/DocumentsUI/res/values-iw/strings.xml
index 712c060..c8a3fb9 100644
--- a/packages/DocumentsUI/res/values-iw/strings.xml
+++ b/packages/DocumentsUI/res/values-iw/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"שמור"</string>
     <string name="menu_share" msgid="3075149983979628146">"שתף"</string>
     <string name="menu_delete" msgid="8138799623850614177">"מחק"</string>
+    <string name="menu_select" msgid="8711270657353563424">"בחר ב-\"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> נבחרו"</string>
     <string name="sort_name" msgid="9183560467917256779">"לפי שם"</string>
     <string name="sort_date" msgid="586080032956151448">"לפי תאריך שינוי"</string>
diff --git a/packages/DocumentsUI/res/values-ja/strings.xml b/packages/DocumentsUI/res/values-ja/strings.xml
index 996496d..1475005 100644
--- a/packages/DocumentsUI/res/values-ja/strings.xml
+++ b/packages/DocumentsUI/res/values-ja/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"保存"</string>
     <string name="menu_share" msgid="3075149983979628146">"共有"</string>
     <string name="menu_delete" msgid="8138799623850614177">"削除"</string>
+    <string name="menu_select" msgid="8711270657353563424">"「<xliff:g id="DIRECTORY">^1</xliff:g>」を選択"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g>件選択済み"</string>
     <string name="sort_name" msgid="9183560467917256779">"名前順"</string>
     <string name="sort_date" msgid="586080032956151448">"更新日順"</string>
diff --git a/packages/DocumentsUI/res/values-ka-rGE/strings.xml b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
index f3e1274..c90768f 100644
--- a/packages/DocumentsUI/res/values-ka-rGE/strings.xml
+++ b/packages/DocumentsUI/res/values-ka-rGE/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"შენახვა"</string>
     <string name="menu_share" msgid="3075149983979628146">"გაზიარება"</string>
     <string name="menu_delete" msgid="8138799623850614177">"წაშლა"</string>
+    <string name="menu_select" msgid="8711270657353563424">"„<xliff:g id="DIRECTORY">^1</xliff:g>“-ის არჩევა"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> მონიშნული"</string>
     <string name="sort_name" msgid="9183560467917256779">"სახელით"</string>
     <string name="sort_date" msgid="586080032956151448">"ცვლილების თარიღით"</string>
diff --git a/packages/DocumentsUI/res/values-km-rKH/strings.xml b/packages/DocumentsUI/res/values-km-rKH/strings.xml
index 80f3698..e8944ec 100644
--- a/packages/DocumentsUI/res/values-km-rKH/strings.xml
+++ b/packages/DocumentsUI/res/values-km-rKH/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"រក្សាទុក"</string>
     <string name="menu_share" msgid="3075149983979628146">"ចែករំលែក"</string>
     <string name="menu_delete" msgid="8138799623850614177">"លុប"</string>
+    <string name="menu_select" msgid="8711270657353563424">"ជ្រើស \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"បាន​ជ្រើស <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"តាម​ឈ្មោះ"</string>
     <string name="sort_date" msgid="586080032956151448">"តាម​កាលបរិច្ឆេទ​បាន​កែប្រែ"</string>
diff --git a/packages/DocumentsUI/res/values-ko/strings.xml b/packages/DocumentsUI/res/values-ko/strings.xml
index 2cd0d44..5996e66 100644
--- a/packages/DocumentsUI/res/values-ko/strings.xml
+++ b/packages/DocumentsUI/res/values-ko/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"저장"</string>
     <string name="menu_share" msgid="3075149983979628146">"공유"</string>
     <string name="menu_delete" msgid="8138799623850614177">"삭제"</string>
+    <string name="menu_select" msgid="8711270657353563424">"\'<xliff:g id="DIRECTORY">^1</xliff:g>\' 선택"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g>개 선택됨"</string>
     <string name="sort_name" msgid="9183560467917256779">"이름순"</string>
     <string name="sort_date" msgid="586080032956151448">"수정된 날짜순"</string>
diff --git a/packages/DocumentsUI/res/values-lo-rLA/strings.xml b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
index 9a6f32f..8452ae1 100644
--- a/packages/DocumentsUI/res/values-lo-rLA/strings.xml
+++ b/packages/DocumentsUI/res/values-lo-rLA/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"ບັນທຶກ"</string>
     <string name="menu_share" msgid="3075149983979628146">"ແບ່ງປັນ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ລຶບ"</string>
+    <string name="menu_select" msgid="8711270657353563424">"ເລືອກ​ \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"ເລືອກແລ້ວ <xliff:g id="COUNT">%1$d</xliff:g> ລາຍການ"</string>
     <string name="sort_name" msgid="9183560467917256779">"ຕາມຊື່"</string>
     <string name="sort_date" msgid="586080032956151448">"ຕາມວັນທີທີ່ແກ້ໄຂ"</string>
diff --git a/packages/DocumentsUI/res/values-lt/strings.xml b/packages/DocumentsUI/res/values-lt/strings.xml
index f861b99..8ec3e0b 100644
--- a/packages/DocumentsUI/res/values-lt/strings.xml
+++ b/packages/DocumentsUI/res/values-lt/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Išsaugoti"</string>
     <string name="menu_share" msgid="3075149983979628146">"Bendrinti"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ištrinti"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Pasirinkti katalogą „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Pasirinkta: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Pagal pavadinimą"</string>
     <string name="sort_date" msgid="586080032956151448">"Pagal keitimo datą"</string>
diff --git a/packages/DocumentsUI/res/values-lv/strings.xml b/packages/DocumentsUI/res/values-lv/strings.xml
index 651a59fe0d..caaf8ec 100644
--- a/packages/DocumentsUI/res/values-lv/strings.xml
+++ b/packages/DocumentsUI/res/values-lv/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Saglabāt"</string>
     <string name="menu_share" msgid="3075149983979628146">"Kopīgot"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Dzēst"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Atlasīt “<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Atlasīts: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Pēc nosaukuma"</string>
     <string name="sort_date" msgid="586080032956151448">"Pēc pārveidošanas datuma"</string>
diff --git a/packages/DocumentsUI/res/values-mn-rMN/strings.xml b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
index 22c9fcd..3d90cc1 100644
--- a/packages/DocumentsUI/res/values-mn-rMN/strings.xml
+++ b/packages/DocumentsUI/res/values-mn-rMN/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Хадгалах"</string>
     <string name="menu_share" msgid="3075149983979628146">"Хуваалцах"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Устгах"</string>
+    <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\"-г сонгох"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> сонгогдсон"</string>
     <string name="sort_name" msgid="9183560467917256779">"Нэрээр"</string>
     <string name="sort_date" msgid="586080032956151448">"Өөрчлөгдсөн огноогоор"</string>
diff --git a/packages/DocumentsUI/res/values-ms-rMY/strings.xml b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
index 7e09c57..9ea7119 100644
--- a/packages/DocumentsUI/res/values-ms-rMY/strings.xml
+++ b/packages/DocumentsUI/res/values-ms-rMY/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Simpan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Kongsi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Padam"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Pilih \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> dipilih"</string>
     <string name="sort_name" msgid="9183560467917256779">"Mengikut nama"</string>
     <string name="sort_date" msgid="586080032956151448">"Diubah suai mengikut tarikh"</string>
diff --git a/packages/DocumentsUI/res/values-nb/strings.xml b/packages/DocumentsUI/res/values-nb/strings.xml
index 8831bd8..af7c282 100644
--- a/packages/DocumentsUI/res/values-nb/strings.xml
+++ b/packages/DocumentsUI/res/values-nb/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Lagre"</string>
     <string name="menu_share" msgid="3075149983979628146">"Del"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Slett"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Velg «<xliff:g id="DIRECTORY">^1</xliff:g>»"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> valgt"</string>
     <string name="sort_name" msgid="9183560467917256779">"Etter navn"</string>
     <string name="sort_date" msgid="586080032956151448">"«Etter dato» endret"</string>
diff --git a/packages/DocumentsUI/res/values-nl/strings.xml b/packages/DocumentsUI/res/values-nl/strings.xml
index 08862e8..a8cf114 100644
--- a/packages/DocumentsUI/res/values-nl/strings.xml
+++ b/packages/DocumentsUI/res/values-nl/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Opslaan"</string>
     <string name="menu_share" msgid="3075149983979628146">"Delen"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Verwijderen"</string>
+    <string name="menu_select" msgid="8711270657353563424">"<xliff:g id="DIRECTORY">^1</xliff:g> selecteren"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> geselecteerd"</string>
     <string name="sort_name" msgid="9183560467917256779">"Op naam"</string>
     <string name="sort_date" msgid="586080032956151448">"Op aanpassingsdatum"</string>
diff --git a/packages/DocumentsUI/res/values-pl/strings.xml b/packages/DocumentsUI/res/values-pl/strings.xml
index 42cec9c..ead40e9 100644
--- a/packages/DocumentsUI/res/values-pl/strings.xml
+++ b/packages/DocumentsUI/res/values-pl/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Zapisz"</string>
     <string name="menu_share" msgid="3075149983979628146">"Udostępnij"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Usuń"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Zaznacz „<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Wybrano: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Według nazwy"</string>
     <string name="sort_date" msgid="586080032956151448">"Według daty edycji"</string>
diff --git a/packages/DocumentsUI/res/values-pt-rPT/strings.xml b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
index f1be722..0003c05 100644
--- a/packages/DocumentsUI/res/values-pt-rPT/strings.xml
+++ b/packages/DocumentsUI/res/values-pt-rPT/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Guardar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Partilhar"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Eliminar"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Selecionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selecionado(s)"</string>
     <string name="sort_name" msgid="9183560467917256779">"Por nome"</string>
     <string name="sort_date" msgid="586080032956151448">"Por data de modificação"</string>
diff --git a/packages/DocumentsUI/res/values-pt/strings.xml b/packages/DocumentsUI/res/values-pt/strings.xml
index 78fcaf8..4a5c72a 100644
--- a/packages/DocumentsUI/res/values-pt/strings.xml
+++ b/packages/DocumentsUI/res/values-pt/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Salvar"</string>
     <string name="menu_share" msgid="3075149983979628146">"Compartilhar"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Excluir"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Selecionar \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selecionados"</string>
     <string name="sort_name" msgid="9183560467917256779">"Por nome"</string>
     <string name="sort_date" msgid="586080032956151448">"Por data de modificação"</string>
diff --git a/packages/DocumentsUI/res/values-ro/strings.xml b/packages/DocumentsUI/res/values-ro/strings.xml
index 5fd44c8..0dfa11d4 100644
--- a/packages/DocumentsUI/res/values-ro/strings.xml
+++ b/packages/DocumentsUI/res/values-ro/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Salvați"</string>
     <string name="menu_share" msgid="3075149983979628146">"Distribuiți"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ștergeți"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Selectați „<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> selectate"</string>
     <string name="sort_name" msgid="9183560467917256779">"După nume"</string>
     <string name="sort_date" msgid="586080032956151448">"După data modificării"</string>
diff --git a/packages/DocumentsUI/res/values-ru/strings.xml b/packages/DocumentsUI/res/values-ru/strings.xml
index 85fd70e0..f86a4af 100644
--- a/packages/DocumentsUI/res/values-ru/strings.xml
+++ b/packages/DocumentsUI/res/values-ru/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Сохранить"</string>
     <string name="menu_share" msgid="3075149983979628146">"Поделиться"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Удалить"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Выбрать папку \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Выбрано: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"По названию"</string>
     <string name="sort_date" msgid="586080032956151448">"По дате изменения"</string>
diff --git a/packages/DocumentsUI/res/values-sk/strings.xml b/packages/DocumentsUI/res/values-sk/strings.xml
index 4b5ebcd..5d03df6 100644
--- a/packages/DocumentsUI/res/values-sk/strings.xml
+++ b/packages/DocumentsUI/res/values-sk/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Uložiť"</string>
     <string name="menu_share" msgid="3075149983979628146">"Zdieľať"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Odstrániť"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Vyberte adresár <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Vybraté: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Podľa názvu"</string>
     <string name="sort_date" msgid="586080032956151448">"Podľa dátumu zmeny"</string>
diff --git a/packages/DocumentsUI/res/values-sl/strings.xml b/packages/DocumentsUI/res/values-sl/strings.xml
index f984a0a..b3e52dd43 100644
--- a/packages/DocumentsUI/res/values-sl/strings.xml
+++ b/packages/DocumentsUI/res/values-sl/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Shrani"</string>
     <string name="menu_share" msgid="3075149983979628146">"Skupna raba"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Izbriši"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Izbira mape »<xliff:g id="DIRECTORY">^1</xliff:g>«"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Št. izbranih: <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Po imenu"</string>
     <string name="sort_date" msgid="586080032956151448">"Po datumu spremembe"</string>
diff --git a/packages/DocumentsUI/res/values-sr/strings.xml b/packages/DocumentsUI/res/values-sr/strings.xml
index eb0b197..892dbce 100644
--- a/packages/DocumentsUI/res/values-sr/strings.xml
+++ b/packages/DocumentsUI/res/values-sr/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Сачувај"</string>
     <string name="menu_share" msgid="3075149983979628146">"Дели"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Избриши"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Изабери „<xliff:g id="DIRECTORY">^1</xliff:g>“"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Изабрано је <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Према имену"</string>
     <string name="sort_date" msgid="586080032956151448">"Према датуму измене"</string>
diff --git a/packages/DocumentsUI/res/values-sv/strings.xml b/packages/DocumentsUI/res/values-sv/strings.xml
index 7aa5c50..fd6457d 100644
--- a/packages/DocumentsUI/res/values-sv/strings.xml
+++ b/packages/DocumentsUI/res/values-sv/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Spara"</string>
     <string name="menu_share" msgid="3075149983979628146">"Dela"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Ta bort"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Välj <xliff:g id="DIRECTORY">^1</xliff:g>"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Har valt <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Efter namn"</string>
     <string name="sort_date" msgid="586080032956151448">"Efter ändringsdatum"</string>
diff --git a/packages/DocumentsUI/res/values-sw/strings.xml b/packages/DocumentsUI/res/values-sw/strings.xml
index 299fda7..0948c71 100644
--- a/packages/DocumentsUI/res/values-sw/strings.xml
+++ b/packages/DocumentsUI/res/values-sw/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Hifadhi"</string>
     <string name="menu_share" msgid="3075149983979628146">"Shiriki"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Futa"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Chagua \" <xliff:g id="DIRECTORY">^1</xliff:g> \""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> zimechaguliwa"</string>
     <string name="sort_name" msgid="9183560467917256779">"Kwa jina"</string>
     <string name="sort_date" msgid="586080032956151448">"Kwa tarehe viliporekebishwa"</string>
diff --git a/packages/DocumentsUI/res/values-th/strings.xml b/packages/DocumentsUI/res/values-th/strings.xml
index 6ac8810..4bf3e4f 100644
--- a/packages/DocumentsUI/res/values-th/strings.xml
+++ b/packages/DocumentsUI/res/values-th/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"บันทึก"</string>
     <string name="menu_share" msgid="3075149983979628146">"แชร์"</string>
     <string name="menu_delete" msgid="8138799623850614177">"ลบ"</string>
+    <string name="menu_select" msgid="8711270657353563424">"เลือก \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"เลือกไว้ <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"ตามชื่อ"</string>
     <string name="sort_date" msgid="586080032956151448">"ตามวันที่ที่ปรับเปลี่ยน"</string>
diff --git a/packages/DocumentsUI/res/values-tl/strings.xml b/packages/DocumentsUI/res/values-tl/strings.xml
index e0fd8c8..8ef8aa5 100644
--- a/packages/DocumentsUI/res/values-tl/strings.xml
+++ b/packages/DocumentsUI/res/values-tl/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"I-save"</string>
     <string name="menu_share" msgid="3075149983979628146">"Ibahagi"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Tanggalin"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Piliin ang \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> ang pinili"</string>
     <string name="sort_name" msgid="9183560467917256779">"Ayon sa pangalan"</string>
     <string name="sort_date" msgid="586080032956151448">"Ayon sa petsa ng pagbago"</string>
diff --git a/packages/DocumentsUI/res/values-tr/strings.xml b/packages/DocumentsUI/res/values-tr/strings.xml
index 699a5cd..93586d0 100644
--- a/packages/DocumentsUI/res/values-tr/strings.xml
+++ b/packages/DocumentsUI/res/values-tr/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Kaydet"</string>
     <string name="menu_share" msgid="3075149983979628146">"Paylaş"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Sil"</string>
+    <string name="menu_select" msgid="8711270657353563424">"\"<xliff:g id="DIRECTORY">^1</xliff:g>\" dizinini seç"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> tane seçildi"</string>
     <string name="sort_name" msgid="9183560467917256779">"Ada göre"</string>
     <string name="sort_date" msgid="586080032956151448">"Değişiklik tarihine göre"</string>
diff --git a/packages/DocumentsUI/res/values-uk/strings.xml b/packages/DocumentsUI/res/values-uk/strings.xml
index f87b6a2..8f8865b 100644
--- a/packages/DocumentsUI/res/values-uk/strings.xml
+++ b/packages/DocumentsUI/res/values-uk/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Зберегти"</string>
     <string name="menu_share" msgid="3075149983979628146">"Поділитися"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Видалити"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Вибрати каталог \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Вибрано <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"За назвою"</string>
     <string name="sort_date" msgid="586080032956151448">"За датою змінення"</string>
diff --git a/packages/DocumentsUI/res/values-vi/strings.xml b/packages/DocumentsUI/res/values-vi/strings.xml
index 41e29fa..8b8ff1f 100644
--- a/packages/DocumentsUI/res/values-vi/strings.xml
+++ b/packages/DocumentsUI/res/values-vi/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Lưu"</string>
     <string name="menu_share" msgid="3075149983979628146">"Chia sẻ"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Xóa"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Chọn \"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"Đã chọn <xliff:g id="COUNT">%1$d</xliff:g>"</string>
     <string name="sort_name" msgid="9183560467917256779">"Theo tên"</string>
     <string name="sort_date" msgid="586080032956151448">"Theo ngày sửa đổi"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rCN/strings.xml b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
index 742cda7..68ab5f8 100644
--- a/packages/DocumentsUI/res/values-zh-rCN/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rCN/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"保存"</string>
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
     <string name="menu_delete" msgid="8138799623850614177">"删除"</string>
+    <string name="menu_select" msgid="8711270657353563424">"选择“<xliff:g id="DIRECTORY">^1</xliff:g>”"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"已选择<xliff:g id="COUNT">%1$d</xliff:g>项"</string>
     <string name="sort_name" msgid="9183560467917256779">"按名称"</string>
     <string name="sort_date" msgid="586080032956151448">"按修改日期"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rHK/strings.xml b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
index 67ed587..afd8b63 100644
--- a/packages/DocumentsUI/res/values-zh-rHK/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rHK/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"儲存"</string>
     <string name="menu_share" msgid="3075149983979628146">"分享"</string>
     <string name="menu_delete" msgid="8138799623850614177">"刪除"</string>
+    <string name="menu_select" msgid="8711270657353563424">"選取「<xliff:g id="DIRECTORY">^1</xliff:g>」"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 個"</string>
     <string name="sort_name" msgid="9183560467917256779">"按名稱"</string>
     <string name="sort_date" msgid="586080032956151448">"按修改日期"</string>
diff --git a/packages/DocumentsUI/res/values-zh-rTW/strings.xml b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
index 269583a..2e77f21 100644
--- a/packages/DocumentsUI/res/values-zh-rTW/strings.xml
+++ b/packages/DocumentsUI/res/values-zh-rTW/strings.xml
@@ -17,7 +17,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="app_label" msgid="2783841764617238354">"文件"</string>
-    <string name="title_open" msgid="4353228937663917801">"開啟工具"</string>
+    <string name="title_open" msgid="4353228937663917801">"開啟檔案"</string>
     <string name="title_save" msgid="2433679664882857999">"儲存至"</string>
     <string name="menu_create_dir" msgid="5947289605844398389">"建立資料夾"</string>
     <string name="menu_grid" msgid="6878021334497835259">"格狀檢視"</string>
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"儲存"</string>
     <string name="menu_share" msgid="3075149983979628146">"共用"</string>
     <string name="menu_delete" msgid="8138799623850614177">"刪除"</string>
+    <string name="menu_select" msgid="8711270657353563424">"選取「<xliff:g id="DIRECTORY">^1</xliff:g>」"</string>
     <string name="mode_selected_count" msgid="459111894725594625">"已選取 <xliff:g id="COUNT">%1$d</xliff:g> 個項目"</string>
     <string name="sort_name" msgid="9183560467917256779">"依名稱"</string>
     <string name="sort_date" msgid="586080032956151448">"依修改日期"</string>
@@ -38,7 +39,7 @@
     <string name="save_error" msgid="6167009778003223664">"無法儲存文件"</string>
     <string name="create_error" msgid="3735649141335444215">"無法建立資料夾"</string>
     <string name="query_error" msgid="1222448261663503501">"無法查詢文件"</string>
-    <string name="root_recent" msgid="4470053704320518133">"最近使用過的項目"</string>
+    <string name="root_recent" msgid="4470053704320518133">"最近存取過"</string>
     <string name="root_available_bytes" msgid="8568452858617033281">"可用空間:<xliff:g id="SIZE">%1$s</xliff:g>"</string>
     <string name="root_type_service" msgid="2178854894416775409">"儲存空間服務"</string>
     <string name="root_type_shortcut" msgid="3318760609471618093">"捷徑"</string>
@@ -47,7 +48,7 @@
     <string name="pref_advanced_devices" msgid="903257239609301276">"顯示進階裝置"</string>
     <string name="pref_file_size" msgid="2826879315743961459">"顯示檔案大小"</string>
     <string name="pref_device_size" msgid="3542106883278997222">"顯示裝置大小"</string>
-    <string name="empty" msgid="7858882803708117596">"沒有項目"</string>
+    <string name="empty" msgid="7858882803708117596">"沒有任何項目"</string>
     <string name="toast_no_application" msgid="1339885974067891667">"無法開啟檔案"</string>
     <string name="toast_failed_delete" msgid="2180678019407244069">"無法刪除部分文件"</string>
     <string name="share_via" msgid="8966594246261344259">"分享方式:"</string>
diff --git a/packages/DocumentsUI/res/values-zu/strings.xml b/packages/DocumentsUI/res/values-zu/strings.xml
index bedd2cdf..55e2c75 100644
--- a/packages/DocumentsUI/res/values-zu/strings.xml
+++ b/packages/DocumentsUI/res/values-zu/strings.xml
@@ -29,6 +29,7 @@
     <string name="menu_save" msgid="2394743337684426338">"Londoloza"</string>
     <string name="menu_share" msgid="3075149983979628146">"Yabelana"</string>
     <string name="menu_delete" msgid="8138799623850614177">"Susa"</string>
+    <string name="menu_select" msgid="8711270657353563424">"Khetha i-\"<xliff:g id="DIRECTORY">^1</xliff:g>\""</string>
     <string name="mode_selected_count" msgid="459111894725594625">"<xliff:g id="COUNT">%1$d</xliff:g> okukhethiwe"</string>
     <string name="sort_name" msgid="9183560467917256779">"Ngegama"</string>
     <string name="sort_date" msgid="586080032956151448">"Ngedethi yokuguqula"</string>
diff --git a/packages/DocumentsUI/res/values/strings.xml b/packages/DocumentsUI/res/values/strings.xml
index 92c30ba..c1a9d72 100644
--- a/packages/DocumentsUI/res/values/strings.xml
+++ b/packages/DocumentsUI/res/values/strings.xml
@@ -44,6 +44,8 @@
     <string name="menu_share">Share</string>
     <!-- Menu item title that deletes the selected documents [CHAR LIMIT=24] -->
     <string name="menu_delete">Delete</string>
+    <!-- Menu item title that selects the current directory [CHAR LIMIT=48] -->
+    <string name="menu_select">Select \"<xliff:g id="directory" example="My Directory">^1</xliff:g>\"</string>
 
     <!-- Action mode title summarizing the number of documents selected [CHAR LIMIT=32] -->
     <string name="mode_selected_count"><xliff:g id="count" example="3">%1$d</xliff:g> selected</string>
diff --git a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
index 4212e96..9f76991 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/DocumentsActivity.java
@@ -24,6 +24,7 @@
 import static com.android.documentsui.DocumentsActivity.State.ACTION_GET_CONTENT;
 import static com.android.documentsui.DocumentsActivity.State.ACTION_MANAGE;
 import static com.android.documentsui.DocumentsActivity.State.ACTION_OPEN;
+import static com.android.documentsui.DocumentsActivity.State.ACTION_PICK_DIRECTORY;
 import static com.android.documentsui.DocumentsActivity.State.MODE_GRID;
 import static com.android.documentsui.DocumentsActivity.State.MODE_LIST;
 
@@ -202,6 +203,8 @@
             final String mimeType = getIntent().getType();
             final String title = getIntent().getStringExtra(Intent.EXTRA_TITLE);
             SaveFragment.show(getFragmentManager(), mimeType, title);
+        } else if (mState.action == ACTION_PICK_DIRECTORY) {
+            PickFragment.show(getFragmentManager());
         }
 
         if (mState.action == ACTION_GET_CONTENT) {
@@ -209,7 +212,8 @@
             moreApps.setComponent(null);
             moreApps.setPackage(null);
             RootsFragment.show(getFragmentManager(), moreApps);
-        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE) {
+        } else if (mState.action == ACTION_OPEN || mState.action == ACTION_CREATE
+                || mState.action == ACTION_PICK_DIRECTORY) {
             RootsFragment.show(getFragmentManager(), null);
         }
 
@@ -236,6 +240,8 @@
             mState.action = ACTION_CREATE;
         } else if (Intent.ACTION_GET_CONTENT.equals(action)) {
             mState.action = ACTION_GET_CONTENT;
+        } else if (Intent.ACTION_PICK_DIRECTORY.equals(action)) {
+            mState.action = ACTION_PICK_DIRECTORY;
         } else if (DocumentsContract.ACTION_MANAGE_ROOT.equals(action)) {
             mState.action = ACTION_MANAGE;
         }
@@ -434,7 +440,8 @@
             actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
             actionBar.setIcon(new ColorDrawable());
 
-            if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT) {
+            if (mState.action == ACTION_OPEN || mState.action == ACTION_GET_CONTENT
+                    || mState.action == ACTION_PICK_DIRECTORY) {
                 actionBar.setTitle(R.string.title_open);
             } else if (mState.action == ACTION_CREATE) {
                 actionBar.setTitle(R.string.title_save);
@@ -576,7 +583,7 @@
         sortSize.setVisible(mState.showSize);
 
         final boolean searchVisible;
-        if (mState.action == ACTION_CREATE) {
+        if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
             createDir.setVisible(cwd != null && cwd.isCreateSupported());
             searchVisible = false;
 
@@ -586,7 +593,9 @@
                 list.setVisible(false);
             }
 
-            SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
+            if (mState.action == ACTION_CREATE) {
+                SaveFragment.get(fm).setSaveEnabled(cwd != null && cwd.isCreateSupported());
+            }
         } else {
             createDir.setVisible(false);
 
@@ -819,7 +828,7 @@
 
         if (cwd == null) {
             // No directory means recents
-            if (mState.action == ACTION_CREATE) {
+            if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
                 RecentsCreateFragment.show(fm);
             } else {
                 DirectoryFragment.showRecentsOpen(fm, anim);
@@ -848,6 +857,15 @@
             }
         }
 
+        if (mState.action == ACTION_PICK_DIRECTORY) {
+            final PickFragment pick = PickFragment.get(fm);
+            if (pick != null) {
+                final CharSequence displayName = (mState.stack.size() <= 1) ? root.title
+                        : cwd.displayName;
+                pick.setPickTarget(cwd, displayName);
+            }
+        }
+
         final RootsFragment roots = RootsFragment.get(fm);
         if (roots != null) {
             roots.onCurrentRootChanged();
@@ -1002,12 +1020,18 @@
         new CreateFinishTask(mimeType, displayName).executeOnExecutor(getCurrentExecutor());
     }
 
+    public void onPickRequested(DocumentInfo pickTarget) {
+        final Uri viaUri = DocumentsContract.buildViaUri(pickTarget.authority,
+                pickTarget.documentId);
+        new PickFinishTask(viaUri).executeOnExecutor(getCurrentExecutor());
+    }
+
     private void saveStackBlocking() {
         final ContentResolver resolver = getContentResolver();
         final ContentValues values = new ContentValues();
 
         final byte[] rawStack = DurableUtils.writeToArrayOrNull(mState.stack);
-        if (mState.action == ACTION_CREATE) {
+        if (mState.action == ACTION_CREATE || mState.action == ACTION_PICK_DIRECTORY) {
             // Remember stack for last create
             values.clear();
             values.put(RecentColumns.KEY, mState.stack.buildKey());
@@ -1040,6 +1064,11 @@
 
         if (mState.action == ACTION_GET_CONTENT) {
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+        } else if (mState.action == ACTION_PICK_DIRECTORY) {
+            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
         } else {
             intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
                     | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
@@ -1121,6 +1150,25 @@
         }
     }
 
+    private class PickFinishTask extends AsyncTask<Void, Void, Void> {
+        private final Uri mUri;
+
+        public PickFinishTask(Uri uri) {
+            mUri = uri;
+        }
+
+        @Override
+        protected Void doInBackground(Void... params) {
+            saveStackBlocking();
+            return null;
+        }
+
+        @Override
+        protected void onPostExecute(Void result) {
+            onFinished(mUri);
+        }
+    }
+
     public static class State implements android.os.Parcelable {
         public int action;
         public String[] acceptMimes;
@@ -1154,7 +1202,8 @@
         public static final int ACTION_OPEN = 1;
         public static final int ACTION_CREATE = 2;
         public static final int ACTION_GET_CONTENT = 3;
-        public static final int ACTION_MANAGE = 4;
+        public static final int ACTION_PICK_DIRECTORY = 4;
+        public static final int ACTION_MANAGE = 5;
 
         public static final int MODE_UNKNOWN = 0;
         public static final int MODE_LIST = 1;
diff --git a/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
new file mode 100644
index 0000000..a9e488a1
--- /dev/null
+++ b/packages/DocumentsUI/src/com/android/documentsui/PickFragment.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.documentsui;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import com.android.documentsui.model.DocumentInfo;
+
+import java.util.Locale;
+
+/**
+ * Display pick confirmation bar, usually for selecting a directory.
+ */
+public class PickFragment extends Fragment {
+    public static final String TAG = "PickFragment";
+
+    private DocumentInfo mPickTarget;
+
+    private View mContainer;
+    private Button mPick;
+
+    public static void show(FragmentManager fm) {
+        final PickFragment fragment = new PickFragment();
+
+        final FragmentTransaction ft = fm.beginTransaction();
+        ft.replace(R.id.container_save, fragment, TAG);
+        ft.commitAllowingStateLoss();
+    }
+
+    public static PickFragment get(FragmentManager fm) {
+        return (PickFragment) fm.findFragmentByTag(TAG);
+    }
+
+    @Override
+    public View onCreateView(
+            LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+        mContainer = inflater.inflate(R.layout.fragment_pick, container, false);
+
+        mPick = (Button) mContainer.findViewById(android.R.id.button1);
+        mPick.setOnClickListener(mPickListener);
+
+        setPickTarget(null, null);
+
+        return mContainer;
+    }
+
+    private View.OnClickListener mPickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            final DocumentsActivity activity = DocumentsActivity.get(PickFragment.this);
+            activity.onPickRequested(mPickTarget);
+        }
+    };
+
+    public void setPickTarget(DocumentInfo pickTarget, CharSequence displayName) {
+        mPickTarget = pickTarget;
+
+        if (mPickTarget != null) {
+            mContainer.setVisibility(View.VISIBLE);
+            final Locale locale = getResources().getConfiguration().locale;
+            final String raw = getString(R.string.menu_select).toUpperCase(locale);
+            mPick.setText(TextUtils.expandTemplate(raw, displayName));
+        } else {
+            mContainer.setVisibility(View.GONE);
+        }
+    }
+}
diff --git a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
index f1dca1d..933dbe0 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/RootsCache.java
@@ -104,7 +104,8 @@
         mRecentsRoot.authority = null;
         mRecentsRoot.rootId = null;
         mRecentsRoot.icon = R.drawable.ic_root_recent;
-        mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE;
+        mRecentsRoot.flags = Root.FLAG_LOCAL_ONLY | Root.FLAG_SUPPORTS_CREATE
+                | Root.FLAG_SUPPORTS_DIR_SELECTION;
         mRecentsRoot.title = mContext.getString(R.string.root_recent);
         mRecentsRoot.availableBytes = -1;
 
@@ -349,12 +350,15 @@
         final List<RootInfo> matching = Lists.newArrayList();
         for (RootInfo root : roots) {
             final boolean supportsCreate = (root.flags & Root.FLAG_SUPPORTS_CREATE) != 0;
+            final boolean supportsDir = (root.flags & Root.FLAG_SUPPORTS_DIR_SELECTION) != 0;
             final boolean advanced = (root.flags & Root.FLAG_ADVANCED) != 0;
             final boolean localOnly = (root.flags & Root.FLAG_LOCAL_ONLY) != 0;
             final boolean empty = (root.flags & Root.FLAG_EMPTY) != 0;
 
             // Exclude read-only devices when creating
             if (state.action == State.ACTION_CREATE && !supportsCreate) continue;
+            // Exclude roots that don't support directory picking
+            if (state.action == State.ACTION_PICK_DIRECTORY && !supportsDir) continue;
             // Exclude advanced devices when not requested
             if (!state.showAdvanced && advanced) continue;
             // Exclude non-local devices when local only
diff --git a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java b/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
deleted file mode 100644
index 1a47308..0000000
--- a/packages/DocumentsUI/src/com/android/documentsui/TestActivity.java
+++ /dev/null
@@ -1,268 +0,0 @@
-/*
- * Copyright (C) 2013 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 com.android.documentsui;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.net.Uri;
-import android.os.Bundle;
-import android.provider.DocumentsContract;
-import android.util.Log;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.CheckBox;
-import android.widget.LinearLayout;
-import android.widget.ScrollView;
-import android.widget.TextView;
-
-import libcore.io.IoUtils;
-import libcore.io.Streams;
-
-import java.io.InputStream;
-import java.io.OutputStream;
-
-public class TestActivity extends Activity {
-    private static final String TAG = "TestActivity";
-
-    private static final int CODE_READ = 42;
-    private static final int CODE_WRITE = 43;
-
-    private TextView mResult;
-
-    @Override
-    public void onCreate(Bundle icicle) {
-        super.onCreate(icicle);
-
-        final Context context = this;
-
-        final LinearLayout view = new LinearLayout(context);
-        view.setOrientation(LinearLayout.VERTICAL);
-
-        mResult = new TextView(context);
-        view.addView(mResult);
-
-        final CheckBox multiple = new CheckBox(context);
-        multiple.setText("ALLOW_MULTIPLE");
-        view.addView(multiple);
-        final CheckBox localOnly = new CheckBox(context);
-        localOnly.setText("LOCAL_ONLY");
-        view.addView(localOnly);
-
-        Button button;
-        button = new Button(context);
-        button.setText("OPEN_DOC */*");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("*/*");
-                if (multiple.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                }
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_READ);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("OPEN_DOC image/*");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("image/*");
-                if (multiple.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                }
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_READ);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("OPEN_DOC audio/ogg");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("audio/ogg");
-                if (multiple.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                }
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_READ);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("OPEN_DOC text/plain, application/msword");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("*/*");
-                intent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] {
-                        "text/plain", "application/msword" });
-                if (multiple.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                }
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_READ);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("CREATE_DOC text/plain");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("text/plain");
-                intent.putExtra(Intent.EXTRA_TITLE, "foobar.txt");
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_WRITE);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("CREATE_DOC image/png");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("image/png");
-                intent.putExtra(Intent.EXTRA_TITLE, "mypicture.png");
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(intent, CODE_WRITE);
-            }
-        });
-        view.addView(button);
-
-        button = new Button(context);
-        button.setText("GET_CONTENT */*");
-        button.setOnClickListener(new OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
-                intent.addCategory(Intent.CATEGORY_OPENABLE);
-                intent.setType("*/*");
-                if (multiple.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
-                }
-                if (localOnly.isChecked()) {
-                    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
-                }
-                startActivityForResult(Intent.createChooser(intent, "Kittens!"), CODE_READ);
-            }
-        });
-        view.addView(button);
-
-        final ScrollView scroll = new ScrollView(context);
-        scroll.addView(view);
-
-        setContentView(scroll);
-    }
-
-    @Override
-    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
-        mResult.setText(null);
-        String result = "resultCode=" + resultCode + ", data=" + String.valueOf(data);
-
-        if (requestCode == CODE_READ) {
-            final Uri uri = data != null ? data.getData() : null;
-            if (uri != null) {
-                if (DocumentsContract.isDocumentUri(this, uri)) {
-                    result += "; DOC_ID";
-                }
-                try {
-                    getContentResolver().takePersistableUriPermission(
-                            uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
-                } catch (SecurityException e) {
-                    result += "; FAILED TO TAKE";
-                    Log.e(TAG, "Failed to take", e);
-                }
-                InputStream is = null;
-                try {
-                    is = getContentResolver().openInputStream(uri);
-                    final int length = Streams.readFullyNoClose(is).length;
-                    result += "; read length=" + length;
-                } catch (Exception e) {
-                    result += "; ERROR";
-                    Log.e(TAG, "Failed to read " + uri, e);
-                } finally {
-                    IoUtils.closeQuietly(is);
-                }
-            } else {
-                result += "no uri?";
-            }
-        } else if (requestCode == CODE_WRITE) {
-            final Uri uri = data != null ? data.getData() : null;
-            if (uri != null) {
-                if (DocumentsContract.isDocumentUri(this, uri)) {
-                    result += "; DOC_ID";
-                }
-                try {
-                    getContentResolver().takePersistableUriPermission(
-                            uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-                } catch (SecurityException e) {
-                    result += "; FAILED TO TAKE";
-                    Log.e(TAG, "Failed to take", e);
-                }
-                OutputStream os = null;
-                try {
-                    os = getContentResolver().openOutputStream(uri);
-                    os.write("THE COMPLETE WORKS OF SHAKESPEARE".getBytes());
-                } catch (Exception e) {
-                    result += "; ERROR";
-                    Log.e(TAG, "Failed to write " + uri, e);
-                } finally {
-                    IoUtils.closeQuietly(os);
-                }
-            } else {
-                result += "no uri?";
-            }
-        }
-
-        Log.d(TAG, result);
-        mResult.setText(result);
-    }
-}
diff --git a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
index 559e052..16fc3e5 100644
--- a/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
+++ b/packages/ExternalStorageProvider/src/com/android/externalstorage/ExternalStorageProvider.java
@@ -27,6 +27,7 @@
 import android.os.CancellationSignal;
 import android.os.Environment;
 import android.os.FileObserver;
+import android.os.FileUtils;
 import android.os.ParcelFileDescriptor;
 import android.os.storage.StorageManager;
 import android.os.storage.StorageVolume;
@@ -143,7 +144,7 @@
                 final RootInfo root = new RootInfo();
                 root.rootId = rootId;
                 root.flags = Root.FLAG_SUPPORTS_CREATE | Root.FLAG_LOCAL_ONLY | Root.FLAG_ADVANCED
-                        | Root.FLAG_SUPPORTS_SEARCH;
+                        | Root.FLAG_SUPPORTS_SEARCH | Root.FLAG_SUPPORTS_DIR_SELECTION;
                 if (ROOT_ID_PRIMARY_EMULATED.equals(rootId)) {
                     root.title = getContext().getString(R.string.root_internal_storage);
                 } else {
@@ -240,8 +241,8 @@
                 flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
             } else {
                 flags |= Document.FLAG_SUPPORTS_WRITE;
+                flags |= Document.FLAG_SUPPORTS_DELETE;
             }
-            flags |= Document.FLAG_SUPPORTS_DELETE;
         }
 
         final String displayName = file.getName();
@@ -284,11 +285,26 @@
     }
 
     @Override
+    public boolean isChildDocument(String parentDocId, String docId) {
+        try {
+            final File parent = getFileForDocId(parentDocId).getCanonicalFile();
+            final File doc = getFileForDocId(docId).getCanonicalFile();
+            return FileUtils.contains(parent, doc);
+        } catch (IOException e) {
+            throw new IllegalArgumentException(
+                    "Failed to determine if " + docId + " is child of " + parentDocId + ": " + e);
+        }
+    }
+
+    @Override
     public String createDocument(String docId, String mimeType, String displayName)
             throws FileNotFoundException {
         final File parent = getFileForDocId(docId);
-        File file;
+        if (!parent.isDirectory()) {
+            throw new IllegalArgumentException("Parent document isn't a directory");
+        }
 
+        File file;
         if (Document.MIME_TYPE_DIR.equals(mimeType)) {
             file = new File(parent, displayName);
             if (!file.mkdir()) {
@@ -317,6 +333,7 @@
 
     @Override
     public void deleteDocument(String docId) throws FileNotFoundException {
+        // TODO: extend to delete directories
         final File file = getFileForDocId(docId);
         if (!file.delete()) {
             throw new IllegalStateException("Failed to delete " + file);
diff --git a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
index f710a8e..dc614db 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_czech.kcm
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 #
-# Czech keyboard layout.
+# Czech (EU - qwerty) keyboard layout.
 #
 
 type OVERLAY
@@ -26,6 +26,8 @@
     label:                              ';'
     base:                               ';'
     shift:                              '\u00b0'
+    ralt:                               '\u0060'
+    shift+ralt:                         '\u007e'
 }
 
 key 1 {
@@ -38,6 +40,7 @@
 key 2 {
     label:                              '2'
     base:                               '\u011b'
+    capslock:                           '\u011a'
     shift:                              '2'
     ralt:                               '@'
 }
@@ -45,6 +48,7 @@
 key 3 {
     label:                              '3'
     base:                               '\u0161'
+    capslock:                           '\u0160'
     shift:                              '3'
     ralt:                               '#'
 }
@@ -52,6 +56,7 @@
 key 4 {
     label:                              '4'
     base:                               '\u010d'
+    capslock:                           '\u010c'
     shift:                              '4'
     ralt:                               '$'
 }
@@ -59,6 +64,7 @@
 key 5 {
     label:                              '5'
     base:                               '\u0159'
+    capslock:                           '\u0158'
     shift:                              '5'
     ralt:                               '%'
 }
@@ -66,6 +72,7 @@
 key 6 {
     label:                              '6'
     base:                               '\u017e'
+    capslock:                           '\u017d'
     shift:                              '6'
     ralt:                               '^'
 }
@@ -73,6 +80,7 @@
 key 7 {
     label:                              '7'
     base:                               '\u00fd'
+    capslock:                           '\u00dd'
     shift:                              '7'
     ralt:                               '&'
 }
@@ -80,6 +88,7 @@
 key 8 {
     label:                              '8'
     base:                               '\u00e1'
+    capslock:                           '\u00c1'
     shift:                              '8'
     ralt:                               '*'
 }
@@ -87,6 +96,7 @@
 key 9 {
     label:                              '9'
     base:                               '\u00ed'
+    capslock:                           '\u00cd'
     shift:                              '9'
     ralt:                               '('
 }
@@ -94,6 +104,7 @@
 key 0 {
     label:                              '0'
     base:                               '\u00e9'
+    capslock:                           '\u00c9'
     shift:                              '0'
     ralt:                               ')'
 }
@@ -180,6 +191,7 @@
 key LEFT_BRACKET {
     label:                              '\u00fa'
     base:                               '\u00fa'
+    capslock:                           '\u00da'
     shift:                              '/'
     ralt:                               '['
     ralt+shift:                         '{'
@@ -252,6 +264,7 @@
 key SEMICOLON {
     label:                              '\u016f'
     base:                               '\u016f'
+    capslock:                           '\u016e'
     shift:                              '"'
     ralt:                               ';'
     ralt+shift:                         ':'
@@ -261,8 +274,8 @@
     label:                              '\u00a7'
     base:                               '\u00a7'
     shift:                              '!'
-    ralt:                               '\''
-    ralt+shift:                         '"'
+    ralt:                               '\u00a4'
+    ralt+shift:                         '\u005e'
 }
 
 key BACKSLASH {
@@ -279,6 +292,8 @@
     label:                              '\\'
     base:                               '\\'
     shift:                              '|'
+    ralt:                               '\u00df'
+    shift+ralt:                         '\u02dd'
 }
 
 key Z {
@@ -330,6 +345,7 @@
     base:                               ','
     shift:                              '?'
     ralt:                               '<'
+    shift+ralt:                         '\u00d7'
 }
 
 key PERIOD {
@@ -337,6 +353,7 @@
     base:                               '.'
     shift:                              ':'
     ralt:                               '>'
+    shift+ralt:                         '\u00f7'
 }
 
 key SLASH {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
index 0fabf02..66c1c98 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_english_us_intl.kcm
@@ -122,7 +122,7 @@
     base:                               'q'
     shift, capslock:                    'Q'
     ralt:                               '\u00e4'
-    shift+ralt:                         '\u00c4'
+    shift+ralt, capslock+ralt:          '\u00c4'
 }
 
 key W {
@@ -130,7 +130,7 @@
     base:                               'w'
     shift, capslock:                    'W'
     ralt:                               '\u00e5'
-    shift+ralt:                         '\u00c5'
+    shift+ralt, capslock+ralt:          '\u00c5'
 }
 
 key E {
@@ -138,7 +138,7 @@
     base:                               'e'
     shift, capslock:                    'E'
     ralt:                               '\u00e9'
-    shift+ralt:                         '\u00c9'
+    shift+ralt, capslock+ralt:          '\u00c9'
 }
 
 key R {
@@ -153,7 +153,7 @@
     base:                               't'
     shift, capslock:                    'T'
     ralt:                               '\u00fe'
-    shift+ralt:                         '\u00de'
+    shift+ralt, capslock+ralt:          '\u00de'
 }
 
 key Y {
@@ -161,7 +161,7 @@
     base:                               'y'
     shift, capslock:                    'Y'
     ralt:                               '\u00fc'
-    shift+ralt:                         '\u00dc'
+    shift+ralt, capslock+ralt:          '\u00dc'
 }
 
 key U {
@@ -169,7 +169,7 @@
     base:                               'u'
     shift, capslock:                    'U'
     ralt:                               '\u00fa'
-    shift+ralt:                         '\u00da'
+    shift+ralt, capslock+ralt:          '\u00da'
 }
 
 key I {
@@ -177,7 +177,7 @@
     base:                               'i'
     shift, capslock:                    'I'
     ralt:                               '\u00ed'
-    shift+ralt:                         '\u00cd'
+    shift+ralt, capslock+ralt:          '\u00cd'
 }
 
 key O {
@@ -185,7 +185,7 @@
     base:                               'o'
     shift, capslock:                    'O'
     ralt:                               '\u00f3'
-    shift+ralt:                         '\u00d3'
+    shift+ralt, capslock+ralt:          '\u00d3'
 }
 
 key P {
@@ -193,7 +193,7 @@
     base:                               'p'
     shift, capslock:                    'P'
     ralt:                               '\u00f6'
-    shift+ralt:                         '\u00d6'
+    shift+ralt, capslock+ralt:          '\u00d6'
 }
 
 key LEFT_BRACKET {
@@ -225,7 +225,7 @@
     base:                               'a'
     shift, capslock:                    'A'
     ralt:                               '\u00e1'
-    shift+ralt:                         '\u00c1'
+    shift+ralt, ralt+capslock:          '\u00c1'
 }
 
 key S {
@@ -241,7 +241,7 @@
     base:                               'd'
     shift, capslock:                    'D'
     ralt:                               '\u00f0'
-    shift+ralt:                         '\u00d0'
+    shift+ralt, capslock+ralt:          '\u00d0'
 }
 
 key F {
@@ -279,7 +279,7 @@
     base:                               'l'
     shift, capslock:                    'L'
     ralt:                               '\u00f8'
-    shift+ralt:                         '\u00d8'
+    shift+ralt, capslock+ralt:          '\u00d8'
 }
 
 key SEMICOLON {
@@ -313,7 +313,7 @@
     base:                               'z'
     shift, capslock:                    'Z'
     ralt:                               '\u00e6'
-    shift+ralt:                         '\u00c6'
+    shift+ralt, capslock+ralt:          '\u00c6'
 }
 
 key X {
@@ -347,7 +347,7 @@
     base:                               'n'
     shift, capslock:                    'N'
     ralt:                               '\u00f1'
-    shift+ralt:                         '\u00d1'
+    shift+ralt, capslock+ralt:          '\u00d1'
 }
 
 key M {
@@ -362,7 +362,7 @@
     base:                               ','
     shift:                              '<'
     ralt:                               '\u00e7'
-    shift+ralt:                         '\u00c7'
+    shift+ralt, capslock+ralt:          '\u00c7'
 }
 
 key PERIOD {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
index 70c1fa4..2eb0f63 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_slovak.kcm
@@ -13,7 +13,7 @@
 # limitations under the License.
 
 #
-# Slovak keyboard layout.
+# Slovak (EU - qwerty) keyboard layout.
 #
 
 type OVERLAY
@@ -26,94 +26,90 @@
     label:                              ';'
     base:                               ';'
     shift:                              '\u00b0'
-    ralt:                               '`'
-    ralt+shift:                         '~'
 }
 
 key 1 {
     label:                              '1'
     base:                               '+'
     shift:                              '1'
-    ralt:                               '!'
+    ralt:                               '~'
 }
 
 key 2 {
     label:                              '2'
     base:                               '\u013e'
     shift:                              '2'
-    ralt:                               '@'
+    ralt:                               '\u02c7'
 }
 
 key 3 {
     label:                              '3'
     base:                               '\u0161'
     shift:                              '3'
-    ralt:                               '#'
+    ralt:                               '\u0302'
 }
 
 key 4 {
     label:                              '4'
     base:                               '\u010d'
     shift:                              '4'
-    ralt:                               '$'
+    ralt:                               '\u02d8'
 }
 
 key 5 {
     label:                              '5'
     base:                               '\u0165'
     shift:                              '5'
-    ralt:                               '%'
+    ralt:                               '\u00b0'
 }
 
 key 6 {
     label:                              '6'
     base:                               '\u017e'
     shift:                              '6'
-    ralt:                               '^'
+    ralt:                               '\u02db'
 }
 
 key 7 {
     label:                              '7'
     base:                               '\u00fd'
     shift:                              '7'
-    ralt:                               '&'
+    ralt:                               '\u0300'
 }
 
 key 8 {
     label:                              '8'
     base:                               '\u00e1'
     shift:                              '8'
-    ralt:                               '*'
+    ralt:                               '\u02d9'
 }
 
 key 9 {
     label:                              '9'
     base:                               '\u00ed'
     shift:                              '9'
-    ralt:                               '('
+    ralt:                               '\u0301'
 }
 
 key 0 {
     label:                              '0'
     base:                               '\u00e9'
     shift:                              '0'
-    ralt:                               ')'
+    ralt:                               '\u02dd'
 }
 
 key MINUS {
     label:                              '='
     base:                               '='
     shift:                              '%'
-    ralt:                               '-'
-    ralt+shift:                         '_'
+    ralt:                               '\u0308'
 }
 
 key EQUALS {
     label:                              '\u00b4'
     base:                               '\u0301'
     shift:                              '\u030c'
-    ralt:                               '='
-    ralt+shift:                         '+'
+    ralt:                               '\u00b8'
 }
 
 ### ROW 2
@@ -179,22 +175,21 @@
     label:                              'P'
     base:                               'p'
     shift, capslock:                    'P'
+    ralt:                               '\''
 }
 
 key LEFT_BRACKET {
     label:                              '\u00fa'
     base:                               '\u00fa'
     shift:                              '/'
-    ralt:                               '['
-    ralt+shift:                         '{'
+    ralt:                               '\u00f7'
 }
 
 key RIGHT_BRACKET {
     label:                              '\u00e4'
     base:                               '\u00e4'
     shift:                              '('
-    ralt:                               ']'
-    ralt+shift:                         '}'
+    ralt:                               '\u00d7'
 }
 
 ### ROW 3
@@ -209,24 +204,28 @@
     label:                              'S'
     base:                               's'
     shift, capslock:                    'S'
+    ralt:                               '\u0111'
 }
 
 key D {
     label:                              'D'
     base:                               'd'
     shift, capslock:                    'D'
+    ralt:                               '\u0110'
 }
 
 key F {
     label:                              'F'
     base:                               'f'
     shift, capslock:                    'F'
+    ralt:                               '['
 }
 
 key G {
     label:                              'G'
     base:                               'g'
     shift, capslock:                    'G'
+    ralt:                               ']'
 }
 
 key H {
@@ -245,64 +244,65 @@
     label:                              'K'
     base:                               'k'
     shift, capslock:                    'K'
+    ralt:                               '\u0142'
 }
 
 key L {
     label:                              'L'
     base:                               'l'
     shift, capslock:                    'L'
+    ralt:                               '\u0141'
 }
 
 key SEMICOLON {
     label:                              '\u00f4'
     base:                               '\u00f4'
     shift:                              '"'
-    ralt:                               ';'
-    ralt+shift:                         ':'
+    ralt:                               '$'
 }
 
 key APOSTROPHE {
     label:                              '\u00a7'
     base:                               '\u00a7'
     shift:                              '!'
-    ralt:                               '\''
-    ralt+shift:                         '"'
+    ralt:                               '\u00df'
 }
 
 key BACKSLASH {
     label:                              '\u0148'
     base:                               '\u0148'
     shift:                              ')'
-    ralt:                               '\\'
-    ralt+shift:                         '|'
+    ralt:                               '\u00a4'
 }
 
 ### ROW 4
 
 key PLUS {
-    label:                              '\\'
-    base:                               '\\'
-    shift:                              '|'
-    ralt:                               '&'
-    ralt+shift:                         '*'
+    label:                              '&'
+    base:                               '&'
+    shift:                              '*'
+    ralt:                               '<'
 }
 
 key Z {
     label:                              'Z'
     base:                               'z'
     shift, capslock:                    'Z'
+    ralt:                               '>'
 }
 
 key X {
     label:                              'X'
     base:                               'x'
     shift, capslock:                    'X'
+    ralt:                               '#'
 }
 
 key C {
     label:                              'C'
     base:                               'c'
     shift, capslock:                    'C'
+    ralt:                               '&'
 }
 
 key V {
@@ -316,12 +316,14 @@
     label:                              'B'
     base:                               'b'
     shift, capslock:                    'B'
+    ralt:                               '{'
 }
 
 key N {
     label:                              'N'
     base:                               'n'
     shift, capslock:                    'N'
+    ralt:                               '}'
 }
 
 key M {
@@ -348,6 +350,5 @@
     label:                              '-'
     base:                               '-'
     shift:                              '_'
-    ralt:                               '/'
-    ralt+shift:                         '?'
+    ralt:                               '*'
 }
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
index a75d154..9e20462 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_french.kcm
@@ -56,12 +56,14 @@
     label:                              '4'
     base:                               '4'
     shift:                              '\u00e7'
+    ralt:                               '\u00b0'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
     shift:                              '%'
+    ralt:                               '\u00a7'
 }
 
 key 6 {
diff --git a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
index ae93f4b..7fbd1a9 100644
--- a/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
+++ b/packages/InputDevices/res/raw/keyboard_layout_swiss_german.kcm
@@ -56,12 +56,14 @@
     label:                              '4'
     base:                               '4'
     shift:                              '\u00e7'
+    ralt:                               '\u00b0'
 }
 
 key 5 {
     label:                              '5'
     base:                               '5'
     shift:                              '%'
+    ralt:                               '\u00a7'
 }
 
 key 6 {
@@ -178,6 +180,8 @@
     label:                              '\u00fc'
     base:                               '\u00fc'
     shift:                              '\u00e8'
+    capslock:                           '\u00dc'
+    capslock+shift:                     '\u00c8'
     ralt:                               '['
 }
 
@@ -248,12 +252,16 @@
     label:                              '\u00f6'
     base:                               '\u00f6'
     shift:                              '\u00e9'
+    capslock:                           '\u00d6'
+    capslock+shift:                     '\u00c9'
 }
 
 key APOSTROPHE {
     label:                              '\u00e4'
     base:                               '\u00e4'
     shift:                              '\u00e0'
+    capslock:                           '\u00c4'
+    capslock+shift:                     '\u00c0'
     ralt:                               '{'
 }
 
diff --git a/packages/Keyguard/Android.mk b/packages/Keyguard/Android.mk
index 5b08674..1be44f9 100644
--- a/packages/Keyguard/Android.mk
+++ b/packages/Keyguard/Android.mk
@@ -19,7 +19,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) $(call all-subdir-Iaidl-files) \
                    $(call all-proto-files-under,src)
 
-LOCAL_PACKAGE_NAME := Keyguard
+LOCAL_MODULE := Keyguard
 
 LOCAL_CERTIFICATE := platform
 
@@ -30,6 +30,8 @@
 LOCAL_PROTOC_OPTIMIZE_TYPE := nano
 LOCAL_PROTO_JAVA_OUTPUT_PARAMS := optional_field_style=accessors
 
-include $(BUILD_PACKAGE)
+LOCAL_RESOURCE_DIR := $(LOCAL_PATH)/res
 
-#include $(call all-makefiles-under,$(LOCAL_PATH))
+include $(BUILD_STATIC_JAVA_LIBRARY)
+
+#include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file
diff --git a/packages/Keyguard/AndroidManifest.xml b/packages/Keyguard/AndroidManifest.xml
index 75b7dbd..352317d 100644
--- a/packages/Keyguard/AndroidManifest.xml
+++ b/packages/Keyguard/AndroidManifest.xml
@@ -44,11 +44,7 @@
     <application android:label="@string/app_name"
         android:process="com.android.systemui"
         android:persistent="true"
-        android:supportsRtl="true"
-        android:requiredForProfile="all">
-
-        <service android:name=".KeyguardService"
-            android:exported="true" />
+        android:supportsRtl="true">
 
     </application>
 </manifest>
diff --git a/packages/Keyguard/res/layout-land/keyguard_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
index 9f1c1f0..1d596d3 100644
--- a/packages/Keyguard/res/layout-land/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
index ebd0a64..49b4212 100644
--- a/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardSimpleHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
index da31065..50c2709 100644
--- a/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-land/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
 
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardWidgetCarousel
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:paddingLeft="25dp"
     android:paddingRight="25dp"
diff --git a/packages/Keyguard/res/layout-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
index 136b296..8223db4 100644
--- a/packages/Keyguard/res/layout-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
index cba7667..ed600b0 100644
--- a/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_simple_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardSimpleHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
index d0a07ca..6d7d864 100644
--- a/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
+++ b/packages/Keyguard/res/layout-port/keyguard_widget_pager.xml
@@ -19,7 +19,7 @@
 
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardWidgetPager
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/app_widget_container"
     android:paddingLeft="25dp"
diff --git a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
index 85f6b6d..ba2f3a6 100644
--- a/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
+++ b/packages/Keyguard/res/layout-sw600dp-port/keyguard_host_view.xml
@@ -21,7 +21,7 @@
     and the security view. -->
 <com.android.keyguard.KeyguardHostView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_host_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_account_view.xml b/packages/Keyguard/res/layout/keyguard_account_view.xml
index 766effa..bde2ec6 100644
--- a/packages/Keyguard/res/layout/keyguard_account_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_account_view.xml
@@ -18,7 +18,7 @@
 -->
 <com.android.keyguard.KeyguardAccountView
     xmlns:android="http://schemas.android.com/apk/res/android"
-	xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+	xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_account_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_bouncer.xml b/packages/Keyguard/res/layout/keyguard_bouncer.xml
new file mode 100644
index 0000000..8716ebc
--- /dev/null
+++ b/packages/Keyguard/res/layout/keyguard_bouncer.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <View android:id="@+id/bouncer_background"
+        android:background="#aa000000"
+        android:clickable="true"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"/>
+
+    <include
+        style="@style/BouncerSecurityContainer"
+        layout="@layout/keyguard_simple_host_view"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+</FrameLayout>
+
diff --git a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
index b4847f0..b2d0219 100644
--- a/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_emergency_carrier_area.xml
@@ -20,6 +20,7 @@
 <!-- This contains emergency call button and carrier as shared by pin/pattern/password screens -->
 <com.android.keyguard.EmergencyCarrierArea
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
@@ -35,7 +36,8 @@
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceMedium"
         android:textSize="@dimen/kg_status_line_font_size"
-        android:textColor="?android:attr/textColorSecondary" />
+        android:textColor="?android:attr/textColorSecondary"
+        androidprv:allCaps="@bool/kg_use_all_caps" />
 
     <LinearLayout
         android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
index 94c68a5..8c8ec7a 100644
--- a/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_face_unlock_view.xml
@@ -20,7 +20,7 @@
 <!-- This is the screen that allows the user to unlock by showing their face.  -->
 <com.android.keyguard.KeyguardFaceUnlockView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_face_unlock_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
index c1d5326..83036ab 100644
--- a/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
+++ b/packages/Keyguard/res/layout/keyguard_multi_user_selector.xml
@@ -17,7 +17,7 @@
 */
 -->
 <com.android.keyguard.KeyguardMultiUserSelectorView
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     xmlns:android="http://schemas.android.com/apk/res/android"
     androidprv:layout_childType="userSwitcher"
     android:id="@+id/keyguard_user_selector"
diff --git a/packages/Keyguard/res/layout/keyguard_password_view.xml b/packages/Keyguard/res/layout/keyguard_password_view.xml
index d8012bf..ed3f0e0 100644
--- a/packages/Keyguard/res/layout/keyguard_password_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_password_view.xml
@@ -18,7 +18,7 @@
 -->
 <com.android.keyguard.KeyguardPasswordView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_password_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pattern_view.xml b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
index 0c9380c..3d7820f 100644
--- a/packages/Keyguard/res/layout/keyguard_pattern_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pattern_view.xml
@@ -22,7 +22,7 @@
      is the portrait layout.  -->
 <com.android.keyguard.KeyguardPatternView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_pattern_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_pin_view.xml b/packages/Keyguard/res/layout/keyguard_pin_view.xml
index 00c6a21..a804c8c 100644
--- a/packages/Keyguard/res/layout/keyguard_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_pin_view.xml
@@ -19,7 +19,7 @@
 
 <com.android.keyguard.KeyguardPINView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_pin_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_presentation.xml b/packages/Keyguard/res/layout/keyguard_presentation.xml
index 7df0b70..ab676aa 100644
--- a/packages/Keyguard/res/layout/keyguard_presentation.xml
+++ b/packages/Keyguard/res/layout/keyguard_presentation.xml
@@ -20,7 +20,7 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/presentation"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
diff --git a/packages/Keyguard/res/layout/keyguard_selector_view.xml b/packages/Keyguard/res/layout/keyguard_selector_view.xml
index 6cb5e67..d3064ed 100644
--- a/packages/Keyguard/res/layout/keyguard_selector_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_selector_view.xml
@@ -20,7 +20,7 @@
 <!-- This is the selector widget that allows the user to select an action. -->
 <com.android.keyguard.KeyguardSelectorView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_selector_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
diff --git a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
index eccac19..0e2b33a 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_pin_view.xml
@@ -19,7 +19,7 @@
 <!-- This is the SIM PIN view that allows the user to enter a SIM PIN to unlock the device. -->
 <com.android.keyguard.KeyguardSimPinView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_sim_pin_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
@@ -52,7 +52,7 @@
            android:orientation="horizontal"
            android:layout_weight="1"
            >
-           <TextView android:id="@+id/pinEntry"
+           <TextView android:id="@+id/simPinEntry"
                android:editable="true"
                android:layout_width="0dip"
                android:layout_height="match_parent"
@@ -96,7 +96,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="1"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -105,7 +105,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="2"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -114,7 +114,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="3"
                />
        </LinearLayout>
@@ -130,7 +130,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="4"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -139,7 +139,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="5"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -148,7 +148,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="6"
                />
        </LinearLayout>
@@ -164,7 +164,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="7"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -173,7 +173,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="8"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -182,7 +182,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="9"
                />
        </LinearLayout>
@@ -203,7 +203,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/simPinEntry"
                androidprv:digit="0"
                />
            <ImageButton
diff --git a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
index fe37203..88049a7 100644
--- a/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_sim_puk_view.xml
@@ -20,7 +20,7 @@
     carrier-provided PUK code and entering a new SIM PIN for it. -->
 <com.android.keyguard.KeyguardSimPukView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_sim_puk_view"
     android:orientation="vertical"
     android:layout_width="match_parent"
@@ -53,7 +53,7 @@
            android:orientation="horizontal"
            android:layout_weight="1"
            >
-           <TextView android:id="@+id/pinEntry"
+           <TextView android:id="@+id/pukEntry"
                android:editable="true"
                android:layout_width="0dip"
                android:layout_height="match_parent"
@@ -97,7 +97,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="1"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -106,7 +106,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="2"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -115,7 +115,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="3"
                />
        </LinearLayout>
@@ -131,7 +131,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="4"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -140,7 +140,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="5"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -149,7 +149,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="6"
                />
        </LinearLayout>
@@ -165,7 +165,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="7"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -174,7 +174,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="8"
                />
            <view class="com.android.keyguard.NumPadKey"
@@ -183,7 +183,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="9"
                />
        </LinearLayout>
@@ -204,7 +204,7 @@
                android:layout_width="0px"
                android:layout_height="match_parent"
                android:layout_weight="1"
-               androidprv:textView="@+id/pinEntry"
+               androidprv:textView="@+id/pukEntry"
                androidprv:digit="0"
                />
            <ImageButton
diff --git a/packages/Keyguard/res/layout/keyguard_status_area.xml b/packages/Keyguard/res/layout/keyguard_status_area.xml
index 98ba512..2730517 100644
--- a/packages/Keyguard/res/layout/keyguard_status_area.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_area.xml
@@ -20,7 +20,7 @@
 <!-- This is a view that shows general status information in Keyguard. -->
 <LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
diff --git a/packages/Keyguard/res/layout/keyguard_status_view.xml b/packages/Keyguard/res/layout/keyguard_status_view.xml
index a4d298a..546ddd4 100644
--- a/packages/Keyguard/res/layout/keyguard_status_view.xml
+++ b/packages/Keyguard/res/layout/keyguard_status_view.xml
@@ -18,43 +18,38 @@
 -->
 
 <!-- This is a view that shows general status information in Keyguard. -->
-<com.android.keyguard.KeyguardWidgetFrame
+<com.android.keyguard.KeyguardStatusView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/res/com.android.keyguard"
+    xmlns:androidprv="http://schemas.android.com/apk/res-auto"
     android:id="@+id/keyguard_status_view"
+    android:orientation="vertical"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="wrap_content"
     androidprv:layout_maxWidth="@dimen/keyguard_security_width"
     androidprv:layout_maxHeight="@dimen/keyguard_security_height"
-    android:gravity="center">
-
-    <com.android.keyguard.KeyguardStatusView
-        android:id="@+id/keyguard_status_view_face_palm"
-        android:orientation="vertical"
+    android:gravity="center_horizontal|top"
+    android:layout_marginTop="32dp"
+    android:layout_marginBottom="32dp"
+    android:contentDescription="@string/keyguard_accessibility_status">
+    <LinearLayout
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:gravity="center_horizontal|top"
-        android:contentDescription="@string/keyguard_accessibility_status">
-        <LinearLayout
-            android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal|top"
+        android:orientation="vertical"
+        android:focusable="true">
+        <TextClock
+            android:id="@+id/clock_view"
+            android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_horizontal|top"
-            android:orientation="vertical"
-            android:focusable="true">
-            <TextClock
-                android:id="@+id/clock_view"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center_horizontal|top"
-                android:textColor="@color/clock_white"
-                android:singleLine="true"
-                style="@style/widget_big_thin"
-                android:format12Hour="@string/keyguard_widget_12_hours_format"
-                android:format24Hour="@string/keyguard_widget_24_hours_format"
-                android:baselineAligned="true"
-                android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
+            android:textColor="@color/clock_white"
+            android:singleLine="true"
+            style="@style/widget_big_thin"
+            android:format12Hour="@string/keyguard_widget_12_hours_format"
+            android:format24Hour="@string/keyguard_widget_24_hours_format"
+            android:baselineAligned="true"
+            android:layout_marginBottom="@dimen/bottom_text_spacing_digital" />
 
-            <include layout="@layout/keyguard_status_area" />
-        </LinearLayout>
-    </com.android.keyguard.KeyguardStatusView>
-</com.android.keyguard.KeyguardWidgetFrame>
+        <include layout="@layout/keyguard_status_area" />
+    </LinearLayout>
+</com.android.keyguard.KeyguardStatusView>
diff --git a/packages/Keyguard/res/values-af/activitystrings.xml b/packages/Keyguard/res/values-af/activitystrings.xml
deleted file mode 100644
index f6e8d5e..0000000
--- a/packages/Keyguard/res/values-af/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardToetsAktiwiteit"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"VerenigdeKamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Geen sekuriteit nie"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Wagwoord"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Patroon"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Kies legstuk…"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"opSkermAfgeskakel"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"opSkermAangeskakel"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doenKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifieerOntsluit"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-af/strings.xml b/packages/Keyguard/res/values-af/strings.xml
index 2667ed2..a046dc5 100644
--- a/packages/Keyguard/res/values-af/strings.xml
+++ b/packages/Keyguard/res/values-af/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Voer PIN-kode in"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Voer SIM PUK- en nuwe PIN-kode in"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK-kode"</string>
diff --git a/packages/Keyguard/res/values-am/activitystrings.xml b/packages/Keyguard/res/values-am/activitystrings.xml
deleted file mode 100644
index a6c7449..0000000
--- a/packages/Keyguard/res/values-am/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"ምንም ደህንነት የለም"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"ፒን"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"የይለፍ ቃል"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"ሥርዓተ ጥለት"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"የሲም ፒን"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"የሲም ፒዩኬ"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"ንዑስ ፕሮግራም ይምረጡ..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-am/strings.xml b/packages/Keyguard/res/values-am/strings.xml
index 933ef9c..0bb7993 100644
--- a/packages/Keyguard/res/values-am/strings.xml
+++ b/packages/Keyguard/res/values-am/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"የቁልፍ ጥበቃ"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"ፒን ኮድ ተይብ"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"የሲም PUK እና አዲሱን ፒን ኮድ ይተይቡ"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"የሲም PUK ኮድ"</string>
diff --git a/packages/Keyguard/res/values-ar/activitystrings.xml b/packages/Keyguard/res/values-ar/activitystrings.xml
deleted file mode 100644
index f77d8f00..0000000
--- a/packages/Keyguard/res/values-ar/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"بدون تأمين"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"رقم التعريف الشخصي"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"كلمة المرور"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"نقش"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"رقم التعريف الشخصي لبطاقة SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"رمز PUK لبطاقة SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"جارٍ اختيار أداة..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ar/strings.xml b/packages/Keyguard/res/values-ar/strings.xml
index 83d4b93..eac3216 100644
--- a/packages/Keyguard/res/values-ar/strings.xml
+++ b/packages/Keyguard/res/values-ar/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"‏اكتب رمز رمز PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"‏أدخل رمز PUK لبطاقة SIM ورمز \"رقم التعريف الشخصي\" الجديد"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"‏رمز PUK لبطاقة SIM"</string>
diff --git a/packages/Keyguard/res/values-bg/activitystrings.xml b/packages/Keyguard/res/values-bg/activitystrings.xml
deleted file mode 100644
index 807bcf2..0000000
--- a/packages/Keyguard/res/values-bg/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Без защита"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"ПИН код"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Парола"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Фигура"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"ПИН код за SIM карта"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK код за SIM карта"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Избиране на приспособление..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-bg/strings.xml b/packages/Keyguard/res/values-bg/strings.xml
index 641adbd..ad4285a 100644
--- a/packages/Keyguard/res/values-bg/strings.xml
+++ b/packages/Keyguard/res/values-bg/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Въведете ПИН кода"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Въведете PUK за SIM картата и новия ПИН код"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK код за SIM картата"</string>
diff --git a/packages/Keyguard/res/values-ca/activitystrings.xml b/packages/Keyguard/res/values-ca/activitystrings.xml
deleted file mode 100644
index c18b9bb..0000000
--- a/packages/Keyguard/res/values-ca/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"No hi ha seguretat"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Contrasenya"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Patró"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN de la SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK de la SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Tria un widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ca/strings.xml b/packages/Keyguard/res/values-ca/strings.xml
index 8b81086..7e40709 100644
--- a/packages/Keyguard/res/values-ca/strings.xml
+++ b/packages/Keyguard/res/values-ca/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Bloqueig de teclat"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introdueix el codi PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Escriu el PUK de la SIM i el codi PIN nou."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Codi PUK de la SIM"</string>
diff --git a/packages/Keyguard/res/values-cs/activitystrings.xml b/packages/Keyguard/res/values-cs/activitystrings.xml
deleted file mode 100644
index 354176e..0000000
--- a/packages/Keyguard/res/values-cs/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Žádné zabezpečení"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Heslo"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Gesto"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN SIM karty"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK SIM karty"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Zvolte widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-cs/strings.xml b/packages/Keyguard/res/values-cs/strings.xml
index e4ed02a..53cc707 100644
--- a/packages/Keyguard/res/values-cs/strings.xml
+++ b/packages/Keyguard/res/values-cs/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Uzamčení kláves"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Zadejte kód PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Zadejte kód PUK SIM karty a nový kód PIN."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Kód PUK SIM karty"</string>
diff --git a/packages/Keyguard/res/values-da/activitystrings.xml b/packages/Keyguard/res/values-da/activitystrings.xml
deleted file mode 100644
index af07ba5..0000000
--- a/packages/Keyguard/res/values-da/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Ingen sikkerhed"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"Pinkode"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Adgangskode"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Mønster"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Pinkode til SIM-kort"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-kode til SIM-kort"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Vælg widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-da/strings.xml b/packages/Keyguard/res/values-da/strings.xml
index f8f0a6f..cf1aad9 100644
--- a/packages/Keyguard/res/values-da/strings.xml
+++ b/packages/Keyguard/res/values-da/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Tastaturlås"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Indtast pinkode"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Indtast PUK-koden til SIM-kortet og den nye pinkode"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-kode til SIM-kort"</string>
diff --git a/packages/Keyguard/res/values-de/activitystrings.xml b/packages/Keyguard/res/values-de/activitystrings.xml
deleted file mode 100644
index d8e9272..0000000
--- a/packages/Keyguard/res/values-de/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Keine Sicherheit"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Passwort"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Muster"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN für SIM-Karte"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK für SIM-Karte"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Widget auswählen..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-de/strings.xml b/packages/Keyguard/res/values-de/strings.xml
index edbbffd..14df237 100644
--- a/packages/Keyguard/res/values-de/strings.xml
+++ b/packages/Keyguard/res/values-de/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN-Code eingeben"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Geben Sie den PUK-Code der SIM-Karte und den neuen PIN-Code ein."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-Code der SIM-Karte"</string>
diff --git a/packages/Keyguard/res/values-el/activitystrings.xml b/packages/Keyguard/res/values-el/activitystrings.xml
deleted file mode 100644
index 3941f4f..0000000
--- a/packages/Keyguard/res/values-el/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Χωρίς ασφάλεια"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Κωδικός πρόσβασης"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Μοτίβο"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Κωδικός PIN κάρτας SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"Κωδικός PUK κάρτας SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Επιλογή γραφικού στοιχείου…"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-el/strings.xml b/packages/Keyguard/res/values-el/strings.xml
index be07dcd..63d8409 100644
--- a/packages/Keyguard/res/values-el/strings.xml
+++ b/packages/Keyguard/res/values-el/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Πληκτρολογήστε τον κωδικό αριθμό PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Πληκτρολογήστε τον κωδικό PUK της κάρτας SIM και τον νέο κωδικό PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Κωδικός PUK κάρτας SIM"</string>
diff --git a/packages/Keyguard/res/values-en-rGB/activitystrings.xml b/packages/Keyguard/res/values-en-rGB/activitystrings.xml
deleted file mode 100644
index 88e806e..0000000
--- a/packages/Keyguard/res/values-en-rGB/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"No security"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Password"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Pattern"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Choose widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-en-rGB/strings.xml b/packages/Keyguard/res/values-en-rGB/strings.xml
index f0d81b8..ecc850d 100644
--- a/packages/Keyguard/res/values-en-rGB/strings.xml
+++ b/packages/Keyguard/res/values-en-rGB/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Type PIN code"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Type SIM PUK and new PIN code"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK code"</string>
diff --git a/packages/Keyguard/res/values-en-rIN/strings.xml b/packages/Keyguard/res/values-en-rIN/strings.xml
index f0d81b8..ecc850d 100644
--- a/packages/Keyguard/res/values-en-rIN/strings.xml
+++ b/packages/Keyguard/res/values-en-rIN/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Type PIN code"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Type SIM PUK and new PIN code"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK code"</string>
diff --git a/packages/Keyguard/res/values-es-rUS/activitystrings.xml b/packages/Keyguard/res/values-es-rUS/activitystrings.xml
deleted file mode 100644
index 20117c4..0000000
--- a/packages/Keyguard/res/values-es-rUS/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Sin seguridad"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Contraseña"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Patrón"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN de tarjeta SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK de tarjeta SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Elegir widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-es-rUS/strings.xml b/packages/Keyguard/res/values-es-rUS/strings.xml
index 38beca3..c6d63ba 100644
--- a/packages/Keyguard/res/values-es-rUS/strings.xml
+++ b/packages/Keyguard/res/values-es-rUS/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Bloqueo de teclado"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingresa el código PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Escribe el código PUK de la tarjeta SIM y un nuevo código PIN."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Código PUK de la tarjeta SIM"</string>
diff --git a/packages/Keyguard/res/values-es/activitystrings.xml b/packages/Keyguard/res/values-es/activitystrings.xml
deleted file mode 100644
index 34899cc..0000000
--- a/packages/Keyguard/res/values-es/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Sin seguridad"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Contraseña"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Patrón"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN de tarjeta SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK de tarjeta SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Seleccionar widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-es/strings.xml b/packages/Keyguard/res/values-es/strings.xml
index a93b10d..8a78399 100644
--- a/packages/Keyguard/res/values-es/strings.xml
+++ b/packages/Keyguard/res/values-es/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Bloqueo"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduce el código PIN."</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Escribe el PUK de la tarjeta SIM y un nuevo código PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Código PUK de la tarjeta SIM"</string>
diff --git a/packages/Keyguard/res/values-et-rEE/strings.xml b/packages/Keyguard/res/values-et-rEE/strings.xml
index 90bd829..b837f01 100644
--- a/packages/Keyguard/res/values-et-rEE/strings.xml
+++ b/packages/Keyguard/res/values-et-rEE/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Klahvilukk"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Sisestage PIN-kood"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Sisestage SIM-i PUK- ja uus PIN-kood"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM-i PUK-kood"</string>
diff --git a/packages/Keyguard/res/values-fa/activitystrings.xml b/packages/Keyguard/res/values-fa/activitystrings.xml
deleted file mode 100644
index 735af8d..0000000
--- a/packages/Keyguard/res/values-fa/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"عدم وجود امنیت"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"پین"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"گذرواژه"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"الگو"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"پین سیم کارت"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK سیم کارت"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"انتخاب ابزارک..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-fa/strings.xml b/packages/Keyguard/res/values-fa/strings.xml
index b4a4c61..5d1c487 100644
--- a/packages/Keyguard/res/values-fa/strings.xml
+++ b/packages/Keyguard/res/values-fa/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"پین کد را وارد کنید"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"‏PUK سیم کارت و کد پین جدید را تایپ کنید"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"‏کد PUK سیم کارت"</string>
diff --git a/packages/Keyguard/res/values-fi/activitystrings.xml b/packages/Keyguard/res/values-fi/activitystrings.xml
deleted file mode 100644
index 6e0a5a9..0000000
--- a/packages/Keyguard/res/values-fi/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Ei suojausta"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN-koodi"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Salasana"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Kuvio"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM-kortin PIN-koodi"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM-kortin PUK-koodi"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Valitse widget…"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-fi/strings.xml b/packages/Keyguard/res/values-fi/strings.xml
index e079ffa..bdf6677 100644
--- a/packages/Keyguard/res/values-fi/strings.xml
+++ b/packages/Keyguard/res/values-fi/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Näppäinvahti"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Anna PIN-koodi"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Anna SIM-kortin PUK-koodi ja uusi PIN-koodi"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM-kortin PUK-koodi"</string>
diff --git a/packages/Keyguard/res/values-fr-rCA/strings.xml b/packages/Keyguard/res/values-fr-rCA/strings.xml
index 59f27aa..e77927c 100644
--- a/packages/Keyguard/res/values-fr-rCA/strings.xml
+++ b/packages/Keyguard/res/values-fr-rCA/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Verrouillage du clavier"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Saisissez le NIP."</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Entrez le code PUK et le nouveau NIP de la carte SIM"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Code PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-fr/activitystrings.xml b/packages/Keyguard/res/values-fr/activitystrings.xml
deleted file mode 100644
index dc79842..0000000
--- a/packages/Keyguard/res/values-fr/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Aucune sécurité"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"Code PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Mot de passe"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Schéma"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Code PIN de la carte SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"Clé PUK de la carte SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Sélectionner un widget"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-fr/strings.xml b/packages/Keyguard/res/values-fr/strings.xml
index b910dd4..41be1eb 100644
--- a/packages/Keyguard/res/values-fr/strings.xml
+++ b/packages/Keyguard/res/values-fr/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Protection des touches"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Saisissez le code PIN."</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Saisissez la clé PUK et le nouveau code PIN de la carte SIM."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Clé PUK de la carte SIM"</string>
diff --git a/packages/Keyguard/res/values-hi/activitystrings.xml b/packages/Keyguard/res/values-hi/activitystrings.xml
deleted file mode 100644
index 4b0a082..0000000
--- a/packages/Keyguard/res/values-hi/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"कोई सुरक्षा नहीं"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"पासवर्ड"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"प्रतिमान"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM पिन"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"विजेट चुनें..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-hi/strings.xml b/packages/Keyguard/res/values-hi/strings.xml
index 8c94eb3..c963beb 100644
--- a/packages/Keyguard/res/values-hi/strings.xml
+++ b/packages/Keyguard/res/values-hi/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"कीगार्ड"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"पिन कोड लिखें"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"सिम PUK और नया PIN कोड लिखें"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"सिम PUK कोड"</string>
diff --git a/packages/Keyguard/res/values-hr/activitystrings.xml b/packages/Keyguard/res/values-hr/activitystrings.xml
deleted file mode 100644
index d2b8e92..0000000
--- a/packages/Keyguard/res/values-hr/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Nema zaštite"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Zaporka"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Uzorak"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN za SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK za SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Odaberite widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-hr/strings.xml b/packages/Keyguard/res/values-hr/strings.xml
index 3843549..6bbdd51 100644
--- a/packages/Keyguard/res/values-hr/strings.xml
+++ b/packages/Keyguard/res/values-hr/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Zaštita tipkovnice"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Unesite PIN kôd"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Unesite PUK i novi PIN kôd SIM kartice"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK kôd SIM kartice"</string>
diff --git a/packages/Keyguard/res/values-hu/activitystrings.xml b/packages/Keyguard/res/values-hu/activitystrings.xml
deleted file mode 100644
index 30d2951..0000000
--- a/packages/Keyguard/res/values-hu/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Nincs védelem"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN kód"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Jelszó"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Minta"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM kártya PIN kódja"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM kártya PUK kódja"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Modul kiválasztása..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-hu/strings.xml b/packages/Keyguard/res/values-hu/strings.xml
index bf6f528..9706874 100644
--- a/packages/Keyguard/res/values-hu/strings.xml
+++ b/packages/Keyguard/res/values-hu/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Billentyűzár"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Írja be a PIN kódot"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Írja be a SIM kártya PUK kódját, majd az új PIN kódot"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM kártya PUK kódja"</string>
diff --git a/packages/Keyguard/res/values-hy-rAM/strings.xml b/packages/Keyguard/res/values-hy-rAM/strings.xml
index ff87920..60c626d 100644
--- a/packages/Keyguard/res/values-hy-rAM/strings.xml
+++ b/packages/Keyguard/res/values-hy-rAM/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Մուտքագրեք PIN կոդը"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Մուտքագրեք SIM PUK-ը և նոր PIN կոդը"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK կոդը"</string>
diff --git a/packages/Keyguard/res/values-in/activitystrings.xml b/packages/Keyguard/res/values-in/activitystrings.xml
deleted file mode 100644
index ec9774d..0000000
--- a/packages/Keyguard/res/values-in/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Tanpa pengamanan"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Sandi"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Pola"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Pilih widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-in/strings.xml b/packages/Keyguard/res/values-in/strings.xml
index 9e19472..9ea5a29 100644
--- a/packages/Keyguard/res/values-in/strings.xml
+++ b/packages/Keyguard/res/values-in/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ketik kode PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Ketik kode PIN baru dan PUK SIM"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Kode PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-it/activitystrings.xml b/packages/Keyguard/res/values-it/activitystrings.xml
deleted file mode 100644
index 34ad96497..0000000
--- a/packages/Keyguard/res/values-it/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Nessuna sicurezza"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Password"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Sequenza"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN della SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK della SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Scegli widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-it/strings.xml b/packages/Keyguard/res/values-it/strings.xml
index 7212e5e..2a481e6 100644
--- a/packages/Keyguard/res/values-it/strings.xml
+++ b/packages/Keyguard/res/values-it/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Inserisci il codice PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Digita il PUK della SIM e il nuovo codice PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Codice PUK della SIM"</string>
diff --git a/packages/Keyguard/res/values-iw/activitystrings.xml b/packages/Keyguard/res/values-iw/activitystrings.xml
deleted file mode 100644
index 84e351a2..0000000
--- a/packages/Keyguard/res/values-iw/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"ללא אבטחה"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"סיסמה"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"קו ביטול נעילה"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN של SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK של SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"בחר Widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-iw/strings.xml b/packages/Keyguard/res/values-iw/strings.xml
index 12b45e4..a6a3192 100644
--- a/packages/Keyguard/res/values-iw/strings.xml
+++ b/packages/Keyguard/res/values-iw/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"מגן מקלדת"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"‏הקלד קוד PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"‏הקלד קוד PUK של כרטיס SIM וקוד PIN חדש"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"‏קוד PUK של כרטיס SIM"</string>
diff --git a/packages/Keyguard/res/values-ja/activitystrings.xml b/packages/Keyguard/res/values-ja/activitystrings.xml
deleted file mode 100644
index b0e77f1..0000000
--- a/packages/Keyguard/res/values-ja/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"セキュリティなし"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"パスワード"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"パターン"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"ウィジェットを選択..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ja/strings.xml b/packages/Keyguard/res/values-ja/strings.xml
index 5106271..b683a9d 100644
--- a/packages/Keyguard/res/values-ja/strings.xml
+++ b/packages/Keyguard/res/values-ja/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"キーガード"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PINコードを入力"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"PUKと新しいPINコードを入力"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUKコード"</string>
diff --git a/packages/Keyguard/res/values-ka-rGE/strings.xml b/packages/Keyguard/res/values-ka-rGE/strings.xml
index 3d7af75..4414096 100644
--- a/packages/Keyguard/res/values-ka-rGE/strings.xml
+++ b/packages/Keyguard/res/values-ka-rGE/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"აკრიფეთ PIN კოდი"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"დაბეჭდეთ SIM-ის PUK კოდი და ახალი PIN კოდი"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK კოდი"</string>
diff --git a/packages/Keyguard/res/values-km-rKH/strings.xml b/packages/Keyguard/res/values-km-rKH/strings.xml
index b09c749..a2e54a7 100644
--- a/packages/Keyguard/res/values-km-rKH/strings.xml
+++ b/packages/Keyguard/res/values-km-rKH/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"ការពារ​គ្រាប់ចុច"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"បញ្ចូល​កូដ PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"បញ្ចូល​លេខ​កូដ PUK  និង​​ PIN ថ្មី​របស់​ស៊ីម"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"លេខ​កូដ PUK ស៊ីម"</string>
diff --git a/packages/Keyguard/res/values-ko/activitystrings.xml b/packages/Keyguard/res/values-ko/activitystrings.xml
deleted file mode 100644
index 3aab225..0000000
--- a/packages/Keyguard/res/values-ko/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"보안 사용 안함"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"비밀번호"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"패턴"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"위젯 선택..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ko/strings.xml b/packages/Keyguard/res/values-ko/strings.xml
index 2a7200c..cde2b1c 100644
--- a/packages/Keyguard/res/values-ko/strings.xml
+++ b/packages/Keyguard/res/values-ko/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"키가드"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN 코드 입력"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"SIM PUK 및 새 PIN 코드 입력"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK 코드"</string>
diff --git a/packages/Keyguard/res/values-lo-rLA/strings.xml b/packages/Keyguard/res/values-lo-rLA/strings.xml
index 81c10181..0571768 100644
--- a/packages/Keyguard/res/values-lo-rLA/strings.xml
+++ b/packages/Keyguard/res/values-lo-rLA/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"ພິມລະຫັດ PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"ປະເພດ PUK ຂອງ SIM ແລະລະຫັດ PIN ໃໝ່"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"ລະຫັດ PUK ຂອງ SIM"</string>
diff --git a/packages/Keyguard/res/values-lt/activitystrings.xml b/packages/Keyguard/res/values-lt/activitystrings.xml
deleted file mode 100644
index 9ec21e4..0000000
--- a/packages/Keyguard/res/values-lt/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Neapsaugota"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN kodas"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Slaptažodis"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Šablonas"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM kortelės PIN kodas"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM kortelės PUK kodas"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Pasirinkite valdiklį..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-lt/strings.xml b/packages/Keyguard/res/values-lt/strings.xml
index ff3034a..0fd6605 100644
--- a/packages/Keyguard/res/values-lt/strings.xml
+++ b/packages/Keyguard/res/values-lt/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Klaviatūros apsauga"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Įveskite PIN kodą"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Įveskite SIM kortelės PUK kodą ir naują PIN kodą"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM kortelės PUK kodas"</string>
diff --git a/packages/Keyguard/res/values-lv/activitystrings.xml b/packages/Keyguard/res/values-lv/activitystrings.xml
deleted file mode 100644
index 96807de..0000000
--- a/packages/Keyguard/res/values-lv/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Drošība nav iespējota"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Parole"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Kombinācija"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Izvēlēties logrīku..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-lv/strings.xml b/packages/Keyguard/res/values-lv/strings.xml
index 539f91d..2bcde1d 100644
--- a/packages/Keyguard/res/values-lv/strings.xml
+++ b/packages/Keyguard/res/values-lv/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Taustiņslēgs"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ievadiet PIN kodu."</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Ievadiet SIM kartes PUK kodu un jaunu PIN kodu."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM kartes PUK kods"</string>
diff --git a/packages/Keyguard/res/values-mn-rMN/strings.xml b/packages/Keyguard/res/values-mn-rMN/strings.xml
index e1b833e..7bb819d 100644
--- a/packages/Keyguard/res/values-mn-rMN/strings.xml
+++ b/packages/Keyguard/res/values-mn-rMN/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN кодыг бичнэ үү"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"СИМ ПҮК-г бичээд шинэ ПИН код оруулна уу"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"СИМ ПҮК код"</string>
diff --git a/packages/Keyguard/res/values-ms-rMY/strings.xml b/packages/Keyguard/res/values-ms-rMY/strings.xml
index a6845bc..b4c1b46 100644
--- a/packages/Keyguard/res/values-ms-rMY/strings.xml
+++ b/packages/Keyguard/res/values-ms-rMY/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Pengawal kekunci"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Taip kod PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Taip PUK SIM dan kod PIN baharu"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Kod PUK SIM"</string>
diff --git a/packages/Keyguard/res/values-nb/activitystrings.xml b/packages/Keyguard/res/values-nb/activitystrings.xml
deleted file mode 100644
index 015df15..0000000
--- a/packages/Keyguard/res/values-nb/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Ingen sikkerhet"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Passord"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Mønster"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Personlig kode for SIM-kort"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-kode for SIM-kort"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Velg modul"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-nb/strings.xml b/packages/Keyguard/res/values-nb/strings.xml
index 71138a5..801e03d 100644
--- a/packages/Keyguard/res/values-nb/strings.xml
+++ b/packages/Keyguard/res/values-nb/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Tastaturlås"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Skriv inn PIN-kode"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Skriv inn PUK-koden for SIM-kortet og en ny PIN-kode"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-koden for SIM-kortet"</string>
diff --git a/packages/Keyguard/res/values-nl/activitystrings.xml b/packages/Keyguard/res/values-nl/activitystrings.xml
deleted file mode 100644
index fcb0be9..0000000
--- a/packages/Keyguard/res/values-nl/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Geen beveiliging"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"Pincode"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Wachtwoord"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Patroon"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Pincode van simkaart"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-code van simkaart"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Widget kiezen…"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-nl/strings.xml b/packages/Keyguard/res/values-nl/strings.xml
index 34149c9..195f950 100644
--- a/packages/Keyguard/res/values-nl/strings.xml
+++ b/packages/Keyguard/res/values-nl/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Toetsblokkering"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Pincode typen"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Typ de pukcode voor de simkaart en de nieuwe pincode"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Pukcode voor simkaart"</string>
diff --git a/packages/Keyguard/res/values-pl/activitystrings.xml b/packages/Keyguard/res/values-pl/activitystrings.xml
deleted file mode 100644
index f04170e..0000000
--- a/packages/Keyguard/res/values-pl/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Bez zabezpieczeń"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Hasło"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Wzór"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN do karty SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK do karty SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Wybierz widżet..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-pl/strings.xml b/packages/Keyguard/res/values-pl/strings.xml
index cfcbc46..165b2c4 100644
--- a/packages/Keyguard/res/values-pl/strings.xml
+++ b/packages/Keyguard/res/values-pl/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Blokada klawiszy"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Wpisz kod PIN."</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Wpisz PUK i nowy kod PIN karty SIM"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Kod PUK karty SIM"</string>
diff --git a/packages/Keyguard/res/values-pt-rPT/activitystrings.xml b/packages/Keyguard/res/values-pt-rPT/activitystrings.xml
deleted file mode 100644
index 470865d..0000000
--- a/packages/Keyguard/res/values-pt-rPT/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Sem segurança"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Palavra-passe"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Sequência"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN do SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK do SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Escolher widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-pt-rPT/strings.xml b/packages/Keyguard/res/values-pt-rPT/strings.xml
index abd4fcd..332a943 100644
--- a/packages/Keyguard/res/values-pt-rPT/strings.xml
+++ b/packages/Keyguard/res/values-pt-rPT/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Escreva o código PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Introduzir PUK do cartão SIM e o novo código PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Código PUK do cartão SIM"</string>
diff --git a/packages/Keyguard/res/values-pt/activitystrings.xml b/packages/Keyguard/res/values-pt/activitystrings.xml
deleted file mode 100644
index 7a63708..0000000
--- a/packages/Keyguard/res/values-pt/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Sem segurança"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Senha"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Padrão"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN do SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK do SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Escolher widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-pt/strings.xml b/packages/Keyguard/res/values-pt/strings.xml
index 24d78e5..a97b1b6 100644
--- a/packages/Keyguard/res/values-pt/strings.xml
+++ b/packages/Keyguard/res/values-pt/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Bloqueio do teclado"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Insira o código PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Digite o PUK do SIM e o novo código PIN."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Código PUK do SIM"</string>
diff --git a/packages/Keyguard/res/values-rm/strings.xml b/packages/Keyguard/res/values-rm/strings.xml
index ee26a3d..4d71f27 100644
--- a/packages/Keyguard/res/values-rm/strings.xml
+++ b/packages/Keyguard/res/values-rm/strings.xml
@@ -20,6 +20,8 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- no translation found for app_name (719438068451601849) -->
+    <skip />
     <!-- no translation found for keyguard_password_enter_pin_code (3037685796058495017) -->
     <skip />
     <!-- no translation found for keyguard_password_enter_puk_code (3035856550289724338) -->
diff --git a/packages/Keyguard/res/values-ro/activitystrings.xml b/packages/Keyguard/res/values-ro/activitystrings.xml
deleted file mode 100644
index 6d3447d..0000000
--- a/packages/Keyguard/res/values-ro/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Fără securitate"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Parolă"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Model"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Alegeți un widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ro/strings.xml b/packages/Keyguard/res/values-ro/strings.xml
index 1c7e88f..58bc337 100644
--- a/packages/Keyguard/res/values-ro/strings.xml
+++ b/packages/Keyguard/res/values-ro/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Blocarea tastaturii"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Introduceţi codul PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Introduceți codul PUK pentru cardul SIM și codul PIN nou"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Codul PUK pentru cardul SIM"</string>
diff --git a/packages/Keyguard/res/values-ru/activitystrings.xml b/packages/Keyguard/res/values-ru/activitystrings.xml
deleted file mode 100644
index 002cd56..0000000
--- a/packages/Keyguard/res/values-ru/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Защита отключена"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN-код"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Пароль"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Графический ключ"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN-код SIM-карты"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-код SIM-карты"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Выбор виджета..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-ru/strings.xml b/packages/Keyguard/res/values-ru/strings.xml
index 304f474..866abc0 100644
--- a/packages/Keyguard/res/values-ru/strings.xml
+++ b/packages/Keyguard/res/values-ru/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Введите PIN-код"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Введите PUK-код и новый PIN-код"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-код"</string>
diff --git a/packages/Keyguard/res/values-sk/activitystrings.xml b/packages/Keyguard/res/values-sk/activitystrings.xml
deleted file mode 100644
index 33f2228..0000000
--- a/packages/Keyguard/res/values-sk/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Bez zabezpečenia"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"Kód PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Heslo"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Vzor"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN karty SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK karty SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Vyberte miniaplikáciu..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-sk/strings.xml b/packages/Keyguard/res/values-sk/strings.xml
index 89ac293..45e4288 100644
--- a/packages/Keyguard/res/values-sk/strings.xml
+++ b/packages/Keyguard/res/values-sk/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Zámka klávesnice"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Zadajte kód PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Zadajte kód PUK karty SIM a nový kód PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Kód PUK karty SIM"</string>
diff --git a/packages/Keyguard/res/values-sl/activitystrings.xml b/packages/Keyguard/res/values-sl/activitystrings.xml
deleted file mode 100644
index 2c60219..0000000
--- a/packages/Keyguard/res/values-sl/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Brez varnosti"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Geslo"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Vzorec"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN za kartico SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK za kartico SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Izberite pripomoček ..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-sl/strings.xml b/packages/Keyguard/res/values-sl/strings.xml
index b0ec84e..cf72e47 100644
--- a/packages/Keyguard/res/values-sl/strings.xml
+++ b/packages/Keyguard/res/values-sl/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Vnesite kodo PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Vnesite kodo PUK in novo kodo PIN kartice SIM"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Koda PUK kartice SIM"</string>
diff --git a/packages/Keyguard/res/values-sr/activitystrings.xml b/packages/Keyguard/res/values-sr/activitystrings.xml
deleted file mode 100644
index 34802df..0000000
--- a/packages/Keyguard/res/values-sr/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Без заштите"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Лозинка"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Шаблон"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN SIM картице"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK SIM картице"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Изабери виџет..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-sr/strings.xml b/packages/Keyguard/res/values-sr/strings.xml
index 2bdd8f5..bd08eae 100644
--- a/packages/Keyguard/res/values-sr/strings.xml
+++ b/packages/Keyguard/res/values-sr/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Заштита тастера"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Унесите PIN кôд"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Унесите SIM PUK кôд и нови PIN кôд"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK кôд"</string>
@@ -118,7 +119,7 @@
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="7003469261464593516">"PIN кодови се не подударају"</string>
     <string name="kg_login_too_many_attempts" msgid="6486842094005698475">"Превише покушаја уноса шаблона"</string>
     <string name="kg_login_instructions" msgid="1100551261265506448">"Да бисте откључали, пријавите се помоћу Google налога."</string>
-    <string name="kg_login_username_hint" msgid="5718534272070920364">"Корисничко име (адреса е-поште)"</string>
+    <string name="kg_login_username_hint" msgid="5718534272070920364">"Корисничко име (имејл адреса)"</string>
     <string name="kg_login_password_hint" msgid="9057289103827298549">"Лозинка"</string>
     <string name="kg_login_submit_button" msgid="5355904582674054702">"Пријави ме"</string>
     <string name="kg_login_invalid_input" msgid="5754664119319872197">"Неважеће корисничко име или лозинка."</string>
diff --git a/packages/Keyguard/res/values-sv/activitystrings.xml b/packages/Keyguard/res/values-sv/activitystrings.xml
deleted file mode 100644
index e664383..0000000
--- a/packages/Keyguard/res/values-sv/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Ingen säkerhet"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN-kod"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Lösenord"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Grafiskt lösenord"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN-kod för SIM-kort"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-kod för SIM-kort"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Välj widget ..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-sv/strings.xml b/packages/Keyguard/res/values-sv/strings.xml
index e446f61..1214100 100644
--- a/packages/Keyguard/res/values-sv/strings.xml
+++ b/packages/Keyguard/res/values-sv/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ange PIN-kod"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Ange PUK-koden och en ny pinkod för SIM-kortet"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-kod för SIM-kortet"</string>
diff --git a/packages/Keyguard/res/values-sw/activitystrings.xml b/packages/Keyguard/res/values-sw/activitystrings.xml
deleted file mode 100644
index 357b911..0000000
--- a/packages/Keyguard/res/values-sw/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Hakuna usalama"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Nenosiri"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Ruwaza"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN ya SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK ya SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Chagua wijeti..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-sw/strings.xml b/packages/Keyguard/res/values-sw/strings.xml
index 1d60a13..fc1ce17 100644
--- a/packages/Keyguard/res/values-sw/strings.xml
+++ b/packages/Keyguard/res/values-sw/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Kilinda vitufe"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Ingiza msimbo wa PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Chapa PUK ya SIM na msimbo mpya wa PIN"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Msimbo wa PUK ya SIM"</string>
diff --git a/packages/Keyguard/res/values-sw600dp/dimens.xml b/packages/Keyguard/res/values-sw600dp/dimens.xml
index ea5ef27..25e86e1 100644
--- a/packages/Keyguard/res/values-sw600dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw600dp/dimens.xml
@@ -32,7 +32,7 @@
 
     <!-- Keyguard dimensions -->
     <!-- Size of the clock font in keyguard's status view -->
-    <dimen name="kg_status_clock_font_size">141dp</dimen>
+    <dimen name="kg_status_clock_font_size">120dp</dimen>
 
     <!-- Size of the generic status lines keyguard's status view  -->
     <dimen name="kg_status_line_font_size">16sp</dimen>
diff --git a/core/res/res/drawable/notification_quantum_press.xml b/packages/Keyguard/res/values-sw600dp/styles.xml
similarity index 76%
copy from core/res/res/drawable/notification_quantum_press.xml
copy to packages/Keyguard/res/values-sw600dp/styles.xml
index 4999f55..e632e76 100644
--- a/core/res/res/drawable/notification_quantum_press.xml
+++ b/packages/Keyguard/res/values-sw600dp/styles.xml
@@ -1,4 +1,3 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!--
   ~ Copyright (C) 2014 The Android Open Source Project
   ~
@@ -15,7 +14,8 @@
   ~ limitations under the License
   -->
 
-<shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="#ffcccccc" />
-    <corners android:radius="2dp" />
-</shape>
\ No newline at end of file
+<resources>
+    <style name="BouncerSecurityContainer">
+        <item name="android:layout_gravity">center</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/packages/Keyguard/res/values-sw720dp/dimens.xml b/packages/Keyguard/res/values-sw720dp/dimens.xml
index 4853a7b..30b979c 100644
--- a/packages/Keyguard/res/values-sw720dp/dimens.xml
+++ b/packages/Keyguard/res/values-sw720dp/dimens.xml
@@ -19,7 +19,7 @@
 <resources>
     <!-- Keyguard dimensions -->
     <!-- Size of the clock font in keyguard's status view -->
-    <dimen name="kg_status_clock_font_size">188dp</dimen>
+    <dimen name="kg_status_clock_font_size">140dp</dimen>
 
     <!-- Size of the generic status lines keyguard's status view  -->
     <dimen name="kg_status_line_font_size">19sp</dimen>
diff --git a/packages/Keyguard/res/values-th/activitystrings.xml b/packages/Keyguard/res/values-th/activitystrings.xml
deleted file mode 100644
index 64f50cc..0000000
--- a/packages/Keyguard/res/values-th/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"ไม่มีการรักษาความปลอดภัย"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"รหัสผ่าน"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"รูปแบบ"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN ของซิม"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK ของซิม"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"เลือกวิดเจ็ต..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-th/strings.xml b/packages/Keyguard/res/values-th/strings.xml
index a44f9fe..34d97c2 100644
--- a/packages/Keyguard/res/values-th/strings.xml
+++ b/packages/Keyguard/res/values-th/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"การล็อกปุ่มกด"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"พิมพ์รหัส PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"พิมพ์ PUK และรหัส PIN ใหม่"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"รหัส PUK ของซิม"</string>
diff --git a/packages/Keyguard/res/values-tl/activitystrings.xml b/packages/Keyguard/res/values-tl/activitystrings.xml
deleted file mode 100644
index 71f3564..0000000
--- a/packages/Keyguard/res/values-tl/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Walang seguridad"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Password"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Pattern"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Pumili ng widget..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenNaka-off"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenNaka-on"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-tl/strings.xml b/packages/Keyguard/res/values-tl/strings.xml
index 6516766..9d97d22 100644
--- a/packages/Keyguard/res/values-tl/strings.xml
+++ b/packages/Keyguard/res/values-tl/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"I-type ang PIN code"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"I-type ang SIM PUK at bagong PIN code"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK code ng SIM"</string>
diff --git a/packages/Keyguard/res/values-tr/activitystrings.xml b/packages/Keyguard/res/values-tr/activitystrings.xml
deleted file mode 100644
index 7f5a958..0000000
--- a/packages/Keyguard/res/values-tr/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Güvenlik yok"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Şifre"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Desen"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN\'i"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK\'u"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Widget seç..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-tr/strings.xml b/packages/Keyguard/res/values-tr/strings.xml
index aed8a47..1d8b982 100644
--- a/packages/Keyguard/res/values-tr/strings.xml
+++ b/packages/Keyguard/res/values-tr/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"PIN kodunu yazın"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"SIM PUK kodunu ve yeni bir PIN kodu yazın."</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK kodu"</string>
diff --git a/packages/Keyguard/res/values-uk/activitystrings.xml b/packages/Keyguard/res/values-uk/activitystrings.xml
deleted file mode 100644
index d4d0a4d..0000000
--- a/packages/Keyguard/res/values-uk/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Без захисту"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN-код"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Пароль"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Ключ"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"PIN-код SIM-карти"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"PUK-код SIM-карти"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Вибрати віджет…"</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-uk/strings.xml b/packages/Keyguard/res/values-uk/strings.xml
index 5e355e4..16cf6cf 100644
--- a/packages/Keyguard/res/values-uk/strings.xml
+++ b/packages/Keyguard/res/values-uk/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Введіть PIN-код"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Введіть PUK-код і новий PIN-код SIM-карти"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"PUK-код SIM-карти"</string>
diff --git a/packages/Keyguard/res/values-vi/activitystrings.xml b/packages/Keyguard/res/values-vi/activitystrings.xml
deleted file mode 100644
index 009c3bd..0000000
--- a/packages/Keyguard/res/values-vi/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Không có bảo mật"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"Mã PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Mật khẩu"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Hình"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"Mã PIN của SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"Mã PUK của SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Chọn tiện ích..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-vi/strings.xml b/packages/Keyguard/res/values-vi/strings.xml
index c775467..00693aa5 100644
--- a/packages/Keyguard/res/values-vi/strings.xml
+++ b/packages/Keyguard/res/values-vi/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Khóa bàn phím"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Nhập mã PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Nhập mã PIN mới và mã PUK của SIM"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Mã PUK của SIM"</string>
diff --git a/packages/Keyguard/res/values-zh-rCN/activitystrings.xml b/packages/Keyguard/res/values-zh-rCN/activitystrings.xml
deleted file mode 100644
index d9b99e0..0000000
--- a/packages/Keyguard/res/values-zh-rCN/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"无安全措施"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"密码"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"图案"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM 卡 PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM 卡 PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"选择小部件..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-zh-rCN/strings.xml b/packages/Keyguard/res/values-zh-rCN/strings.xml
index 18578e4..1c014c3 100644
--- a/packages/Keyguard/res/values-zh-rCN/strings.xml
+++ b/packages/Keyguard/res/values-zh-rCN/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Keyguard"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"输入 PIN 码"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"请输入 SIM 卡 PUK 码和新的 PIN 码"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM 卡 PUK 码"</string>
diff --git a/packages/Keyguard/res/values-zh-rHK/strings.xml b/packages/Keyguard/res/values-zh-rHK/strings.xml
index 010ad2f..1b621d6 100644
--- a/packages/Keyguard/res/values-zh-rHK/strings.xml
+++ b/packages/Keyguard/res/values-zh-rHK/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"鍵盤鎖"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"輸入 PIN 碼"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"請輸入 SIM PUK 碼和新 PIN 碼"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM PUK 碼"</string>
diff --git a/packages/Keyguard/res/values-zh-rTW/activitystrings.xml b/packages/Keyguard/res/values-zh-rTW/activitystrings.xml
deleted file mode 100644
index 42c2a51..0000000
--- a/packages/Keyguard/res/values-zh-rTW/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"Keyguard 測試活動"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"整合式相機"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"無安全性設定"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"密碼"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"圖形"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"SIM PIN"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"SIM PUK"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"選擇小工具..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"在螢幕上關閉"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"在螢幕上開啟"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"執行 Keyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"驗證解鎖"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-zh-rTW/strings.xml b/packages/Keyguard/res/values-zh-rTW/strings.xml
index d81cc16..6e632ef 100644
--- a/packages/Keyguard/res/values-zh-rTW/strings.xml
+++ b/packages/Keyguard/res/values-zh-rTW/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"鍵盤鎖"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"輸入 PIN 碼"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"輸入 SIM 卡 PUK 碼和新 PIN 碼"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"SIM 卡 PUK 碼"</string>
diff --git a/packages/Keyguard/res/values-zu/activitystrings.xml b/packages/Keyguard/res/values-zu/activitystrings.xml
deleted file mode 100644
index 0031a8b..0000000
--- a/packages/Keyguard/res/values-zu/activitystrings.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- 
-/* //device/apps/common/assets/res/any/strings.xml
-**
-** Copyright 2006, 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.
-*/
- -->
-
-<resources xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
-    <string name="app_name" msgid="3352888186674981593">"I-KeyguardTestActivity"</string>
-    <string name="secure_app_name" msgid="7955498742816868049">"I-UnifiedCamera"</string>
-    <string name="none_menu_item" msgid="6156747285687551424">"Akukho ukuphepha"</string>
-    <string name="pin_menu_item" msgid="1179756433268962311">"I-PIN"</string>
-    <string name="password_menu_item" msgid="1959980499662153160">"Iphasiwedi"</string>
-    <string name="pattern_menu_item" msgid="2987798152175140249">"Iphethini"</string>
-    <string name="sim_pin_menu_item" msgid="3962286639645084880">"I-PIN ye-SIM"</string>
-    <string name="sim_puk_menu_item" msgid="6190044133008392974">"I-PUK YE-SIM"</string>
-    <string name="add_widget_item" msgid="279702152366857415">"Khetha iwijethi..."</string>
-    <string name="on_screen_turned_off" msgid="8761396329770508367">"I-onScreenTurnedOff"</string>
-    <string name="on_screen_turned_on" msgid="9222926818030728999">"I-onScreenTurnedOn"</string>
-    <string name="do_keyguard" msgid="9210936977823118796">"I-doKeyguard"</string>
-    <string name="verify_unlock" msgid="8508722273329306968">"I-verifyUnlock"</string>
-</resources>
diff --git a/packages/Keyguard/res/values-zu/strings.xml b/packages/Keyguard/res/values-zu/strings.xml
index b205634..95d3474 100644
--- a/packages/Keyguard/res/values-zu/strings.xml
+++ b/packages/Keyguard/res/values-zu/strings.xml
@@ -20,6 +20,7 @@
 
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string name="app_name" msgid="719438068451601849">"Ukhiye wokugada"</string>
     <string name="keyguard_password_enter_pin_code" msgid="3037685796058495017">"Faka ikhodi ye-PIN"</string>
     <string name="keyguard_password_enter_puk_code" msgid="3035856550289724338">"Thayipha i-PUK ye-SIM nekhodi yephinikhodi entsha"</string>
     <string name="keyguard_password_enter_puk_prompt" msgid="1801941051094974609">"Ikhodi ye-PUK ye-SIM"</string>
diff --git a/packages/Keyguard/res/values/attrs.xml b/packages/Keyguard/res/values/attrs.xml
index e045dd2..2410b6a 100644
--- a/packages/Keyguard/res/values/attrs.xml
+++ b/packages/Keyguard/res/values/attrs.xml
@@ -133,4 +133,8 @@
         <attr name="digit" format="integer" />
         <attr name="textView" format="reference" />
     </declare-styleable>
+
+    <declare-styleable name="CarrierText">
+        <attr name="allCaps" format="boolean" />
+    </declare-styleable>
 </resources>
diff --git a/packages/Keyguard/res/values/dimens.xml b/packages/Keyguard/res/values/dimens.xml
index 71e9924..c05f834 100644
--- a/packages/Keyguard/res/values/dimens.xml
+++ b/packages/Keyguard/res/values/dimens.xml
@@ -158,7 +158,7 @@
     <dimen name="bottom_text_spacing_digital">-8dp</dimen>
     <dimen name="label_font_size">14dp</dimen>
     <dimen name="widget_label_font_size">14dp</dimen>
-    <dimen name="widget_big_font_size">80dp</dimen>
+    <dimen name="widget_big_font_size">60dp</dimen>
     <dimen name="big_font_size">120dp</dimen>
 
 </resources>
diff --git a/packages/Keyguard/res/values/strings.xml b/packages/Keyguard/res/values/strings.xml
index 4738049..d20b269 100644
--- a/packages/Keyguard/res/values/strings.xml
+++ b/packages/Keyguard/res/values/strings.xml
@@ -18,6 +18,8 @@
 */
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <!-- App label in the manifest  -->
+    <string name="app_name">Keyguard</string>
     <!-- Instructions telling the user to enter their SIM PIN to unlock the keyguard.
          Displayed in one line in a large font.  -->
     <string name="keyguard_password_enter_pin_code">Type PIN code</string>
diff --git a/packages/Keyguard/res/values/styles.xml b/packages/Keyguard/res/values/styles.xml
index 80fcf75..b54ac50 100644
--- a/packages/Keyguard/res/values/styles.xml
+++ b/packages/Keyguard/res/values/styles.xml
@@ -56,8 +56,7 @@
     <!-- Built-in clock widget stuff -->
     <style name="widget_label">
         <item name="android:textStyle">bold</item>
-        <item name="android:textAllCaps">true</item>
-        <item name="android:fontFamily">sans-serif-condensed</item>
+        <item name="android:fontFamily">sans-serif-light</item>
         <item name="android:textSize">@dimen/widget_label_font_size</item>
     </style>
     <style name="big_thin">
@@ -82,4 +81,9 @@
         <item name="android:mirrorForRtl">true</item>
     </style>
 
+    <style name="BouncerSecurityContainer">
+        <item name="android:layout_marginBottom">32dp</item>
+        <item name="android:layout_gravity">center_horizontal|bottom</item>
+    </style>
+
 </resources>
diff --git a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
index 74e6f33..2bf74ea 100644
--- a/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
+++ b/packages/Keyguard/src/com/android/keyguard/CameraWidgetFrame.java
@@ -38,7 +38,7 @@
 
 public class CameraWidgetFrame extends KeyguardWidgetFrame implements View.OnClickListener {
     private static final String TAG = CameraWidgetFrame.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final int WIDGET_ANIMATION_DURATION = 250; // ms
     private static final int WIDGET_WAIT_DURATION = 400; // ms
     private static final int RECOVERY_DELAY = 1000; // ms
@@ -113,12 +113,14 @@
 
     private final KeyguardUpdateMonitorCallback mCallback = new KeyguardUpdateMonitorCallback() {
         private boolean mShowing;
-        void onKeyguardVisibilityChanged(boolean showing) {
+
+        @Override
+        public void onKeyguardVisibilityChanged(boolean showing) {
             if (mShowing == showing)
                 return;
             mShowing = showing;
             CameraWidgetFrame.this.onKeyguardVisibilityChanged(mShowing);
-        };
+        }
     };
 
     private static final class FixedSizeFrameLayout extends FrameLayout {
diff --git a/packages/Keyguard/src/com/android/keyguard/CarrierText.java b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
index 88558cd..05f2962 100644
--- a/packages/Keyguard/src/com/android/keyguard/CarrierText.java
+++ b/packages/Keyguard/src/com/android/keyguard/CarrierText.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.text.method.SingleLineTransformationMethod;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -81,7 +82,14 @@
     public CarrierText(Context context, AttributeSet attrs) {
         super(context, attrs);
         mLockPatternUtils = new LockPatternUtils(mContext);
-        boolean useAllCaps = mContext.getResources().getBoolean(R.bool.kg_use_all_caps);
+        boolean useAllCaps;
+        TypedArray a = context.getTheme().obtainStyledAttributes(
+                attrs, R.styleable.CarrierText, 0, 0);
+        try {
+            useAllCaps = a.getBoolean(R.styleable.CarrierText_allCaps, false);
+        } finally {
+            a.recycle();
+        }
         setTransformationMethod(new CarrierTextTransformationMethod(mContext, useAllCaps));
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
index fd56613..4ed37d4 100644
--- a/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
+++ b/packages/Keyguard/src/com/android/keyguard/EmergencyButton.java
@@ -48,10 +48,11 @@
             updateEmergencyCallButton(simState, phoneState);
         }
 
-        void onPhoneStateChanged(int phoneState) {
+        @Override
+        public void onPhoneStateChanged(int phoneState) {
             State simState = KeyguardUpdateMonitor.getInstance(mContext).getSimState();
             updateEmergencyCallButton(simState, phoneState);
-        };
+        }
     };
     private LockPatternUtils mLockPatternUtils;
     private PowerManager mPowerManager;
diff --git a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
index de839c6..2f14003 100644
--- a/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
+++ b/packages/Keyguard/src/com/android/keyguard/FaceUnlock.java
@@ -37,8 +37,9 @@
 
 public class FaceUnlock implements BiometricSensorUnlock, Handler.Callback {
 
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "FULLockscreen";
+    private static final String FACE_LOCK_PACKAGE = "com.android.facelock";
 
     private final Context mContext;
     private final LockPatternUtils mLockPatternUtils;
@@ -128,7 +129,8 @@
         if (!mBoundToService) {
             Log.d(TAG, "Binding to Face Unlock service for user="
                     + mLockPatternUtils.getCurrentUser());
-            mContext.bindServiceAsUser(new Intent(IFaceLockInterface.class.getName()),
+            mContext.bindServiceAsUser(
+                    new Intent(IFaceLockInterface.class.getName()).setPackage(FACE_LOCK_PACKAGE),
                     mConnection,
                     Context.BIND_AUTO_CREATE,
                     new UserHandle(mLockPatternUtils.getCurrentUser()));
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
index 3950159..4b386b6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardAbsKeyInputView.java
@@ -231,7 +231,7 @@
     @Override
     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
         if (mCallback != null) {
-            mCallback.userActivity(KeyguardViewManager.DIGIT_PRESS_WAKE_MILLIS);
+            mCallback.userActivity(KeyguardConstants.DIGIT_PRESS_WAKE_MILLIS);
         }
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
index 0d5e477..25f3383 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardActivityLauncher.java
@@ -43,7 +43,7 @@
 
 public abstract class KeyguardActivityLauncher {
     private static final String TAG = KeyguardActivityLauncher.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String META_DATA_KEYGUARD_LAYOUT = "com.android.keyguard.layout";
     private static final Intent SECURE_CAMERA_INTENT =
             new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE)
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
new file mode 100644
index 0000000..bfa95f38
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardConstants.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+/**
+ * Defines constants for the Keyguard.
+ */
+public class KeyguardConstants {
+
+    /**
+     * Turns on debugging information for the whole Keyguard. This is very verbose and should only
+     * be used temporarily for debugging.
+     */
+    public static final boolean DEBUG = false;
+
+    /** Timeout used for key presses. */
+    public static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
index 6bcbd6c..55f965c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardDisplayManager.java
@@ -30,18 +30,18 @@
 
 public class KeyguardDisplayManager {
     protected static final String TAG = "KeyguardDisplayManager";
-    private static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static boolean DEBUG = KeyguardConstants.DEBUG;
     Presentation mPresentation;
     private MediaRouter mMediaRouter;
     private Context mContext;
     private boolean mShowing;
 
-    KeyguardDisplayManager(Context context) {
+    public KeyguardDisplayManager(Context context) {
         mContext = context;
         mMediaRouter = (MediaRouter) mContext.getSystemService(Context.MEDIA_ROUTER_SERVICE);
     }
 
-    void show() {
+    public void show() {
         if (!mShowing) {
             if (DEBUG) Slog.v(TAG, "show");
             mMediaRouter.addCallback(MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY,
@@ -51,7 +51,7 @@
         mShowing = true;
     }
 
-    void hide() {
+    public void hide() {
         if (mShowing) {
             if (DEBUG) Slog.v(TAG, "hide");
             mMediaRouter.removeCallback(mMediaRouterCallback);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
index c2cd32f..900d16e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardFaceUnlockView.java
@@ -36,7 +36,7 @@
 public class KeyguardFaceUnlockView extends LinearLayout implements KeyguardSecurityView {
 
     private static final String TAG = "FULKeyguardFaceUnlockView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private KeyguardSecurityCallback mKeyguardSecurityCallback;
     private LockPatternUtils mLockPatternUtils;
     private BiometricSensorUnlock mBiometricUnlock;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 2e76f19..f85e29f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -22,10 +22,8 @@
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
 
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetHostView;
@@ -36,7 +34,6 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.media.RemoteControlClient;
@@ -44,7 +41,6 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -55,13 +51,11 @@
 import android.view.View;
 import android.widget.RemoteViews.OnClickHandler;
 
-import java.io.File;
 import java.lang.ref.WeakReference;
-import java.util.List;
 
 public class KeyguardHostView extends KeyguardViewBase {
     private static final String TAG = "KeyguardHostView";
-    public static boolean DEBUG = KeyguardViewMediator.DEBUG;
+    public static boolean DEBUG = KeyguardConstants.DEBUG;
     public static boolean DEBUGXPORT = true; // debug music transport control
 
     // Transport control states.
@@ -118,7 +112,7 @@
         void userActivity();
     }
 
-    /*package*/ interface OnDismissAction {
+    public interface OnDismissAction {
         /* returns true if the dismiss should be deferred */
         boolean onDismiss();
     }
@@ -241,7 +235,7 @@
             }
         }
         @Override
-        void onMusicClientIdChanged(
+        public void onMusicClientIdChanged(
                 int clientGeneration, boolean clearing, android.app.PendingIntent intent) {
             // Set transport state to invisible until we know music is playing (below)
             if (DEBUGXPORT && (mClientGeneration != clientGeneration || clearing)) {
@@ -449,7 +443,7 @@
     }
 
     @Override
-    protected void setLockPatternUtils(LockPatternUtils utils) {
+    public void setLockPatternUtils(LockPatternUtils utils) {
         super.setLockPatternUtils(utils);
         getSecurityContainer().updateSecurityViews(mViewStateManager.isBouncing());
     }
@@ -595,16 +589,16 @@
     };
 
     @Override
-    public void onScreenTurnedOn() {
-        super.onScreenTurnedOn();
+    public void onResume() {
+        super.onResume();
         if (mViewStateManager != null) {
             mViewStateManager.showUsabilityHints();
         }
     }
 
     @Override
-    public void onScreenTurnedOff() {
-        super.onScreenTurnedOff();
+    public void onPause() {
+        super.onPause();
         // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
         // turns off we reset that behavior
         clearAppWidgetToShow();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
index 2e4dbdf..ede23ef 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMessageArea.java
@@ -27,11 +27,10 @@
 import android.os.SystemClock;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.MutableInt;
 import android.view.View;
 import android.widget.TextView;
 
-import libcore.util.MutableInt;
-
 import java.lang.ref.WeakReference;
 
 import com.android.internal.widget.LockPatternUtils;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
index aa2ae0e..3aec55c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardMultiUserAvatar.java
@@ -37,7 +37,7 @@
 
 class KeyguardMultiUserAvatar extends FrameLayout {
     private static final String TAG = KeyguardMultiUserAvatar.class.getSimpleName();
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     private ImageView mUserImage;
     private TextView mUserName;
@@ -123,7 +123,7 @@
         mUserName = (TextView) findViewById(R.id.keyguard_user_name);
 
         mFramed = (KeyguardCircleFramedDrawable)
-                KeyguardViewMediator.getAvatarCache().get(user.id);
+                MultiUserAvatarCache.getInstance().get(user.id);
 
         // If we can't find it or the params don't match, create the drawable again
         if (mFramed == null
@@ -143,7 +143,7 @@
 
             mFramed = new KeyguardCircleFramedDrawable(icon, (int) mIconSize, mFrameColor, mStroke,
                     mFrameShadowColor, mShadowRadius, mHighlightColor);
-            KeyguardViewMediator.getAvatarCache().put(user.id, mFramed);
+            MultiUserAvatarCache.getInstance().put(user.id, mFramed);
         }
 
         mFramed.reset();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
index 14de6dd..b4308c6 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardPatternView.java
@@ -44,7 +44,7 @@
 public class KeyguardPatternView extends LinearLayout implements KeyguardSecurityView {
 
     private static final String TAG = "SecurityPatternView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     // how long before we clear the wrong pattern
     private static final int PATTERN_CLEAR_TIMEOUT_MS = 2000;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
index 0f62100..8425c48 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityContainer.java
@@ -30,7 +30,7 @@
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 
 public class KeyguardSecurityContainer extends FrameLayout implements KeyguardSecurityView {
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardSecurityView";
     private KeyguardSecurityModel mSecurityModel;
     private boolean mEnableFallback; // TODO: This should get the value from KeyguardPatternView
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index da6482a..2d492db 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -28,7 +28,7 @@
      * The different types of security available for {@link Mode#UnlockScreen}.
      * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
      */
-    enum SecurityMode {
+    public enum SecurityMode {
         Invalid, // NULL state
         None, // No security enabled
         Pattern, // Unlock by drawing a pattern.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
index 70a0e44..07239d1 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityViewFlipper.java
@@ -38,7 +38,7 @@
  */
 public class KeyguardSecurityViewFlipper extends ViewFlipper implements KeyguardSecurityView {
     private static final String TAG = "KeyguardSecurityViewFlipper";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     private Rect mTempRect = new Rect();
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
index 97aec68..03e7b07 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSelectorView.java
@@ -36,7 +36,6 @@
 import com.android.internal.widget.multiwaveview.GlowPadView.OnTriggerListener;
 
 public class KeyguardSelectorView extends LinearLayout implements KeyguardSecurityView {
-    private static final boolean DEBUG = KeyguardHostView.DEBUG;
     private static final String TAG = "SecuritySelectorView";
     private static final String ASSIST_ICON_METADATA_NAME =
         "com.android.systemui.action_assist_icon";
@@ -57,12 +56,10 @@
         public void onTrigger(View v, int target) {
             final int resId = mGlowPadView.getResourceIdForTarget(target);
 
-            switch (resId) {
-                case R.drawable.ic_lockscreen_unlock_phantom:
-                case R.drawable.ic_lockscreen_unlock:
-                    mCallback.userActivity(0);
-                    mCallback.dismiss(false);
-                break;
+            if (resId == R.drawable.ic_lockscreen_unlock_phantom
+                    || resId == R.drawable.ic_lockscreen_unlock) {
+                mCallback.userActivity(0);
+                mCallback.dismiss(false);
             }
         }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
index ae7ac97..4791956 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPinView.java
@@ -41,7 +41,7 @@
 public class KeyguardSimPinView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
     private static final String LOG_TAG = "KeyguardSimPinView";
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     public static final String TAG = "KeyguardSimPinView";
 
     private ProgressDialog mSimUnlockProgressDialog = null;
@@ -87,7 +87,7 @@
 
     @Override
     protected int getPasswordTextViewId() {
-        return R.id.pinEntry;
+        return R.id.simPinEntry;
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
index ca4f811..b9c7f51 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimPukView.java
@@ -42,7 +42,7 @@
 public class KeyguardSimPukView extends KeyguardAbsKeyInputView
         implements KeyguardSecurityView, OnEditorActionListener, TextWatcher {
     private static final String LOG_TAG = "KeyguardSimPukView";
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     public static final String TAG = "KeyguardSimPukView";
 
     private ProgressDialog mSimUnlockProgressDialog = null;
@@ -138,7 +138,7 @@
 
     @Override
     protected int getPasswordTextViewId() {
-        return R.id.pinEntry;
+        return R.id.pukEntry;
     }
 
     @Override
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
index cf983cb..5d5168c 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSimpleHostView.java
@@ -38,11 +38,6 @@
     }
 
     @Override
-    public void verifyUnlock() {
-        // TODO Auto-generated method stub
-    }
-
-    @Override
     public void cleanUp() {
         // TODO Auto-generated method stub
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
index 0bfee38..ae55c4a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardStatusView.java
@@ -33,7 +33,7 @@
 import java.util.Locale;
 
 public class KeyguardStatusView extends GridLayout {
-    private static final boolean DEBUG = KeyguardViewMediator.DEBUG;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardStatusView";
 
     private LockPatternUtils mLockPatternUtils;
@@ -50,22 +50,22 @@
         }
 
         @Override
-        void onKeyguardVisibilityChanged(boolean showing) {
+        public void onKeyguardVisibilityChanged(boolean showing) {
             if (showing) {
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                 refresh();
             }
-        };
+        }
 
         @Override
         public void onScreenTurnedOn() {
             setEnableMarquee(true);
-        };
+        }
 
         @Override
         public void onScreenTurnedOff(int why) {
             setEnableMarquee(false);
-        };
+        }
     };
 
     public KeyguardStatusView(Context context) {
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
index a7cd909..0d472ae 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardTransportControlView.java
@@ -60,7 +60,7 @@
 public class KeyguardTransportControlView extends FrameLayout {
 
     private static final int RESET_TO_METADATA_DELAY = 5000;
-    protected static final boolean DEBUG = false;
+    protected static final boolean DEBUG = KeyguardConstants.DEBUG;
     protected static final String TAG = "TransportControlView";
 
     private static final boolean ANIMATE_TRANSITIONS = true;
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
index 88c78ab..ba67a82 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -72,7 +72,7 @@
 public class KeyguardUpdateMonitor implements TrustManager.TrustListener {
 
     private static final String TAG = "KeyguardUpdateMonitor";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final boolean DEBUG_SIM_STATES = DEBUG || false;
     private static final int FAILED_BIOMETRIC_UNLOCK_ATTEMPTS_BEFORE_BACKUP = 3;
     private static final int LOW_BATTERY_THRESHOLD = 20;
@@ -215,8 +215,29 @@
         mUserHasTrust.put(userId, enabled);
     }
 
+    private boolean isTrustDisabled(int userId) {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) mContext.getSystemService(Context.DEVICE_POLICY_SERVICE);
+        if (dpm != null) {
+                // TODO once UI is finalized
+                final boolean disabledByGlobalActions = false;
+                final boolean disabledBySettings = false;
+
+                // Don't allow trust agent if device is secured with a SIM PIN. This is here
+                // mainly because there's no other way to prompt the user to enter their SIM PIN
+                // once they get past the keyguard screen.
+                final boolean disabledBySimPin = isSimPinSecure();
+
+                final boolean disabledByDpm = (dpm.getKeyguardDisabledFeatures(null, userId)
+                        & DevicePolicyManager.KEYGUARD_DISABLE_TRUST_AGENTS) != 0;
+                return disabledByDpm || disabledByGlobalActions || disabledBySettings
+                        || disabledBySimPin;
+        }
+        return false;
+    }
+
     public boolean getUserHasTrust(int userId) {
-        return mUserHasTrust.get(userId);
+        return !isTrustDisabled(userId) && mUserHasTrust.get(userId);
     }
 
     static class DisplayClientState {
@@ -679,7 +700,7 @@
      * broadcast and hence not handle the event. This method is ultimately called by
      * PhoneWindowManager in this case.
      */
-    protected void dispatchBootCompleted() {
+    public void dispatchBootCompleted() {
         mHandler.sendEmptyMessage(MSG_BOOT_COMPLETED);
     }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 556711b..862931e 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -20,7 +20,7 @@
 import android.graphics.Bitmap;
 import android.media.AudioManager;
 import android.os.SystemClock;
-import android.util.Log;
+import android.telephony.TelephonyManager;
 import android.view.WindowManagerPolicy;
 
 import com.android.internal.telephony.IccCardConstants;
@@ -28,7 +28,7 @@
 /**
  * Callback for general information relevant to lock screen.
  */
-class KeyguardUpdateMonitorCallback {
+public class KeyguardUpdateMonitorCallback {
 
     private static final long VISIBILITY_CHANGED_COLLAPSE_MS = 1000;
     private long mVisibilityChangedCalled;
@@ -40,12 +40,12 @@
      *
      * @param status current battery status
      */
-    void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
+    public void onRefreshBatteryInfo(KeyguardUpdateMonitor.BatteryStatus status) { }
 
     /**
      * Called once per minute or when the time changes.
      */
-    void onTimeChanged() { }
+    public void onTimeChanged() { }
 
     /**
      * Called when the carrier PLMN or SPN changes.
@@ -54,14 +54,14 @@
      *   be displayed.
      * @param spn The service provider name.  May be null if it shouldn't be displayed.
      */
-    void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
+    public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) { }
 
     /**
      * Called when the ringer mode changes.
      * @param state the current ringer state, as defined in
      * {@link AudioManager#RINGER_MODE_CHANGED_ACTION}
      */
-    void onRingerModeChanged(int state) { }
+    public void onRingerModeChanged(int state) { }
 
     /**
      * Called when the phone state changes. String will be one of:
@@ -69,15 +69,15 @@
      * {@link TelephonyManager@EXTRA_STATE_RINGING}
      * {@link TelephonyManager#EXTRA_STATE_OFFHOOK
      */
-    void onPhoneStateChanged(int phoneState) { }
+    public void onPhoneStateChanged(int phoneState) { }
 
     /**
      * Called when the visibility of the keyguard changes.
      * @param showing Indicates if the keyguard is now visible.
      */
-    void onKeyguardVisibilityChanged(boolean showing) { }
+    public void onKeyguardVisibilityChanged(boolean showing) { }
 
-    void onKeyguardVisibilityChangedRaw(boolean showing) {
+    public void onKeyguardVisibilityChangedRaw(boolean showing) {
         final long now = SystemClock.elapsedRealtime();
         if (showing == mShowing
                 && (now - mVisibilityChangedCalled) < VISIBILITY_CHANGED_COLLAPSE_MS) return;
@@ -90,44 +90,44 @@
      * Called when visibility of lockscreen clock changes, such as when
      * obscured by a widget.
      */
-    void onClockVisibilityChanged() { }
+    public void onClockVisibilityChanged() { }
 
     /**
      * Called when the device becomes provisioned
      */
-    void onDeviceProvisioned() { }
+    public void onDeviceProvisioned() { }
 
     /**
      * Called when the device policy changes.
      * See {@link DevicePolicyManager#ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED}
      */
-    void onDevicePolicyManagerStateChanged() { }
+    public void onDevicePolicyManagerStateChanged() { }
 
     /**
      * Called when the user change begins.
      */
-    void onUserSwitching(int userId) { }
+    public void onUserSwitching(int userId) { }
 
     /**
      * Called when the user change is complete.
      */
-    void onUserSwitchComplete(int userId) { }
+    public void onUserSwitchComplete(int userId) { }
 
     /**
      * Called when the SIM state changes.
      * @param simState
      */
-    void onSimStateChanged(IccCardConstants.State simState) { }
+    public void onSimStateChanged(IccCardConstants.State simState) { }
 
     /**
      * Called when a user is removed.
      */
-    void onUserRemoved(int userId) { }
+    public void onUserRemoved(int userId) { }
 
     /**
      * Called when the user's info changed.
      */
-    void onUserInfoChanged(int userId) { }
+    public void onUserInfoChanged(int userId) { }
 
     /**
      * Called when boot completed.
@@ -135,12 +135,12 @@
      * Note, this callback will only be received if boot complete occurs after registering with
      * KeyguardUpdateMonitor.
      */
-    void onBootCompleted() { }
+    public void onBootCompleted() { }
 
     /**
      * Called when audio client attaches or detaches from AudioManager.
      */
-    void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
+    public void onMusicClientIdChanged(int clientGeneration, boolean clearing, PendingIntent intent) { }
 
     /**
      * Called when the audio playback state changes.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index 78f4506..d8e5b8a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -60,7 +60,7 @@
 
     private AudioManager mAudioManager;
     private TelephonyManager mTelephonyManager = null;
-    protected KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
+    protected ViewMediatorCallback mViewMediatorCallback;
     protected LockPatternUtils mLockPatternUtils;
     private OnDismissAction mDismissAction;
 
@@ -68,7 +68,7 @@
     // they will be handled here for specific media types such as music, otherwise
     // the audio service will bring up the volume dialog.
     private static final boolean KEYGUARD_MANAGES_VOLUME = true;
-    private static final boolean DEBUG = false;
+    public static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardViewBase";
 
     private KeyguardSecurityContainer mSecurityContainer;
@@ -107,7 +107,6 @@
         mSecurityContainer.setSecurityCallback(this);
         mSecurityContainer.showPrimarySecurityScreen(false);
         // mSecurityContainer.updateSecurityViews(false /* not bouncing */);
-        setBackButtonEnabled(false);
     }
 
     /**
@@ -120,15 +119,11 @@
 
     /**
      *  Dismisses the keyguard by going to the next screen or making it gone.
+     *
+     *  @return True if the keyguard is done.
      */
-    public void dismiss() {
-        dismiss(false);
-    }
-
-    private void setBackButtonEnabled(boolean enabled) {
-        setSystemUiVisibility(enabled ?
-                getSystemUiVisibility() & ~View.STATUS_BAR_DISABLE_BACK :
-                getSystemUiVisibility() | View.STATUS_BAR_DISABLE_BACK);
+    public boolean dismiss() {
+        return dismiss(false);
     }
 
     protected void showBouncer(boolean show) {
@@ -141,8 +136,7 @@
 
     public boolean handleBackKey() {
         if (mSecurityContainer.getCurrentSecuritySelection() == SecurityMode.Account) {
-            // go back to primary screen and re-disable back
-            setBackButtonEnabled(false);
+            // go back to primary screen
             mSecurityContainer.showPrimarySecurityScreen(false /*turningOff*/);
             return true;
         }
@@ -205,12 +199,6 @@
 
     @Override
     public void onSecurityModeChanged(SecurityMode securityMode, boolean needsInput) {
-        // Enable or disable the back button based on security mode
-        if (securityMode == SecurityMode.Account && !mLockPatternUtils.isPermanentlyLocked()) {
-            // we're showing account as a backup, provide a way to get back to primary
-            setBackButtonEnabled(true);
-        }
-
         if (mViewMediatorCallback != null) {
             mViewMediatorCallback.setNeedsInput(needsInput);
         }
@@ -229,9 +217,9 @@
     }
 
     /**
-     * Called when the screen turned off.
+     * Called when the Keyguard is not actively shown anymore on the screen.
      */
-    protected void onScreenTurnedOff() {
+    public void onPause() {
         if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
                 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
         // Once the screen turns off, we no longer consider this to be first boot and we want the
@@ -243,9 +231,9 @@
     }
 
     /**
-     * Called when the screen turned on.
+     * Called when the Keyguard is actively shown on the screen.
      */
-    protected void onScreenTurnedOn() {
+    public void onResume() {
         if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
         mSecurityContainer.showPrimarySecurityScreen(false);
         mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
@@ -433,8 +421,7 @@
         return false;
     }
 
-    public void setViewMediatorCallback(
-            KeyguardViewMediator.ViewMediatorCallback viewMediatorCallback) {
+    public void setViewMediatorCallback(ViewMediatorCallback viewMediatorCallback) {
         mViewMediatorCallback = viewMediatorCallback;
         // Update ViewMediator with the current input method requirements
         mViewMediatorCallback.setNeedsInput(mSecurityContainer.needsInput());
@@ -484,11 +471,15 @@
         mActivityLauncher.launchCamera(getHandler(), null);
     }
 
-    protected void setLockPatternUtils(LockPatternUtils utils) {
+    public void setLockPatternUtils(LockPatternUtils utils) {
         mLockPatternUtils = utils;
         mSecurityContainer.setLockPatternUtils(utils);
     }
 
+    public SecurityMode getSecurityMode() {
+        return mSecurityContainer.getSecurityMode();
+    }
+
     protected abstract void onUserSwitching(boolean switching);
 
     protected abstract void onCreateOptions(Bundle options);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
deleted file mode 100644
index 5b35ba88..0000000
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewManager.java
+++ /dev/null
@@ -1,575 +0,0 @@
-/*
- * Copyright (C) 2007 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 com.android.keyguard;
-
-import android.graphics.Bitmap;
-import android.graphics.drawable.BitmapDrawable;
-
-import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.KeyguardAnalytics;
-
-import org.xmlpull.v1.XmlPullParser;
-
-import android.app.ActivityManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.pm.ActivityInfo;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.ColorFilter;
-import android.graphics.PixelFormat;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.IBinder;
-import android.os.Parcelable;
-import android.os.RemoteException;
-import android.os.SystemProperties;
-import android.provider.Settings;
-import android.util.Log;
-import android.util.Slog;
-import android.util.SparseArray;
-import android.view.KeyEvent;
-import android.view.LayoutInflater;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewManager;
-import android.view.WindowManager;
-import android.widget.FrameLayout;
-
-/**
- * Manages creating, showing, hiding and resetting the keyguard.  Calls back
- * via {@link KeyguardViewMediator.ViewMediatorCallback} to poke
- * the wake lock and report that the keyguard is done, which is in turn,
- * reported to this class by the current {@link KeyguardViewBase}.
- */
-public class KeyguardViewManager {
-    private final static boolean DEBUG = KeyguardViewMediator.DEBUG;
-    private static String TAG = "KeyguardViewManager";
-    public final static String IS_SWITCHING_USER = "is_switching_user";
-
-    // Delay dismissing keyguard to allow animations to complete.
-    private static final int HIDE_KEYGUARD_DELAY = 500;
-
-    // Timeout used for keypresses
-    static final int DIGIT_PRESS_WAKE_MILLIS = 5000;
-    private static final boolean ENABLE_SIMPLE_KEYGUARD = false;
-
-    private final Context mContext;
-    private final ViewManager mViewManager;
-    private final KeyguardViewMediator.ViewMediatorCallback mViewMediatorCallback;
-    private final KeyguardAnalytics.Callback mAnalyticsCallback;
-
-    private WindowManager.LayoutParams mWindowLayoutParams;
-    private boolean mNeedsInput = false;
-
-    private ViewManagerHost mKeyguardHost;
-    private KeyguardViewBase mKeyguardView;
-
-    private boolean mScreenOn = false;
-    private LockPatternUtils mLockPatternUtils;
-
-    private KeyguardUpdateMonitorCallback mBackgroundChanger = new KeyguardUpdateMonitorCallback() {
-        @Override
-        public void onSetBackground(Bitmap bmp) {
-            mKeyguardHost.setCustomBackground(bmp != null ?
-                    new BitmapDrawable(mContext.getResources(), bmp) : null);
-            updateShowWallpaper(bmp == null);
-        }
-    };
-
-    public interface ShowListener {
-        void onShown(IBinder windowToken);
-    };
-
-    /**
-     * @param context Used to create views.
-     * @param viewManager Keyguard will be attached to this.
-     * @param callback Used to notify of changes.
-     * @param lockPatternUtils
-     */
-    public KeyguardViewManager(Context context, ViewManager viewManager,
-            KeyguardViewMediator.ViewMediatorCallback callback,
-            LockPatternUtils lockPatternUtils, KeyguardAnalytics.Callback analyticsCallback) {
-        mContext = context;
-        mViewManager = viewManager;
-        mViewMediatorCallback = callback;
-        mLockPatternUtils = lockPatternUtils;
-        mAnalyticsCallback = analyticsCallback;
-    }
-
-    /**
-     * Show the keyguard.  Will handle creating and attaching to the view manager
-     * lazily.
-     */
-    public synchronized void show(Bundle options) {
-        if (DEBUG) Log.d(TAG, "show(); mKeyguardView==" + mKeyguardView);
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onShow();
-        }
-
-        boolean enableScreenRotation = shouldEnableScreenRotation();
-
-        maybeCreateKeyguardLocked(enableScreenRotation, false, options);
-        maybeEnableScreenRotation(enableScreenRotation);
-
-        // Disable common aspects of the system/status/navigation bars that are not appropriate or
-        // useful on any keyguard screen but can be re-shown by dialogs or SHOW_WHEN_LOCKED
-        // activities. Other disabled bits are handled by the KeyguardViewMediator talking
-        // directly to the status bar service.
-        int visFlags = View.STATUS_BAR_DISABLE_HOME;
-        if (shouldEnableTranslucentDecor()) {
-            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
-                                       | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
-        }
-        if (DEBUG) Log.v(TAG, "show:setSystemUiVisibility(" + Integer.toHexString(visFlags)+")");
-        mKeyguardHost.setSystemUiVisibility(visFlags);
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-        mKeyguardHost.setVisibility(View.VISIBLE);
-        mKeyguardView.show();
-        mKeyguardView.requestFocus();
-    }
-
-    private boolean shouldEnableScreenRotation() {
-        Resources res = mContext.getResources();
-        return SystemProperties.getBoolean("lockscreen.rot_override",false)
-                || res.getBoolean(R.bool.config_enableLockScreenRotation);
-    }
-
-    private boolean shouldEnableTranslucentDecor() {
-        Resources res = mContext.getResources();
-        return res.getBoolean(R.bool.config_enableLockScreenTranslucentDecor);
-    }
-
-    class ViewManagerHost extends FrameLayout {
-        private static final int BACKGROUND_COLOR = 0x70000000;
-
-        private Drawable mCustomBackground;
-
-        // This is a faster way to draw the background on devices without hardware acceleration
-        private final Drawable mBackgroundDrawable = new Drawable() {
-            @Override
-            public void draw(Canvas canvas) {
-                if (mCustomBackground != null) {
-                    final Rect bounds = mCustomBackground.getBounds();
-                    final int vWidth = getWidth();
-                    final int vHeight = getHeight();
-
-                    final int restore = canvas.save();
-                    canvas.translate(-(bounds.width() - vWidth) / 2,
-                            -(bounds.height() - vHeight) / 2);
-                    mCustomBackground.draw(canvas);
-                    canvas.restoreToCount(restore);
-                } else {
-                    canvas.drawColor(BACKGROUND_COLOR, PorterDuff.Mode.SRC);
-                }
-            }
-
-            @Override
-            public void setAlpha(int alpha) {
-            }
-
-            @Override
-            public void setColorFilter(ColorFilter cf) {
-            }
-
-            @Override
-            public int getOpacity() {
-                return PixelFormat.TRANSLUCENT;
-            }
-        };
-
-        public ViewManagerHost(Context context) {
-            super(context);
-            setBackground(mBackgroundDrawable);
-        }
-
-        public void setCustomBackground(Drawable d) {
-            mCustomBackground = d;
-            if (d != null) {
-                d.setColorFilter(BACKGROUND_COLOR, PorterDuff.Mode.SRC_OVER);
-            }
-            computeCustomBackgroundBounds();
-            invalidate();
-        }
-
-        private void computeCustomBackgroundBounds() {
-            if (mCustomBackground == null) return; // Nothing to do
-            if (!isLaidOut()) return; // We'll do this later
-
-            final int bgWidth = mCustomBackground.getIntrinsicWidth();
-            final int bgHeight = mCustomBackground.getIntrinsicHeight();
-            final int vWidth = getWidth();
-            final int vHeight = getHeight();
-
-            final float bgAspect = (float) bgWidth / bgHeight;
-            final float vAspect = (float) vWidth / vHeight;
-
-            if (bgAspect > vAspect) {
-                mCustomBackground.setBounds(0, 0, (int) (vHeight * bgAspect), vHeight);
-            } else {
-                mCustomBackground.setBounds(0, 0, vWidth, (int) (vWidth / bgAspect));
-            }
-        }
-
-        @Override
-        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-            super.onSizeChanged(w, h, oldw, oldh);
-            computeCustomBackgroundBounds();
-        }
-
-        @Override
-        protected void onConfigurationChanged(Configuration newConfig) {
-            super.onConfigurationChanged(newConfig);
-            if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                // only propagate configuration messages if we're currently showing
-                maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, null);
-            } else {
-                if (DEBUG) Log.v(TAG, "onConfigurationChanged: view not visible");
-            }
-        }
-
-        @Override
-        public boolean dispatchKeyEvent(KeyEvent event) {
-            if (mKeyguardView != null) {
-                // Always process back and menu keys, regardless of focus
-                if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                    int keyCode = event.getKeyCode();
-                    if (keyCode == KeyEvent.KEYCODE_BACK && mKeyguardView.handleBackKey()) {
-                        return true;
-                    } else if (keyCode == KeyEvent.KEYCODE_MENU && mKeyguardView.handleMenuKey()) {
-                        return true;
-                    }
-                }
-                // Always process media keys, regardless of focus
-                if (mKeyguardView.dispatchKeyEvent(event)) {
-                    return true;
-                }
-            }
-            return super.dispatchKeyEvent(event);
-        }
-
-        @Override
-        public boolean dispatchTouchEvent(MotionEvent ev) {
-            boolean result = false;
-            if (mAnalyticsCallback != null) {
-                result = mAnalyticsCallback.onTouchEvent(ev, getWidth(), getHeight()) || result;
-            }
-            return super.dispatchTouchEvent(ev) || result;
-        }
-    }
-
-    SparseArray<Parcelable> mStateContainer = new SparseArray<Parcelable>();
-    private int mCurrentLayout;
-
-    private void maybeCreateKeyguardLocked(boolean enableScreenRotation, boolean force,
-            Bundle options) {
-        if (mKeyguardHost != null) {
-            mKeyguardHost.saveHierarchyState(mStateContainer);
-        }
-
-        if (mKeyguardHost == null) {
-            if (DEBUG) Log.d(TAG, "keyguard host is null, creating it...");
-
-            mKeyguardHost = new ViewManagerHost(mContext);
-
-            int flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
-                    | WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
-                    | WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-
-            if (!mNeedsInput) {
-                flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-
-            final int stretch = ViewGroup.LayoutParams.MATCH_PARENT;
-            final int type = WindowManager.LayoutParams.TYPE_KEYGUARD;
-            WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                    stretch, stretch, type, flags, PixelFormat.TRANSLUCENT);
-            lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
-            lp.windowAnimations = R.style.Animation_LockScreen;
-            lp.screenOrientation = enableScreenRotation ?
-                    ActivityInfo.SCREEN_ORIENTATION_USER : ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-
-            if (ActivityManager.isHighEndGfx()) {
-                lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-                lp.privateFlags |=
-                        WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED;
-            }
-            lp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_SET_NEEDS_MENU_KEY;
-            lp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
-            lp.setTitle("Keyguard");
-            mWindowLayoutParams = lp;
-            mViewManager.addView(mKeyguardHost, lp);
-
-            KeyguardUpdateMonitor.getInstance(mContext).registerCallback(mBackgroundChanger);
-        }
-
-        if (force || mKeyguardView == null) {
-            mKeyguardHost.setCustomBackground(null);
-            mKeyguardHost.removeAllViews();
-            int layout = (allowNotificationsOnSecureKeyguard() && ENABLE_SIMPLE_KEYGUARD)
-                    ? R.layout.keyguard_simple_host_view
-                    : R.layout.keyguard_host_view;
-            if (mCurrentLayout != layout) {
-                mStateContainer.clear(); // don't restore to the wrong view hierarchy
-                mCurrentLayout = layout;
-            }
-            mKeyguardView = inflateKeyguardView(options, layout);
-            mKeyguardView.requestFocus();
-        }
-        updateUserActivityTimeoutInWindowLayoutParams();
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-
-        mKeyguardHost.restoreHierarchyState(mStateContainer);
-    }
-
-    private boolean allowNotificationsOnSecureKeyguard() {
-        ContentResolver cr = mContext.getContentResolver();
-        return Settings.Global.getInt(cr, Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS, 0) == 1;
-    }
-
-    private KeyguardViewBase inflateKeyguardView(Bundle options, int layoutId) {
-        View v = mKeyguardHost.findViewById(R.id.keyguard_host_view);
-        if (v != null) {
-            mKeyguardHost.removeView(v);
-        }
-        final LayoutInflater inflater = LayoutInflater.from(mContext);
-        View view = inflater.inflate(layoutId, mKeyguardHost, true);
-        KeyguardViewBase keyguard = (KeyguardViewBase) view.findViewById(R.id.keyguard_host_view);
-        keyguard.setLockPatternUtils(mLockPatternUtils);
-        keyguard.setViewMediatorCallback(mViewMediatorCallback);
-        keyguard.onUserSwitching(options != null && options.getBoolean(IS_SWITCHING_USER));
-        keyguard.onCreateOptions(options);
-        return keyguard;
-    }
-
-    public void updateUserActivityTimeout() {
-        updateUserActivityTimeoutInWindowLayoutParams();
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    private void updateUserActivityTimeoutInWindowLayoutParams() {
-        // Use the user activity timeout requested by the keyguard view, if any.
-        if (mKeyguardView != null) {
-            long timeout = mKeyguardView.getUserActivityTimeout();
-            if (timeout >= 0) {
-                mWindowLayoutParams.userActivityTimeout = timeout;
-                return;
-            }
-        }
-
-        // Otherwise, use the default timeout.
-        mWindowLayoutParams.userActivityTimeout = KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
-    }
-
-    private void maybeEnableScreenRotation(boolean enableScreenRotation) {
-        // TODO: move this outside
-        if (enableScreenRotation) {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen On!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
-        } else {
-            if (DEBUG) Log.d(TAG, "Rotation sensor for lock screen Off!");
-            mWindowLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
-        }
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    void updateShowWallpaper(boolean show) {
-        if (show) {
-            mWindowLayoutParams.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        } else {
-            mWindowLayoutParams.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
-        }
-        mWindowLayoutParams.format = show ? PixelFormat.TRANSLUCENT : PixelFormat.OPAQUE;
-
-        mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-    }
-
-    public void setNeedsInput(boolean needsInput) {
-        mNeedsInput = needsInput;
-        if (mWindowLayoutParams != null) {
-            if (needsInput) {
-                mWindowLayoutParams.flags &=
-                    ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            } else {
-                mWindowLayoutParams.flags |=
-                    WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-            }
-
-            try {
-                mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
-            } catch (java.lang.IllegalArgumentException e) {
-                // TODO: Ensure this method isn't called on views that are changing...
-                Log.w(TAG,"Can't update input method on " + mKeyguardHost + " window not attached");
-            }
-        }
-    }
-
-    /**
-     * Reset the state of the view.
-     */
-    public synchronized void reset(Bundle options) {
-        if (DEBUG) Log.d(TAG, "reset()");
-        // User might have switched, check if we need to go back to keyguard
-        // TODO: It's preferable to stay and show the correct lockscreen or unlock if none
-        maybeCreateKeyguardLocked(shouldEnableScreenRotation(), true, options);
-    }
-
-    public synchronized void onScreenTurnedOff() {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOff()");
-        mScreenOn = false;
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOff();
-        }
-    }
-
-    public synchronized void onScreenTurnedOn(final IKeyguardShowCallback callback) {
-        if (DEBUG) Log.d(TAG, "onScreenTurnedOn()");
-        mScreenOn = true;
-
-        // If keyguard is not showing, we need to inform PhoneWindowManager with a null
-        // token so it doesn't wait for us to draw...
-        final IBinder token = isShowing() ? mKeyguardHost.getWindowToken() : null;
-
-        if (DEBUG && token == null) Slog.v(TAG, "send wm null token: "
-                + (mKeyguardHost == null ? "host was null" : "not showing"));
-
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOn();
-
-            // Caller should wait for this window to be shown before turning
-            // on the screen.
-            if (callback != null) {
-                if (mKeyguardHost.getVisibility() == View.VISIBLE) {
-                    // Keyguard may be in the process of being shown, but not yet
-                    // updated with the window manager...  give it a chance to do so.
-                    mKeyguardHost.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            try {
-                                callback.onShown(token);
-                            } catch (RemoteException e) {
-                                Slog.w(TAG, "Exception calling onShown():", e);
-                            }
-                        }
-                    });
-                } else {
-                    try {
-                        callback.onShown(token);
-                    } catch (RemoteException e) {
-                        Slog.w(TAG, "Exception calling onShown():", e);
-                    }
-                }
-            }
-        } else if (callback != null) {
-            try {
-                callback.onShown(token);
-            } catch (RemoteException e) {
-                Slog.w(TAG, "Exception calling onShown():", e);
-            }
-        }
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onScreenOn();
-        }
-    }
-
-    public synchronized void verifyUnlock() {
-        if (DEBUG) Log.d(TAG, "verifyUnlock()");
-        show(null);
-        mKeyguardView.verifyUnlock();
-    }
-
-    /**
-     * Hides the keyguard view
-     */
-    public synchronized void hide() {
-        if (DEBUG) Log.d(TAG, "hide()");
-
-        if (mAnalyticsCallback != null) {
-            mAnalyticsCallback.onHide();
-        }
-
-        if (mKeyguardHost != null) {
-            mKeyguardHost.setVisibility(View.GONE);
-
-            // We really only want to preserve keyguard state for configuration changes. Hence
-            // we should clear state of widgets (e.g. Music) when we hide keyguard so it can
-            // start with a fresh state when we return.
-            mStateContainer.clear();
-
-            // Don't do this right away, so we can let the view continue to animate
-            // as it goes away.
-            if (mKeyguardView != null) {
-                final KeyguardViewBase lastView = mKeyguardView;
-                mKeyguardView = null;
-                mKeyguardHost.postDelayed(new Runnable() {
-                    @Override
-                    public void run() {
-                        synchronized (KeyguardViewManager.this) {
-                            lastView.cleanUp();
-                            // Let go of any large bitmaps.
-                            mKeyguardHost.setCustomBackground(null);
-                            updateShowWallpaper(true);
-                            mKeyguardHost.removeView(lastView);
-                            mViewMediatorCallback.keyguardGone();
-                        }
-                    }
-                }, HIDE_KEYGUARD_DELAY);
-            }
-        }
-    }
-
-    /**
-     * Dismisses the keyguard by going to the next screen or making it gone.
-     */
-    public synchronized void dismiss() {
-        if (mScreenOn) {
-            mKeyguardView.dismiss();
-        }
-    }
-
-    /**
-     * @return Whether the keyguard is showing
-     */
-    public synchronized boolean isShowing() {
-        return (mKeyguardHost != null && mKeyguardHost.getVisibility() == View.VISIBLE);
-    }
-
-    public void showAssistant() {
-        if (mKeyguardView != null) {
-            mKeyguardView.showAssistant();
-        }
-    }
-
-    public void dispatch(MotionEvent event) {
-        if (mKeyguardView != null) {
-            mKeyguardView.onExternalMotionEvent(event);
-        }
-    }
-
-    public void launchCamera() {
-        if (mKeyguardView != null) {
-            mKeyguardView.launchCamera();
-        }
-    }
-}
diff --git a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
index 9930e72..7128211 100644
--- a/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
+++ b/packages/Keyguard/src/com/android/keyguard/MultiUserAvatarCache.java
@@ -22,12 +22,21 @@
 
 public class MultiUserAvatarCache {
 
+    private static MultiUserAvatarCache sInstance;
+
     private final HashMap<Integer, Drawable> mCache;
 
-    public MultiUserAvatarCache() {
+    private MultiUserAvatarCache() {
         mCache = new HashMap<Integer, Drawable>();
     }
 
+    public static MultiUserAvatarCache getInstance() {
+        if (sInstance == null) {
+            sInstance = new MultiUserAvatarCache();
+        }
+        return sInstance;
+    }
+
     public void clear(int userId) {
         mCache.remove(userId);
     }
diff --git a/packages/Keyguard/src/com/android/keyguard/PagedView.java b/packages/Keyguard/src/com/android/keyguard/PagedView.java
index d233ee9..b42a085 100644
--- a/packages/Keyguard/src/com/android/keyguard/PagedView.java
+++ b/packages/Keyguard/src/com/android/keyguard/PagedView.java
@@ -56,7 +56,7 @@
 public abstract class PagedView extends ViewGroup implements ViewGroup.OnHierarchyChangeListener {
     private static final int WARP_SNAP_DURATION = 160;
     private static final String TAG = "WidgetPagedView";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final boolean DEBUG_WARP = false;
     protected static final int INVALID_PAGE = -1;
     private static final int WARP_PEEK_ANIMATION_DURATION = 150;
diff --git a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
index 3d515ce..ab9286b 100644
--- a/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
+++ b/packages/Keyguard/src/com/android/keyguard/SlidingChallengeLayout.java
@@ -45,7 +45,7 @@
  */
 public class SlidingChallengeLayout extends ViewGroup implements ChallengeLayout {
     private static final String TAG = "SlidingChallengeLayout";
-    private static final boolean DEBUG = false;
+    private static final boolean DEBUG = KeyguardConstants.DEBUG;
 
     // The drag handle is measured in dp above & below the top edge of the
     // challenge view; these parameters change based on whether the challenge
diff --git a/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
new file mode 100644
index 0000000..1f23785
--- /dev/null
+++ b/packages/Keyguard/src/com/android/keyguard/ViewMediatorCallback.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.keyguard;
+
+/**
+ * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
+ * various things.
+ */
+public interface ViewMediatorCallback {
+    /**
+     * Reports user activity and requests that the screen stay on.
+     */
+    void userActivity();
+
+    /**
+     * Reports user activity and requests that the screen stay on for at least
+     * the specified amount of time.
+     * @param millis The amount of time in millis.  This value is currently ignored.
+     */
+    void userActivity(long millis);
+
+    /**
+     * Report that the keyguard is done.
+     * @param authenticated Whether the user securely got past the keyguard.
+     *   the only reason for this to be false is if the keyguard was instructed
+     *   to appear temporarily to verify the user is supposed to get past the
+     *   keyguard, and the user fails to do so.
+     */
+    void keyguardDone(boolean authenticated);
+
+    /**
+     * Report that the keyguard is done drawing.
+     */
+    void keyguardDoneDrawing();
+
+    /**
+     * Tell ViewMediator that the current view needs IME input
+     * @param needsInput
+     */
+    void setNeedsInput(boolean needsInput);
+
+    /**
+     * Tell view mediator that the keyguard view's desired user activity timeout
+     * has changed and needs to be reapplied to the window.
+     */
+    void onUserActivityTimeoutChanged();
+
+    /**
+     * Report that the keyguard is dismissable, pending the next keyguardDone call.
+     */
+    void keyguardDonePending();
+
+    /**
+     * Report when keyguard is actually gone
+     */
+    void keyguardGone();
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
index 55750cc..20af2f1 100644
--- a/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
+++ b/packages/Keyguard/src/com/android/keyguard/analytics/KeyguardAnalytics.java
@@ -80,7 +80,7 @@
         public void onScreenOn();
         public void onScreenOff();
         public boolean onTouchEvent(MotionEvent ev, int width, int height);
-        public void onSetHidden(boolean hidden);
+        public void onSetOccluded(boolean hidden);
     }
 
     public interface SessionTypeAdapter {
@@ -256,11 +256,11 @@
         }
 
         @Override
-        public void onSetHidden(boolean hidden) {
+        public void onSetOccluded(boolean hidden) {
             synchronized (KeyguardAnalytics.this) {
                 if (hidden != mHidden) {
                     if (DEBUG) {
-                        Log.d(TAG, "onSetHidden(" + hidden + ")");
+                        Log.d(TAG, "onSetOccluded(" + hidden + ")");
                     }
                     mHidden = hidden;
                     if (hidden) {
diff --git a/packages/PrintSpooler/res/values-ja/strings.xml b/packages/PrintSpooler/res/values-ja/strings.xml
index f8be5c7..d3f4f85 100644
--- a/packages/PrintSpooler/res/values-ja/strings.xml
+++ b/packages/PrintSpooler/res/values-ja/strings.xml
@@ -23,7 +23,7 @@
     <string name="label_destination" msgid="9132510997381599275">"印刷先"</string>
     <string name="label_copies" msgid="3634531042822968308">"部数"</string>
     <string name="label_paper_size" msgid="8681895607876809323">"用紙サイズ"</string>
-    <string name="label_color" msgid="1108690305218188969">"カラー"</string>
+    <string name="label_color" msgid="1108690305218188969">"カラー選択"</string>
     <string name="label_orientation" msgid="2853142581990496477">"方向"</string>
     <string name="label_pages" msgid="6300874667546617333">"ページ(<xliff:g id="PAGE_COUNT">%1$s</xliff:g>)"</string>
     <string name="pages_range_example" msgid="8558694453556945172">"例: 1-5,8,11-13"</string>
@@ -66,7 +66,7 @@
     <string name="print_error_default_message" msgid="8568506918983980567">"印刷ジョブを生成できませんでした"</string>
   <string-array name="color_mode_labels">
     <item msgid="7602948745415174937">"モノクロ"</item>
-    <item msgid="2762241247228983754">"色"</item>
+    <item msgid="2762241247228983754">"カラー"</item>
   </string-array>
   <string-array name="orientation_labels">
     <item msgid="4061931020926489228">"縦向き"</item>
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 19286c8..56f5a3a 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -87,6 +87,8 @@
     <uses-permission android:name="android.permission.MANAGE_USERS" />
     <uses-permission android:name="android.permission.BLUETOOTH_STACK" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
+    <uses-permission android:name="android.permission.FRAME_STATS" />
 
     <application android:label="@string/app_label">
         <provider
diff --git a/packages/SystemUI/Android.mk b/packages/SystemUI/Android.mk
index f8f064a..69c6159 100644
--- a/packages/SystemUI/Android.mk
+++ b/packages/SystemUI/Android.mk
@@ -6,6 +6,7 @@
 LOCAL_SRC_FILES := $(call all-java-files-under, src) \
     src/com/android/systemui/EventLogTags.logtags
 
+LOCAL_STATIC_JAVA_LIBRARIES := Keyguard
 LOCAL_JAVA_LIBRARIES := telephony-common
 
 LOCAL_PACKAGE_NAME := SystemUI
@@ -14,6 +15,11 @@
 
 LOCAL_PROGUARD_FLAG_FILES := proguard.flags
 
+LOCAL_RESOURCE_DIR := \
+    frameworks/base/packages/Keyguard/res \
+    $(LOCAL_PATH)/res
+LOCAL_AAPT_FLAGS := --auto-add-overlay --extra-packages com.android.keyguard
+
 include $(BUILD_PACKAGE)
 
 include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/SystemUI/AndroidManifest.xml b/packages/SystemUI/AndroidManifest.xml
index 3424eed..327df8d 100644
--- a/packages/SystemUI/AndroidManifest.xml
+++ b/packages/SystemUI/AndroidManifest.xml
@@ -89,11 +89,20 @@
 
     <!-- Keyguard -->
     <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
+    <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
+    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
+    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
+    <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
+    <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />
+    <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" />
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
+    <uses-permission android:name="android.permission.TRUST_LISTENER" />
 
     <!-- Wifi Display -->
     <uses-permission android:name="android.permission.CONFIGURE_WIFI_DISPLAY" />
 
     <application
+        android:name=".SystemUIApplication"
         android:persistent="true"
         android:allowClearUserData="false"
         android:allowBackup="false"
@@ -101,7 +110,11 @@
         android:label="@string/app_label"
         android:icon="@*android:drawable/platlogo"
         android:process="com.android.systemui"
-        android:supportsRtl="true">
+        android:supportsRtl="true"
+        android:theme="@style/systemui_theme">
+        <!-- Keep theme in sync with SystemUIApplication.onCreate().
+             Setting the theme on the application does not affect views inflated by services.
+             The application theme is set again from onCreate to take effect for those views. -->
 
         <!-- Broadcast receiver that gets the broadcast at boot time and starts
              up everything else.
@@ -258,6 +271,11 @@
             </intent-filter>
         </service>
 
+        <service
+            android:name=".keyguard.KeyguardService"
+            android:exported="true"
+            android:enabled="@bool/config_enableKeyguardService" />
+
         <activity android:name=".Somnambulator"
             android:label="@string/start_dreams"
             android:icon="@mipmap/ic_launcher_dreams"
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 48d9722..da37803 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -6,7 +6,7 @@
   public void setGlowAlpha(float);
   public void setGlowScale(float);
 }
--keep class com.android.systemui.recents.views.TaskIconView {
+-keep class com.android.systemui.recents.views.TaskInfoView {
 	public void setCircularClipRadius(float);
 	public float getCircularClipRadius();
 }
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
index 092b561..3c0dc4e 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
index 064860d..3b1944d 100644
--- a/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-hdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-hdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..85db9c8
--- /dev/null
+++ b/packages/SystemUI/res/drawable-hdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
deleted file mode 100644
index 46d2a16..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_color_space_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
deleted file mode 100644
index 704b4ec..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_contrast_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png b/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
deleted file mode 100644
index d56efb5..0000000
--- a/packages/SystemUI/res/drawable-ldpi/ic_qs_inversion_alpha.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png
deleted file mode 100644
index 13f6b7f..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index ecdb240..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-hdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png
deleted file mode 100644
index c98911c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index bb99022..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-mdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png
deleted file mode 100644
index d9d8b13..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index 09e0a3c..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xhdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png
deleted file mode 100644
index c0855b5..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_open_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png
deleted file mode 100644
index e3fb992..0000000
--- a/packages/SystemUI/res/drawable-ldrtl-xxhdpi/ic_notify_quicksettings_normal.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
index ae5d263..8010ce7 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
index 32fbed4..807f607 100644
--- a/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-mdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-mdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..c4941a6
--- /dev/null
+++ b/packages/SystemUI/res/drawable-mdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
index 990f8bb..6d46fdd 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
index 96eaafe..e562bc2 100644
--- a/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-xhdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..4618f40
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
index 60579f9..7742207 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_open_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
index abb9b18..a2e8fe1 100644
--- a/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
+++ b/packages/SystemUI/res/drawable-xxhdpi/ic_notify_quicksettings_normal.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off.png
rename to packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_off_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on.png b/packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on_alpha.png
similarity index 100%
rename from packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on.png
rename to packages/SystemUI/res/drawable-xxhdpi/ic_qs_brightness_auto_on_alpha.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png b/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png
new file mode 100644
index 0000000..36e7e45
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/recents_task_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png b/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
new file mode 100644
index 0000000..c0bf31d
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xxhdpi/search_bg_transparent.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
index 85f1ea2..3a47261 100644
--- a/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
+++ b/packages/SystemUI/res/drawable/ic_notify_button_bg.xml
@@ -15,6 +15,6 @@
 -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:state_pressed="true"  android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
-    <item                               android:drawable="@*android:drawable/list_selector_disabled_holo_dark" />
+    <item android:state_pressed="true"
+          android:drawable="@*android:drawable/list_selector_pressed_holo_dark" />
 </selector>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
index 15d0890..b7fe5ab 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_off.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +14,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_brightness_auto_off_alpha"
+    android:tint="?android:attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml
index 15d0890..e17b533 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/packages/SystemUI/res/drawable/ic_qs_brightness_auto_on.xml
@@ -1,5 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +14,7 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/ic_qs_brightness_auto_on_alpha"
+    android:tint="?android:attr/colorControlNormal" />
diff --git a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml b/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
deleted file mode 100644
index 0947c6f..0000000
--- a/packages/SystemUI/res/layout-sw600dp/super_status_bar.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-**
-** Copyright 2012, 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.
-*/
--->
-
-<!-- This is the combined status bar / notification panel window. -->
-<com.android.systemui.statusbar.phone.StatusBarWindowView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
-    android:focusable="true"
-    android:descendantFocusability="afterDescendants"
-    android:fitsSystemWindows="true"
-    >
-
-    <include layout="@layout/status_bar"
-        android:layout_width="match_parent"
-        android:layout_height="@*android:dimen/status_bar_height"
-        />
-
-
-    <com.android.systemui.statusbar.phone.PanelHolder
-        android:id="@+id/panel_holder"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:layout_marginTop="@*android:dimen/status_bar_height"
-        >
-        <include layout="@layout/status_bar_expanded"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="start|top"
-            />
-        <include layout="@layout/quick_settings"
-            android:layout_width="@dimen/notification_panel_width"
-            android:layout_height="wrap_content"
-            android:layout_gravity="end|top"
-            />
-    </com.android.systemui.statusbar.phone.PanelHolder>
-</com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/flip_settings.xml b/packages/SystemUI/res/layout/flip_settings.xml
index 1b8898c5..f3c1b90 100644
--- a/packages/SystemUI/res/layout/flip_settings.xml
+++ b/packages/SystemUI/res/layout/flip_settings.xml
@@ -14,18 +14,13 @@
      limitations under the License.
 -->
 
-<com.android.systemui.statusbar.phone.QuickSettingsScrollView
+<com.android.systemui.statusbar.phone.QuickSettingsContainerView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/quick_settings_container"
+    android:padding="@dimen/notification_side_padding"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:layout_marginBottom="@dimen/close_handle_underlap"
-    android:overScrollMode="ifContentScrolls"
-    >
-    <com.android.systemui.statusbar.phone.QuickSettingsContainerView
-        android:id="@+id/quick_settings_container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:animateLayoutChanges="true"
-        android:columnCount="@integer/quick_settings_num_columns"
-        />
-</com.android.systemui.statusbar.phone.QuickSettingsScrollView>
\ No newline at end of file
+    android:background="#5f000000"
+    android:animateLayoutChanges="true"
+    android:visibility="gone"
+    android:columnCount="@integer/quick_settings_num_columns" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
new file mode 100644
index 0000000..809adcd
--- /dev/null
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<com.android.systemui.statusbar.phone.KeyguardBottomAreaView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:id="@+id/keyguard_bottom_area"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    >
+    <com.android.systemui.statusbar.policy.KeyButtonView
+        android:id="@+id/camera_button"
+        android:layout_height="80dp"
+        android:layout_width="80dp"
+        android:layout_gravity="bottom|right"
+        android:src="@drawable/ic_sysbar_camera"
+        android:scaleType="center"
+        android:contentDescription="@string/accessibility_camera_button"
+        systemui:glowBackground="@drawable/ic_sysbar_highlight_land" />
+
+    <com.android.systemui.statusbar.phone.KeyguardIndicationTextView
+        android:id="@+id/keyguard_indication_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="100dp"
+        android:layout_gravity="bottom|center_horizontal"
+        android:textStyle="italic"
+        android:textAppearance="?android:attr/textAppearanceMedium"/>
+
+</com.android.systemui.statusbar.phone.KeyguardBottomAreaView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/navigation_bar.xml b/packages/SystemUI/res/layout/navigation_bar.xml
index 5488a87..2398849 100644
--- a/packages/SystemUI/res/layout/navigation_bar.xml
+++ b/packages/SystemUI/res/layout/navigation_bar.xml
@@ -159,17 +159,6 @@
                 android:visibility="gone"
                 android:contentDescription="@string/accessibility_search_light"
                 />
-
-            <com.android.systemui.statusbar.policy.KeyButtonView
-                android:id="@+id/camera_button"
-                android:layout_height="match_parent"
-                android:layout_width="80dp"
-                android:layout_gravity="center_vertical|right"
-                android:src="@drawable/ic_sysbar_camera"
-                android:scaleType="center"
-                android:visibility="gone"
-                android:contentDescription="@string/accessibility_camera_button"
-                />
         </FrameLayout>
 
         <com.android.systemui.statusbar.policy.DeadZone
diff --git a/packages/SystemUI/res/layout/quick_settings.xml b/packages/SystemUI/res/layout/quick_settings.xml
deleted file mode 100644
index 75082ba..0000000
--- a/packages/SystemUI/res/layout/quick_settings.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
--->
-
-<com.android.systemui.statusbar.phone.SettingsPanelView 
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content"
-    android:id="@+id/settings_panel"
-    android:background="@drawable/notification_panel_bg"
-    >
-    <!-- TODO: Put into ScrollView -->
-    <com.android.systemui.statusbar.phone.QuickSettingsScrollView
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/close_handle_underlap"
-        android:overScrollMode="ifContentScrolls"
-        >
-        <com.android.systemui.statusbar.phone.QuickSettingsContainerView
-            android:id="@+id/quick_settings_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:animateLayoutChanges="true"
-            android:columnCount="@integer/quick_settings_num_columns"
-            />
-    </com.android.systemui.statusbar.phone.QuickSettingsScrollView>
-
-    <View
-        android:id="@+id/handle"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/close_handle_height"
-        android:background="@drawable/status_bar_close"
-        android:visibility="invisible"
-        />
-
-</com.android.systemui.statusbar.phone.SettingsPanelView >
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
index a6f4e9b..b7df51d 100644
--- a/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
+++ b/packages/SystemUI/res/layout/quick_settings_brightness_dialog.xml
@@ -13,27 +13,25 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
-<LinearLayout 
-    xmlns:android="http://schemas.android.com/apk/res/android"
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
     style="@style/BrightnessDialogContainer">
 
     <ImageView
         android:id="@+id/brightness_icon"
-	    android:layout_width="wrap_content"
-	    android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_gravity="center_vertical"
-        android:paddingEnd="10dp"
+        android:layout_marginEnd="8dp"
         android:src="@drawable/ic_qs_brightness_auto_off"
-        />
+        android:contentDescription="@null" />
+
     <com.android.systemui.settings.ToggleSlider
         android:id="@+id/brightness_slider"
         android:layout_width="0dp"
         android:layout_height="40dp"
-        android:layout_weight="1"
-        android:layout_marginEnd="2dp"
         android:layout_gravity="center_vertical"
-        systemui:text="@string/status_bar_settings_auto_brightness_label"
-        />
+        android:layout_weight="1"
+        systemui:text="@string/status_bar_settings_auto_brightness_label" />
+
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/recents_search_bar.xml b/packages/SystemUI/res/layout/recents_search_bar.xml
new file mode 100644
index 0000000..915283e
--- /dev/null
+++ b/packages/SystemUI/res/layout/recents_search_bar.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:background="@drawable/search_bg_transparent">
+    <TextView
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center"
+        android:text="@string/recents_search_bar_label"
+        android:textColor="#99ffffff"
+        android:textSize="18sp"
+        android:textAllCaps="true" />
+</FrameLayout>
+
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 96da21f..ddc0dbf 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -21,36 +21,48 @@
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
         android:layout_height="match_parent" />
+    <com.android.systemui.recents.views.TaskInfoView
+        android:id="@+id/task_view_info_pane"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:visibility="invisible"
+        android:background="@color/recents_task_bar_default_background_color">
+        <Button
+            android:id="@+id/task_view_app_info_button"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginStart="20dp"
+            android:layout_marginEnd="20dp"
+            android:layout_gravity="top|center_horizontal"
+            android:text="@string/recents_app_info_button_label" />
+    </com.android.systemui.recents.views.TaskInfoView>
     <com.android.systemui.recents.views.TaskBarView
         android:id="@+id/task_view_bar"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_gravity="top|center_horizontal"
-        android:background="#e6444444">
+        android:background="@color/recents_task_bar_default_background_color">
         <ImageView
             android:id="@+id/application_icon"
             android:layout_width="@dimen/recents_task_view_application_icon_size"
             android:layout_height="@dimen/recents_task_view_application_icon_size"
-            android:layout_gravity="center_vertical|left"
+            android:layout_gravity="center_vertical|start"
             android:padding="8dp" />
         <TextView
             android:id="@+id/activity_description"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical|left"
-            android:layout_marginLeft="@dimen/recents_task_view_application_icon_size"
-            android:layout_marginRight="@dimen/recents_task_view_activity_icon_size"
-            android:textSize="24sp"
+            android:layout_marginStart="@dimen/recents_task_view_application_icon_size"
+            android:layout_marginEnd="8dp"
+            android:textSize="22sp"
             android:textColor="#ffffffff"
             android:text="@string/recents_empty_message"
-            android:fontFamily="sans-serif-thin" />
-        <ImageView
-            android:id="@+id/activity_icon"
-            android:layout_width="@dimen/recents_task_view_activity_icon_size"
-            android:layout_height="@dimen/recents_task_view_activity_icon_size"
-            android:layout_gravity="center_vertical|right"
-            android:padding="12dp"
-            android:visibility="invisible" />
+            android:fontFamily="sans-serif-thin"
+            android:singleLine="true"
+            android:maxLines="2"
+            android:ellipsize="marquee"
+            android:fadingEdge="horizontal" />
     </com.android.systemui.recents.views.TaskBarView>
 </com.android.systemui.recents.views.TaskView>
 
diff --git a/packages/SystemUI/res/layout/status_bar.xml b/packages/SystemUI/res/layout/status_bar.xml
index ea6be1b..1b35537 100644
--- a/packages/SystemUI/res/layout/status_bar.xml
+++ b/packages/SystemUI/res/layout/status_bar.xml
@@ -27,7 +27,6 @@
     android:orientation="vertical"
     android:focusable="true"
     android:descendantFocusability="afterDescendants"
-    android:fitsSystemWindows="true"
     >
 
     <ImageView
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index a7ec064..761ad42 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -36,45 +36,65 @@
         android:layout_gravity="bottom"
         />
 
-    <LinearLayout
+    <include
+        layout="@layout/status_bar_flip_button"
+        android:id="@+id/keyguard_flipper"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:layout_gravity="right|top"
+        android:layout_marginTop="@dimen/status_bar_height"
+        android:visibility="gone" />
+
+    <com.android.keyguard.CarrierText
+        android:id="@+id/keyguard_carrier_text"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_marginTop="2dp"
+        android:layout_marginLeft="8dp"
+        android:ellipsize="marquee"
+        android:textAppearance="?android:attr/textAppearanceMedium" />
+
+    <include layout="@layout/status_bar_expanded_header"
+        android:layout_width="match_parent"
+        android:layout_height="@dimen/notification_panel_header_height"
+        />
+
+    <include
+        layout="@layout/keyguard_status_view"
+        android:layout_height="wrap_content"
+        android:visibility="gone" />
+
+    <TextView
+        android:id="@+id/emergency_calls_only"
+        android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:padding="4dp"
+        android:gravity="center"
+        android:visibility="gone"
+        />
+
+    <FrameLayout
+        android:id="@+id/notification_container_parent"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/close_handle_underlap"
-        android:orientation="vertical"
-        android:animateLayoutChanges="false"
         >
-
-        <include layout="@layout/status_bar_expanded_header"
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/notification_panel_header_height"
-            />
-
-        <TextView
-            android:id="@+id/emergency_calls_only"
-            android:textAppearance="@style/TextAppearance.StatusBar.Expanded.Network.EmergencyOnly"
-            android:layout_height="wrap_content"
-            android:layout_width="match_parent"
-            android:padding="4dp"
-            android:gravity="center"
-            android:visibility="gone"
-            />
-
-        <FrameLayout
-            android:id="@+id/notification_container_parent"
+        <include
+            layout="@layout/flip_settings"
+            android:layout_marginTop="@dimen/notification_panel_header_height"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            >
-            <ViewStub android:id="@+id/flip_settings_stub"
-                android:layout="@layout/flip_settings"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                />
+            />
 
-            <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
-                    android:id="@+id/notification_stack_scroller"
-                    android:layout_width="match_parent"
-                    android:layout_height="wrap_content"
-                    />
-        </FrameLayout>
-    </LinearLayout>
+        <com.android.systemui.statusbar.stack.NotificationStackScrollLayout
+            android:id="@+id/notification_stack_scroller"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            />
+    </FrameLayout>
+
+    <include
+        layout="@layout/keyguard_bottom_area"
+        android:visibility="gone" />
 </com.android.systemui.statusbar.phone.NotificationPanelView><!-- end of sliding panel -->
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 9aa7cfd..8975728 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -81,29 +81,11 @@
         android:src="@drawable/ic_notify_clear"
         android:background="@drawable/ic_notify_button_bg"
         android:contentDescription="@string/accessibility_clear_all"
-        />     
+        />
 
-    <FrameLayout android:id="@+id/settings_button_holder"
+    <include layout="@layout/status_bar_flip_button"
+        android:id="@+id/header_flipper"
         android:layout_width="50dp"
         android:layout_height="50dp"
-        android:layout_marginStart="12dp"
-        >
-        <ImageView android:id="@+id/settings_button"
-            android:layout_width="50dp"
-            android:layout_height="50dp"
-            android:scaleType="center"
-            android:src="@drawable/ic_notify_settings"
-            android:background="@drawable/ic_notify_button_bg"
-            android:contentDescription="@string/accessibility_desc_quick_settings"
-            />
-        <ImageView android:id="@+id/notification_button"
-            android:layout_width="50dp"
-            android:layout_height="50dp"
-            android:scaleType="center"
-            android:src="@drawable/ic_notifications"
-            android:background="@drawable/ic_notify_button_bg"
-            android:visibility="gone"
-            android:contentDescription="@string/accessibility_notifications_button"
-            />
-    </FrameLayout>
+        android:layout_marginStart="12dp" />
 </LinearLayout>
diff --git a/packages/SystemUI/res/layout/status_bar_flip_button.xml b/packages/SystemUI/res/layout/status_bar_flip_button.xml
new file mode 100644
index 0000000..b7dff8c
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_flip_button.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+        android:layout_width="50dp"
+        android:layout_height="50dp">
+    <ImageView android:id="@+id/settings_button"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:scaleType="center"
+        android:src="@drawable/ic_notify_settings"
+        android:background="@drawable/ic_notify_button_bg"
+        android:contentDescription="@string/accessibility_desc_quick_settings" />
+    <ImageView android:id="@+id/notification_button"
+        android:layout_width="50dp"
+        android:layout_height="50dp"
+        android:scaleType="center"
+        android:src="@drawable/ic_notifications"
+        android:background="@drawable/ic_notify_button_bg"
+        android:visibility="gone"
+        android:contentDescription="@string/accessibility_notifications_button" />
+</FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
new file mode 100644
index 0000000..2e08bff
--- /dev/null
+++ b/packages/SystemUI/res/layout/status_bar_notification_keyguard_overflow.xml
@@ -0,0 +1,44 @@
+<!--
+  ~ 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
+  -->
+
+<!-- Extends FrameLayout -->
+<com.android.systemui.statusbar.NotificationOverflowContainer
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="32dp"
+    android:focusable="true"
+    android:clickable="true"
+    >
+    <TextView
+        android:id="@+id/more_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_vertical"
+        android:gravity="center_horizontal"
+        android:textColor="@color/keyguard_overflow_content_color"
+        android:textAllCaps="true"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        />
+    <com.android.systemui.statusbar.NotificationOverflowIconsView
+        android:id="@+id/overflow_icons_view"
+        android:layout_gravity="end|center_vertical"
+        android:gravity="end"
+        android:paddingLeft="8dp"
+        android:paddingRight="8dp"
+        android:layout_width="120dp"
+        android:layout_height="wrap_content"
+        />
+</com.android.systemui.statusbar.NotificationOverflowContainer>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_row.xml b/packages/SystemUI/res/layout/status_bar_notification_row.xml
index e74e568..8959a5b 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_row.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_row.xml
@@ -2,17 +2,17 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
+    android:focusable="true"
+    android:clickable="true"
     >
 
-    <View
-        android:id="@+id/top_glow"
-        android:alpha="0"
-        android:visibility="invisible"
+    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expanded"
+       android:layout_width="match_parent"
+       android:layout_height="wrap_content" />
+
+    <com.android.systemui.statusbar.NotificationContentView android:id="@+id/expandedPublic"
         android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_divider_height"
-        android:layout_gravity="top|center_horizontal"
-        android:background="@drawable/top_divider_glow"
-        />
+        android:layout_height="wrap_content" />
 
     <Button
         android:id="@+id/veto"
@@ -25,34 +25,6 @@
         android:paddingStart="8dp"
         />
 
-    <com.android.systemui.statusbar.LatestItemView android:id="@+id/container"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_marginBottom="@dimen/notification_divider_height"
-        android:layout_marginTop="@dimen/notification_divider_height"
-        android:focusable="true"
-        android:clickable="true"
-        >
-
-        <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expanded"
-           android:layout_width="match_parent"
-           android:layout_height="wrap_content" />
-
-        <com.android.internal.widget.SizeAdaptiveLayout android:id="@+id/expandedPublic"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content" />
-    </com.android.systemui.statusbar.LatestItemView>
-
-    <View
-        android:id="@+id/bottom_glow"
-        android:alpha="0"
-        android:visibility="invisible"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/notification_divider_height"
-        android:layout_gravity="bottom|center_horizontal"
-        android:background="@drawable/bottom_divider_glow"
-        />
-
     <TextView
         android:id="@+id/debug_info"
         android:visibility="invisible"
diff --git a/packages/SystemUI/res/layout/super_status_bar.xml b/packages/SystemUI/res/layout/super_status_bar.xml
index 2b56618..61d43d7 100644
--- a/packages/SystemUI/res/layout/super_status_bar.xml
+++ b/packages/SystemUI/res/layout/super_status_bar.xml
@@ -20,32 +20,25 @@
 <!-- This is the combined status bar / notification panel window. -->
 <com.android.systemui.statusbar.phone.StatusBarWindowView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:systemui="http://schemas.android.com/apk/res/com.android.systemui"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
     android:focusable="true"
-    android:descendantFocusability="afterDescendants"
     android:fitsSystemWindows="true"
-    android:background="@android:color/transparent"
-    >
+    android:descendantFocusability="afterDescendants">
 
     <include layout="@layout/status_bar"
         android:layout_width="match_parent"
-        android:layout_height="@*android:dimen/status_bar_height"
-        />
+        android:layout_height="@dimen/status_bar_height" />
 
     <com.android.systemui.statusbar.phone.PanelHolder
         android:id="@+id/panel_holder"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        >
+        android:layout_marginTop="@dimen/panel_holder_padding_top">
         <include layout="@layout/status_bar_expanded"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            />
-        <ViewStub android:id="@+id/quick_settings_stub"
-            android:layout="@layout/quick_settings"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            />
+            android:layout_width="@dimen/notification_panel_width"
+            android:layout_height="wrap_content"
+            android:layout_gravity="start|top" />
     </com.android.systemui.statusbar.phone.PanelHolder>
 
 </com.android.systemui.statusbar.phone.StatusBarWindowView>
diff --git a/packages/SystemUI/res/layout/user_switcher_host.xml b/packages/SystemUI/res/layout/user_switcher_host.xml
new file mode 100644
index 0000000..bc56cf6
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_host.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  ~ 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
+  -->
+
+<!-- FrameLayout -->
+<com.android.systemui.settings.UserSwitcherHostView
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:background="#dd000000">
+    <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@*android:dimen/volume_panel_top"
+            android:background="@*android:drawable/dialog_full_holo_dark">
+        <ListView android:id="@android:id/list"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                tools:listitem="@layout/user_switcher_item"/>
+    </FrameLayout>
+</com.android.systemui.settings.UserSwitcherHostView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/user_switcher_item.xml b/packages/SystemUI/res/layout/user_switcher_item.xml
new file mode 100644
index 0000000..43a85e7
--- /dev/null
+++ b/packages/SystemUI/res/layout/user_switcher_item.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<LinearLayout
+        xmlns:android="http://schemas.android.com/apk/res/android"
+        xmlns:tools="http://schemas.android.com/tools"
+        android:layout_width="match_parent"
+        android:layout_height="64dp"
+        android:orientation="horizontal"
+        tools:context=".settings.UserSwitcherDialog">
+    <ImageView
+            android:layout_width="64dp"
+            android:layout_height="match_parent"
+            android:id="@+id/user_picture"
+            tools:src="@drawable/dessert_zombiegingerbread"/>
+    <TextView
+            android:layout_width="0dp"
+            android:layout_height="match_parent"
+            android:layout_weight="1"
+            android:id="@+id/user_name"
+            android:textAppearance="?android:attr/textAppearanceLarge"
+            android:padding="8dp"
+            android:gravity="center_vertical"
+            tools:text="Hiroshi Lockheimer"
+            />
+</LinearLayout>
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index 98d132a..d8a3114 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Verbeterde kontrasmodus"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Kleurregstellingmodus"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ONLANGS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programinligting"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"soek"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk word\ndalk gemonitor"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Soek"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Gly op vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Gly links vir <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Kennisgewing versteek"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d kennisgewings versteek"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak om te wys"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Moenie steur nie"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d meer"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tik weer om oop te maak"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Sleep op om te ontsluit"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index 2e116d0..9d1e036 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"የተሻሻለ ንፅፅር ሁነታ"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"የቀለም እርማት ሁነታ"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"የቅርብ ጊዜዎች"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"የመተግበሪያ መረጃ"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ፈልግ"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"አውታረ መረብ\nክትትል ሊደረግበት ይችላል"</string>
     <string name="description_target_search" msgid="3091587249776033139">"ፍለጋ"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ላይ አንሸራትት።"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"ለ<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ወደ ግራ አንሸራትት።"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ማሳወቂያ ተደብቋል"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ማሳወቂያዎች ተደብቀዋል"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"ለማሳየት ነካ ያድርጉ"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"አይረብሹ"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d ተጨማሪ"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"ለመክፈት ዳግም መታ ያድርጉ"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"ለማስከፈት ወደ ላይ ያንሸራትቱ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 596f612..22a032a 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"وضع التباين المحسن"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"وضع تصحيح الألوان"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"الأخيرة"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"معلومات التطبيق"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"بحث"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"قد تكون الشبكة\nخاضعة للرقابة"</string>
     <string name="description_target_search" msgid="3091587249776033139">"بحث"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"تمرير لأعلى لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"تمرير لليسار لـ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"تم إخفاء الإشعار"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏تم إخفاء %d من الإشعارات"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"المس للعرض"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"الرجاء عدم الإزعاج"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"‏%d أخرى"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"انقر مرة أخرى للفتح"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"مرر سريعًا لأعلى لإلغاء القفل"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index 335c33a..00ac707 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Режим на подобрен контраст"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Режим на коригиране на цветовете"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"СКОРОШНИ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информация за приложението"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"търсене"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежата може\nда се наблюдава"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Търсене"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Плъзнете нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Плъзнете наляво за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Известието е скрито"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d известия са скрити"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Докоснете за показване"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Не ме безпокойте"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Още %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Докоснете отново, за да отворите"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Прекарайте пръст нагоре, за да отключите"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index e79e094..bfad5bc 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mode de contrast millorat"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode de correcció de color"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informació de l\'aplicació"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"És possible que la xarxa\nestigui controlada"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Cerca"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Fes lliscar el dit cap amunt per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Fes lliscar el dit cap a l\'esquerra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificació oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificacions ocultes"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca per mostrar-ho."</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"No molesteu"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d més"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Torna a tocar per obrir-la."</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Fes lliscar el dit cap amunt per desbloquejar el teclat."</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index 60bbe3b..94ba5c7 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Režim zvýšeného kontrastu"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Režim korekce barev"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"POSLEDNÍ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informace o aplikaci"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"vyhledat"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Síť může být\nmonitorována"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Vyhledávání"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Přejeďte prstem nahoru: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Přejeďte prstem doleva: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Oznámení bylo skryto"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skrytá oznámení: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Oznámení zobrazíte kliknutím"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Nerušit"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Další: %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Oznámení otevřete opětovným klepnutím"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Zařízení odemknete přejetím prstem nahoru"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 86c1eb96..df442ab 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Tilstand for forbedret kontrast"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Farvekorrigeringstilstand"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"SENESTE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Oplysninger om applikationen"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"søg"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netværket kan\nvære overvåget"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Søgning"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Glid op for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Glid til venstre for at <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Underretningen er skjult"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d underretninger er skjult"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryk for at vise"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Vil ikke forstyrres"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d mere"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tryk igen for at åbne"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Stryg for at låse op"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index c8cb0a4..451476c 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -165,7 +165,7 @@
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Daten erneut aktivieren"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Keine Internetverbindung"</string>
     <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"WLAN verbunden"</string>
-    <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht"</string>
+    <string name="gps_notification_searching_text" msgid="8574247005642736060">"GPS wird gesucht..."</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Standort durch GPS festgelegt"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"Standortanfragen aktiv"</string>
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Alle Benachrichtigungen löschen"</string>
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Kontrastverbesserungsmodus"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Farbkorrekturmodus"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"Letzte"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-Info"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"Suche"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netzwerk wird\neventuell überwacht."</string>
     <string name="description_target_search" msgid="3091587249776033139">"Suche"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach oben schieben"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Zum <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> nach links schieben"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Benachrichtigung ausgeblendet"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d Benachrichtigungen ausgeblendet"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Zum Ansehen tippen"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Nicht stören"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d mehr"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Erneut tippen, um Benachrichtigung zu öffnen"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Zum Entsperren nach oben wischen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 79025b6..6dcffcf 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Λειτουργία βελτίωσης αντίθεσης"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Λειτουργία διόρθωσης χρώματος"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ΠΡΟΣΦΑΤΑ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Πληροφορίες εφαρμογής"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"αναζήτηση"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Το δίκτυο μπορεί\nνα παρακολουθείται"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Αναζήτηση"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Κύλιση προς τα επάνω για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Κύλιση προς τα αριστερά για <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Έγινε απόκρυψη της ειδοποίησης"</item>
+    <item quantity="other" msgid="7388721375827338153">"Έγινε απόκρυψη %d ειδοποιήσεων"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Αγγίξτε για εμφάνιση"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Μην ενοχλείτε"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d ακόμη"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Πατήστε ξανά για να ανοίξετε"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Σύρετε για να ξεκλειδώσετε"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 338c8ac..91a334a 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Enhanced contrast mode"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Colour correction mode"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Search"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Do not disturb"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d more"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 338c8ac..91a334a 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Enhanced contrast mode"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Colour correction mode"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Application Info"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"search"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Network may\nbe monitored"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Search"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slide up for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slide left for <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification hidden"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications hidden"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touch to show"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Do not disturb"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d more"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tap again to open"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Swipe up to unlock"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 89fe58b..2150cbe 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modo de contraste mejorado"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modo de corrección de color"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Es posible que la red\nesté supervisada."</string>
     <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificación oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"No molestar"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d más"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Presionar de nuevo para abrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar el dedo hacia arriba para desbloquear"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index f2a9850..3424166 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modo de contraste mejorado"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modo de corrección de color"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECIENTES"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Información de la aplicación"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"buscar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La red se\npuede supervisar"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Buscar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Desliza el dedo hacia arriba para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Desliza el dedo hacia la izquierda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificaciones ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toca para mostrar"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"No molestar"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d más"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Toca de nuevo para abrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Desliza el dedo hacia arriba para desbloquear"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et-rEE/strings.xml b/packages/SystemUI/res/values-et-rEE/strings.xml
index b734fa8..8dbf9af 100644
--- a/packages/SystemUI/res/values-et-rEE/strings.xml
+++ b/packages/SystemUI/res/values-et-rEE/strings.xml
@@ -205,8 +205,19 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Täiustatud kontrasti režiim"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Värviparandusrežiim"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"HILJUTISED"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Rakenduste teave"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"otsing"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Võrku võidakse\njälgida"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Otsing"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Lohistage üles: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Lohistage vasakule: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+    <!-- String.format failed for translation -->
+    <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Puudutage kuvamiseks"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Mitte segada"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Veel %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Avamiseks puudutage uuesti"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Lukustuse tühistamiseks pühkige üles"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index 5780a57..b2ac990 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"حالت کنتراست بهبودیافته"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"حالت تصحیح رنگ"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"موارد اخیر"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"اطلاعات برنامه"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"جستجو"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ممکن است شبکه\nتحت نظارت باشد"</string>
     <string name="description_target_search" msgid="3091587249776033139">"جستجو"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"لغزاندن به بالا برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"لغزاندن به چپ برای <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"اعلان پنهان شده"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏%d اعلان پنهان شده"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"برای نمایش لمس کنید"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"مزاحم نشوید"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"‏%d بیشتر"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"برای باز کردن دوباره ضربه بزنید"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"برای باز کردن قفل سریع به بالا بکشید"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index 4809741..af0df4d 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -38,7 +38,7 @@
     <string name="invalid_charger" msgid="4549105996740522523">"USB-latausta ei tueta.\nKäytä laitteen mukana tullutta laturia."</string>
     <string name="battery_low_why" msgid="7279169609518386372">"Akun käyttö"</string>
     <string name="status_bar_settings_settings_button" msgid="3023889916699270224">"Asetukset"</string>
-    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wifi"</string>
+    <string name="status_bar_settings_wifi_button" msgid="1733928151698311923">"Wi-Fi"</string>
     <string name="status_bar_settings_airplane" msgid="4879879698500955300">"Lentokonetila"</string>
     <string name="status_bar_settings_auto_rotation" msgid="3790482541357798421">"Kierrä näyttöä automaattisesti"</string>
     <string name="status_bar_settings_mute_label" msgid="554682549917429396">"ÄÄNET."</string>
@@ -98,11 +98,11 @@
     <string name="accessibility_data_two_bars" msgid="6166018492360432091">"Datasignaali - kaksi palkkia."</string>
     <string name="accessibility_data_three_bars" msgid="9167670452395038520">"Datasignaali - kolme palkkia"</string>
     <string name="accessibility_data_signal_full" msgid="2708384608124519369">"Vahva kuuluvuus."</string>
-    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wifi pois käytöstä."</string>
+    <string name="accessibility_wifi_off" msgid="3177380296697933627">"Wi-Fi pois käytöstä."</string>
     <string name="accessibility_no_wifi" msgid="1425476551827924474">"Ei wifi-yhteyttä."</string>
-    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wifi-signaali – yksi palkki."</string>
-    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wifi-signaali – kaksi palkkia."</string>
-    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wifi-signaali – kolme palkkia."</string>
+    <string name="accessibility_wifi_one_bar" msgid="7735893178010724377">"Wi-Fi-signaali – yksi palkki."</string>
+    <string name="accessibility_wifi_two_bars" msgid="4994274250497262434">"Wi-Fi-signaali – kaksi palkkia."</string>
+    <string name="accessibility_wifi_three_bars" msgid="3495755044276588384">"Wi-Fi-signaali – kolme palkkia."</string>
     <string name="accessibility_wifi_signal_full" msgid="6853561303586480376">"Vahva wifi-signaali."</string>
     <string name="accessibility_no_wimax" msgid="4329180129727630368">"Ei WiMAX-yhteyttä."</string>
     <string name="accessibility_wimax_one_bar" msgid="4170994299011863648">"WiMAX: yksi palkki."</string>
@@ -129,7 +129,7 @@
     <string name="accessibility_data_connection_cdma" msgid="6132648193978823023">"CDMA"</string>
     <string name="accessibility_data_connection_roaming" msgid="5977362333466556094">"Roaming"</string>
     <string name="accessibility_data_connection_edge" msgid="4477457051631979278">"Edge"</string>
-    <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wifi"</string>
+    <string name="accessibility_data_connection_wifi" msgid="2324496756590645221">"Wi-Fi"</string>
     <string name="accessibility_no_sim" msgid="8274017118472455155">"Ei SIM-korttia."</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Internetyhteyden jakaminen Bluetoothin kautta."</string>
     <string name="accessibility_airplane_mode" msgid="834748999790763092">"Lentokonetila."</string>
@@ -162,7 +162,7 @@
     <string name="data_usage_disabled_dialog" msgid="3853117269051806280">"Tiedonsiirtoraja saavutettu.\n\nJos otat tiedonsiirron uudelleen käyttöön, operaattorisi voi veloittaa sinua."</string>
     <string name="data_usage_disabled_dialog_enable" msgid="7729772039208664606">"Ota tiedonsiirto käyttöön"</string>
     <string name="status_bar_settings_signal_meter_disconnected" msgid="1940231521274147771">"Ei internetyhteyttä"</string>
-    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wifi yhdistetty"</string>
+    <string name="status_bar_settings_signal_meter_wifi_nossid" msgid="6557486452774597820">"Wi-Fi yhdistetty"</string>
     <string name="gps_notification_searching_text" msgid="8574247005642736060">"Haetaan GPS-yhteyttä"</string>
     <string name="gps_notification_found_text" msgid="4619274244146446464">"Sijainti määritetty GPS:n avulla"</string>
     <string name="accessibility_location_active" msgid="2427290146138169014">"Sijaintipyynnöt aktiiviset"</string>
@@ -194,10 +194,10 @@
     <string name="quick_settings_settings_label" msgid="5326556592578065401">"Asetukset"</string>
     <string name="quick_settings_time_label" msgid="4635969182239736408">"Aika"</string>
     <string name="quick_settings_user_label" msgid="5238995632130897840">"Minä"</string>
-    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wifi"</string>
+    <string name="quick_settings_wifi_label" msgid="9135344704899546041">"Wi-Fi"</string>
     <string name="quick_settings_wifi_not_connected" msgid="7171904845345573431">"Ei yhteyttä"</string>
     <string name="quick_settings_wifi_no_network" msgid="2221993077220856376">"Ei verkkoa"</string>
-    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wifi-yhteys pois käytöstä"</string>
+    <string name="quick_settings_wifi_off_label" msgid="7558778100843885864">"Wi-Fi-yhteys pois käytöstä"</string>
     <string name="quick_settings_remote_display_no_connection_label" msgid="372107699274391290">"Lähetysnäyttö"</string>
     <string name="quick_settings_brightness_dialog_title" msgid="8599674057673605368">"Kirkkaus"</string>
     <string name="quick_settings_brightness_dialog_auto_brightness_label" msgid="5064982743784071218">"AUTO"</string>
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Kontrastinparannustila"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Värinkorjaustila"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"VIIMEISIMMÄT"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Sovellustiedot"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"haku"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Verkkoa saatetaan\nvalvoa"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Haku"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Liu\'uta ylös ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Liu\'uta vasemmalle ja <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Ilmoitus piilotettu"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ilmoitusta piilotettu"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Näytä koskettamalla"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Älä häiritse"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d muuta"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Avaa napauttamalla uudelleen"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Avaa lukitus pyyhkäisemällä ylös"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 36b54ce..f01c99a 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mode d\'accentuation du contraste"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode de correction des couleurs"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Détails de l\'application"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
     <string name="description_target_search" msgid="3091587249776033139">"Recherche"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Faire glisser le doigt vers le haut : <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser votre doigt vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Touchez pour afficher la notification"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ne pas déranger"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d autres"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Touchez à nouveau pour ouvrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Glissez vers le haut pour déverrouiller"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index 5b81975..5efbd2f 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mode d\'accentuation du contraste"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode de correction des couleurs"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RÉCENTS"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informations sur l\'application"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"rechercher"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Le réseau peut\nêtre surveillé."</string>
     <string name="description_target_search" msgid="3091587249776033139">"Rechercher"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Faites glisser vers le haut pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Faites glisser vers la gauche pour <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notification masquée"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifications masquées"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Appuyer pour afficher"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ne pas déranger"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"+ %d autres"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Appuyer à nouveau pour ouvrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Faire glisser pour déverrouiller"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 9be9550..e6d38ef 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"उन्नत कंट्रास्ट मोड"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"रंग सुधार मोड"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"हाल ही का"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"एप्‍लिकेशन जानकारी"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"खोज"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"नेटवर्क को\nमॉनीटर किया जा सकता है"</string>
     <string name="description_target_search" msgid="3091587249776033139">"खोजें"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए ऊपर स्‍लाइड करें."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> के लिए बाएं स्‍लाइड करें."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"सूचना छिपी हुई है"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d सूचनाएं छिपी हुई हैं"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"दिखाने के लिए स्पर्श करें"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"परेशान न करें"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d और"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"खोलने के लिए पुन: टैप करें"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"अनलॉक करने के लिए ऊपर स्वाइप करें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 21d6ef5..b777b8f 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Način pojačanog kontrasta"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Način korekcije boje"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNO"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacije o aplikaciji"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"pretraži"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mreža se\nmožda prati"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Pretraživanje"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Kliznite prema gore za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Kliznite lijevo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Obavijest je skrivena"</item>
+    <item quantity="other" msgid="7388721375827338153">"Broj skrivenih obavijesti: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dodirnite za prikaz"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ne ometaj"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Još %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Dodirnite opet za otvaranje"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Prijeđite prstom prema gore za otključavanje"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index 8e6ee4f..10732fe 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Kontrasztjavítás mód"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Színjavítás mód"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"LEGUTÓBBIAK"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Az alkalmazás adatai"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"keresés"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Lehet, hogy a\nhálózat felügyelt"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Keresés"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa felfelé."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"A(z) <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> művelethez csúsztassa balra."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Értesítés elrejtve"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d értesítés elrejtve"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"A megtekintéshez érintse meg"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ne zavarjanak"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d további"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Koppintson rá ismét a megnyitáshoz"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Húzza felfelé az ujját a feloldáshoz"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index a787983..f1c4869 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Ընդլայնված ցայտունության ռեժիմ"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Գույների կարգավորման ռեժիմ"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ՎԵՐՋԻՆՆԵՐԸ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Հավելվածի մասին"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"որոնել"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ցանցը կարող է\nվերահսկվել"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Որոնել"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Սահեցրեք վերև <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Սահեցրեք ձախ` <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-ի համար:"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Ծանուցումը թաքցված է"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d ծանուցում թաքցված է"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Հպեք՝ ցուցադրելու համար"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Չխանգարել"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Եվս %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Կրկին հպեք՝ բացելու համար"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Սահեցրեք վերև` ապակողպելու համար"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 13fc534..f0b0713 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mode kontras yang disempurnakan"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode koreksi warna"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"TERBARU"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Info Aplikasi"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"telusuri"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Jaringan bisa\ndiawasi"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Telusuri"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Geser ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Geser ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menampilkan"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Jangan ganggu"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d lainnya"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Ketuk lagi untuk membuka"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Gesek ke atas untuk membuka kunci"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 289d6c6..6a57682 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modalità di contrasto avanzata"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modalità di correzione del colore"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"MESSAGGI RECENTI"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informazioni sull\'applicazione"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"cerca"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"La rete potrebbe\nessere monitorata"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Ricerca"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Su per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"A sinistra per <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notifica nascosta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notifiche nascoste"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tocca per visualizzare"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Non disturbare"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Altre %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tocca ancora per aprire"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Scorri verso l\'alto per sbloccare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 798e8c3..3e87b76 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"מצב ניגודיות מוגברת"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"מצב תיקון צבע"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"אחרונים"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"מידע על האפליקציה"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"חפש"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ייתכן שהרשת\nמנוטרת"</string>
     <string name="description_target_search" msgid="3091587249776033139">"חיפוש"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"הסט למעלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"הסט שמאלה כדי להציג <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ההודעה הוסתרה"</item>
+    <item quantity="other" msgid="7388721375827338153">"‏%d הודעות הוסתרו"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"גע כדי להציג"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"נא לא להפריע"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"‏עוד %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"הקש שוב כדי לפתוח"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"החלק מעלה כדי לבטל את הנעילה"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index c5070a8..1edb630 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"拡張コントラストモード"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"色補正モード"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"アプリ情報"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"検索"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ネットワークが監視される\n場合があります"</string>
     <string name="description_target_search" msgid="3091587249776033139">"検索します"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"上にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"左にスライドして<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>を行います。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"通知が非表示"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d件の通知が非表示"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"表示するにはタップします"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"通知を非表示"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"他%d件"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"開くにはもう一度タップしてください"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"ロック解除するには上にスワイプしてください"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka-rGE/strings.xml b/packages/SystemUI/res/values-ka-rGE/strings.xml
index bbdce19..9d4344a 100644
--- a/packages/SystemUI/res/values-ka-rGE/strings.xml
+++ b/packages/SystemUI/res/values-ka-rGE/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"გაუმჯობესებული კონტრასტის რეჟიმი"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"ფერთა კორექციის რეჟიმი"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ბოლო დროის"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"აპლიკაციის შესახებ"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ძიება"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"შესაძლოა ქსელზე\nმონიტორინგი ხორციელდებოდეს"</string>
     <string name="description_target_search" msgid="3091587249776033139">"ძიება"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"გაასრიალეთ ზემოთ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"გაასრიალეთ მარცხნივ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-თვის."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"შეტყობინება დამალულია"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d შეტყობინება დამალულია"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"შეეხეთ საჩვენებლად"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"არ შემაწუხოთ"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d სხვა"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"შეეხეთ ისევ გასახსნელად"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"გაასრიალეთ ზევით განსაბლოკად"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km-rKH/strings.xml b/packages/SystemUI/res/values-km-rKH/strings.xml
index 61ca77d..bb2d3b9 100644
--- a/packages/SystemUI/res/values-km-rKH/strings.xml
+++ b/packages/SystemUI/res/values-km-rKH/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"របៀប​កម្រិត​ពណ៌​ប្រ​សើ​រ​ឡើង"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"របៀប​កែ​ពណ៌"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ថ្មីៗ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"ព័ត៌មាន​កម្មវិធី"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ស្វែងរក"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"បណ្ដាញ​អាច​\nត្រូវ​បាន​ត្រួតពិនិត្យ"</string>
     <string name="description_target_search" msgid="3091587249776033139">"ស្វែងរក"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"រុញ​ឡើង​លើ​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"រុញ​ទៅ​ឆ្វេង​ដើម្បី <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ។"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"បាន​លាក់​ការ​ជូនដំណឹង"</item>
+    <item quantity="other" msgid="7388721375827338153">"បាន​លាក់ការ​ជូនដំណឹង %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"ប៉ះ​ដើម្បី​បង្ហាញ"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"កុំ​រំខាន"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d ទៀត"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"ប៉ះ​ម្ដង​ទៀត ដើម្បី​បើក"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"អូស​ឡើង​លើ ដើម្បី​ដោះ​សោ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 8108daa..83ffa9f 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"향상된 대비 모드"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"색상 보정 모드"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"최근"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"애플리케이션 정보"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"검색"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"네트워크가\n모니터링될 수 있음"</string>
     <string name="description_target_search" msgid="3091587249776033139">"검색"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 위로 슬라이드"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>하려면 왼쪽으로 슬라이드"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"알림 숨김"</item>
+    <item quantity="other" msgid="7388721375827338153">"알림 %d개 숨김"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"표시하려면 터치"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"알림 일시중지"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d개 더보기"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"다시 탭하여 열기"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"위로 스와이프하여 잠금 해제"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/config.xml b/packages/SystemUI/res/values-land/config.xml
index 6476d88..7223773 100644
--- a/packages/SystemUI/res/values-land/config.xml
+++ b/packages/SystemUI/res/values-land/config.xml
@@ -27,6 +27,9 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">6</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">2</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">2</integer>
 </resources>
diff --git a/packages/SystemUI/res/values-lo-rLA/strings.xml b/packages/SystemUI/res/values-lo-rLA/strings.xml
index c2e5990..9a3d483 100644
--- a/packages/SystemUI/res/values-lo-rLA/strings.xml
+++ b/packages/SystemUI/res/values-lo-rLA/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"ໂໝດຄວາມຕ່າງແສງ"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"ໂໝດການແກ້ໄຂສີ"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ບໍ່​ດົນ​ມາ​ນີ້"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"​ຂໍ້​ມູນ​ແອັບ​ພ​ລິ​ເຄ​ຊັນ"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ຊອກຫາ"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"ເຄືອຄ່າຍອາດ\nຖືກຕິດຕາມ"</string>
     <string name="description_target_search" msgid="3091587249776033139">"ຊອກຫາ"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"ເລື່ອນຂຶ້ນເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"ເລື່ອນໄປທາງຊ້າຍເພື່ອ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ເຊື່ອງ​ການ​ແຈ້ງ​ເຕ​ືອນ​ແລ້ວ"</item>
+    <item quantity="other" msgid="7388721375827338153">"ເຊື່ອງ %d ການ​ແຈ້ງ​ເຕືອນ​ແລ້ວ"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"​ແຕະ​ເພື່ອ​ສະ​ແດງ"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"ຫ້າມລົບກວນ"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d ເພີ່ມ​ເຕີມ"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"ແຕະ​ອີກ​ຄັ້ງ​ເພື່ອ​ເປີດ"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"ເລື່ອນ​ຂຶ້ນ​ເພື່ອ​ປົດ​ລັອກ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 1d8b051..379cfce 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -69,7 +69,7 @@
     <string name="screenshot_failed_title" msgid="705781116746922771">"Nepavyko užfiksuoti ekrano kopijos."</string>
     <string name="screenshot_failed_text" msgid="8134011269572415402">"Nepavyko išsaugoti ekrano kopijos. Gali būti naudojama atmintis."</string>
     <string name="usb_preference_title" msgid="6551050377388882787">"USB failo perdavimo parinktys"</string>
-    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvą (MTP)"</string>
+    <string name="use_mtp_button_title" msgid="4333504413563023626">"Įmontuoti kaip medijos leistuvę (MTP)"</string>
     <string name="use_ptp_button_title" msgid="7517127540301625751">"Įmontuoti kaip fotoaparatą (PTP)"</string>
     <string name="installer_cd_button_title" msgid="2312667578562201583">"Įdiegti „Mac“ skirtą „Android“ perkėl. priem. pr."</string>
     <string name="accessibility_back" msgid="567011538994429120">"Atgal"</string>
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Patobulinto kontrasto režimas"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Spalvų taisymo režimas"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"PASTARIEJI"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Programos informacija"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"paieška"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tinklas gali\nbūti stebimas"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Paieška"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Slyskite aukštyn link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Slyskite į kairę link <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pranešimas paslėptas"</item>
+    <item quantity="other" msgid="7388721375827338153">"Paslėpta pranešimų: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Palieskite, kad būtų rodoma"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Netrukdyti"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Dar %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Palieskite dar kartą, kad atidarytumėte"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Perbraukite aukštyn, kad atrakintumėte"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index 603fa1a..ca07095 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Uzlabota kontrasta režīms"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Krāsu korekcijas režīms"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"JAUNĀKIE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informācija par lietojumprogrammu"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"Meklēt"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Tīkls var\ntikt uzraudzīts"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Meklēt"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Velciet uz augšu, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Velciet pa kreisi, lai veiktu šādu darbību: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Paziņojums paslēpts"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d paziņojumi paslēpti"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pieskarieties, lai rādītu"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Netraucēt"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"vēl %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Pieskarieties vēlreiz, lai atvērtu"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Velciet uz augšu, lai atbloķētu"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn-rMN/strings.xml b/packages/SystemUI/res/values-mn-rMN/strings.xml
index 110cfd2..4545301 100644
--- a/packages/SystemUI/res/values-mn-rMN/strings.xml
+++ b/packages/SystemUI/res/values-mn-rMN/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Сайжруулсан ялгаралтай горим"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Өнгө залруулах горим"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"СҮҮЛИЙН"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Аппликешны мэдээлэл"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"хайх"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Сүлжээ хянагдаж\nбайж болзошгүй"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Хайх"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>-г гулсуулах."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> хийх зүүнлүү гулсуулах."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Мэдэгдлийг нуусан"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d мэдэгдлийг нуусан"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Харуулах бол хүрнэ үү"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Бүү саад бол"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"өөр %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Нээхийн тулд дахин товшино уу"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Түгжээг тайлах бол шудрана уу"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms-rMY/strings.xml b/packages/SystemUI/res/values-ms-rMY/strings.xml
index 62c90ab..587b84f 100644
--- a/packages/SystemUI/res/values-ms-rMY/strings.xml
+++ b/packages/SystemUI/res/values-ms-rMY/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mod kontras dipertingkat"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mod pembetulan warna"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"TERBAHARU"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maklumat Aplikasi"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"cari"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rangkaian mungkin\nboleh dipantau"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Carian"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Luncurkan ke atas untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Luncurkan ke kiri untuk <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Pemberitahuan disembunyikan"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d pemberitahuan disembunyikan"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Sentuh untuk menunjukkan"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Jangan ganggu"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d lagi"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Ketik lagi untuk membuka"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Leret ke atas untuk membuka kunci"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index 0e914ea..001e733 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Forbedret kontrastmodus"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modus for fargekorrigering"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"NYLIGE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformasjon"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"Søk"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nettverket kan\nvære overvåket"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Søk"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Dra opp for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Dra til venstre for å <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Varselet er skjult"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d varsler er skjult"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Trykk for å vise"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ikke forstyrr"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d til"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Trykk på nytt for å åpne"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Sveip oppover for å låse opp"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index 032fa34..8a6e33b 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modus voor verbeterd contrast"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modus voor kleurcorrectie"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"App-informatie"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"zoeken"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Netwerk kan\nworden gecontroleerd"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Zoeken"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Veeg omhoog voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Veeg naar links voor <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Melding verborgen"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d meldingen verborgen"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Raak aan om weer te geven"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Niet storen"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Nog %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tik nogmaals om te openen"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Veeg omhoog om te ontgrendelen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index c21230c..4862d1b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Tryb zwiększonego kontrastu"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Tryb korekcji kolorów"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"OSTATNIE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informacje o aplikacji"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"szukaj"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieć może być\nmonitorowana"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Szukaj"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Przesuń w górę: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Przesuń w lewo: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Powiadomienie ukryte"</item>
+    <item quantity="other" msgid="7388721375827338153">"Ukryte powiadomienia: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotknij, by zobaczyć"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Nie przeszkadzać"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d więcej"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Kliknij ponownie, by otworzyć"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Przesuń w górę, by odblokować"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 771daf2..012283a 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modo de contraste melhorado"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modo de correção de cor"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações da aplicação"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode ser\nmonitorizada"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Deslize para cima para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Deslize para a esquerda para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Não incomodar"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Mais %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Deslizar rapidamente com o dedo para cima para desbloquear"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index b643bae..0978d18 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Modo de contraste aprimorado"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Modo de correção de cor"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTES"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informações do aplicativo"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"pesquisar"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"A rede pode estar\nsob monitoração"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Pesquisar"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para cima."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Para <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>, deslize para a esquerda."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificação oculta"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d notificações ocultas"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Toque para mostrar"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Não perturbe"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Mais %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Toque novamente para abrir"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Deslize para cima para desbloquear"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-rm/strings.xml b/packages/SystemUI/res/values-rm/strings.xml
index 33cb355..25f643f 100644
--- a/packages/SystemUI/res/values-rm/strings.xml
+++ b/packages/SystemUI/res/values-rm/strings.xml
@@ -380,6 +380,10 @@
     <skip />
     <!-- no translation found for recents_empty_message (2269156590813544104) -->
     <skip />
+    <!-- no translation found for recents_app_info_button_label (2890317189376000030) -->
+    <skip />
+    <!-- no translation found for recents_search_bar_label (8074997400187836677) -->
+    <skip />
     <!-- no translation found for ssl_ca_cert_warning (9005954106902053641) -->
     <skip />
     <!-- no translation found for description_target_search (3091587249776033139) -->
@@ -388,4 +392,15 @@
     <skip />
     <!-- no translation found for description_direction_left (7207478719805562165) -->
     <skip />
+    <!-- no translation found for zen_mode_notification_title:one (7809876956258040354) -->
+    <!-- no translation found for zen_mode_notification_title:other (7388721375827338153) -->
+    <!-- no translation found for zen_mode_notification_text (8336623711388065713) -->
+    <skip />
+    <!-- no translation found for zen_mode_title (8793432092004749188) -->
+    <skip />
+    <!-- no translation found for keyguard_more_overflow_text:other (9180696159506883684) -->
+    <!-- no translation found for notification_tap_again (7590196980943943842) -->
+    <skip />
+    <!-- no translation found for keyguard_unlock (8043466894212841998) -->
+    <skip />
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 87f9c0c..5c9764a 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mod contrast îmbunătățit"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mod de corectare a culorilor"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"RECENTE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informații despre aplicație"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"căutare"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Rețeaua poate\nfi monitorizată"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Căutaţi"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Glisaţi în sus pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Glisaţi spre stânga pentru <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Notificare ascunsă"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d de notificări ascunse"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Atingeți pentru a afișa"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Nu deranjaţi"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Încă %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Atingeți din nou pentru a deschide"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Glisați în sus pentru a debloca"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index e79a0dd..976a793 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -178,9 +178,7 @@
     <string name="ethernet_label" msgid="7967563676324087464">"Ethernet"</string>
     <string name="quick_settings_airplane_mode_label" msgid="5510520633448831350">"Режим полета"</string>
     <string name="quick_settings_battery_charging_label" msgid="490074774465309209">"<xliff:g id="NUMBER">%d</xliff:g><xliff:g id="PERCENT">%%</xliff:g>"</string>
-    <!-- String.format failed for translation -->
-    <!-- no translation found for quick_settings_battery_charged_label (8865413079414246081) -->
-    <skip />
+    <string name="quick_settings_battery_charged_label" msgid="8865413079414246081">"100%%"</string>
     <string name="quick_settings_bluetooth_label" msgid="6304190285170721401">"Bluetooth"</string>
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="3912245565613684735">"Bluetooth (<xliff:g id="NUMBER">%d</xliff:g>)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="8159652146149219937">"Bluetooth выкл."</string>
@@ -209,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Контрастность"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Коррекция цвета"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"НЕДАВНИЕ СООБЩЕНИЯ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Сведения о приложении"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"поиск"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Действия в сети\nмогут отслеживаться"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Поиск"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведите вверх, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведите влево, чтобы <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Оповещение скрыто"</item>
+    <item quantity="other" msgid="7388721375827338153">"Скрыто оповещений: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Нажмите, чтобы открыть"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Не беспокоить"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Ещё %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Нажмите ещё раз, чтобы открыть"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Для разблокировки проведите пальцем по экрану"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index d39c8bd..1224c3a 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Režim zvýšeného kontrastu"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Režim korekcie farieb"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"NEDÁVNE"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Informácie o aplikácii"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"hľadať"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Sieť môže byť\nmonitorovaná"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Vyhľadávanie"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Prejdite prstom nahor: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Prejdite prstom doľava: <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Upozornenie bolo skryté"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skryté upozornenia: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Upozornenie zobrazíte dotykom"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Nerušiť"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d ďalších"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Upozornenie otvoríte opätovným klepnutím"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Zariadenie odomknete prejdením prstom nahor"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index 9d57586..10011bc 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Način izboljšanega kontrasta"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Način popravljanja barv"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"NEDAVNI"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Podatki o aplikaciji"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"iskanje"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Omrežje je\nlahko spremljano"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Iskanje"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Povlecite navzgor za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Povlecite v levo za <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Obvestilo je skrito"</item>
+    <item quantity="other" msgid="7388721375827338153">"Skritih je toliko obvestil: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Dotaknite se za prikaz"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ne moti"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"še %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Znova se dotaknite, da odprete"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Povlecite, da odklenete"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 89bc3c5..0c6a939 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Режим унапређеног контраста"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Режим корекције боје"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"НАЈНОВИЈЕ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Информације о апликацији"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"претражи"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мрежа се можда\nнадгледа"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Претрага"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Превуците нагоре за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Превуците улево за <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Обавештење је сакривено"</item>
+    <item quantity="other" msgid="7388721375827338153">"Сакривена обавештења: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Додирните за приказ"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Не узнемиравај"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Још %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Додирните поново да бисте отворили"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Превуците нагоре да бисте откључали"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index 1b47be5..d8bd1b1 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Kontrastförbättringsläge"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Färgkorrigeringsläge"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"NYA"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Appinformation"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"sök"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Nätverket kan\nvara övervakat"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Sök"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Dra uppåt för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Dra åt vänster för <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Aviseringen har dolts"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d aviseringar har dolts"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Tryck här om du vill visa aviseringar"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Stör ej"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d till"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Tryck igen för att öppna"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Dra uppåt om du vill låsa upp"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 3702196..d308b518 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -203,8 +203,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Hali ya utofautishaji ulioboreshwa"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Hali ya kusahihisha rangi"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"YA HIVI KARIBUNI"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Maelezo ya Programu"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"tafuta"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Huenda mtandao\nunafuatiliwa"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Tafuta"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Sogeza juu kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Sogeza kushoto kwa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> ."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Arifa imefichwa"</item>
+    <item quantity="other" msgid="7388721375827338153">"Arifa %d zimefichwa"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Gusa ili zionekane"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Usisumbue"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d zaidi"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Gonga tena ili ufungue"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Telezesha kidole ili ufungue"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/config.xml b/packages/SystemUI/res/values-sw600dp/config.xml
index b77f1e0..fe2224e 100644
--- a/packages/SystemUI/res/values-sw600dp/config.xml
+++ b/packages/SystemUI/res/values-sw600dp/config.xml
@@ -20,15 +20,12 @@
 <!-- These resources are around just to allow their values to be customized
      for different hardware and product builds. -->
 <resources>
-    <!-- Enable quick settings on tablets -->
-    <bool name="config_hasSettingsPanel">true</bool>
-
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">4</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
-
-    <!-- Enable the "flip settings" panel -->
-    <bool name="config_hasFlipSettingsPanel">false</bool>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 45f6af3..5b5587d 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -23,10 +23,9 @@
     <dimen name="notification_panel_margin_bottom">192dp</dimen>
     <dimen name="notification_panel_margin_left">16dp</dimen>
 
-    <!-- Gravity for the notification & quick settings panels -->
-    <!-- 0x800033 = start|top ; 0x800035 = end|top -->
-    <integer name="notification_panel_layout_gravity">0x800033</integer>
-    <integer name="settings_panel_layout_gravity">0x800035</integer>
+    <!-- Gravity for the notification panel -->
+    <!-- 0x31 = top|center_horizontal -->
+    <integer name="notification_panel_layout_gravity">0x31</integer>
 
     <!-- Diameter of outer shape drawable shown in navbar search-->
     <dimen name="navbar_search_outerring_diameter">430dip</dimen>
@@ -41,9 +40,8 @@
     <dimen name="status_bar_recents_thumbnail_width">200dp</dimen>
     <dimen name="status_bar_recents_thumbnail_height">177dp</dimen>
 
-    <!-- On tablet-sized devices, we allocate the rightmost third(ish) of the draggable status bar
-         to quick settings. -->
-    <item type="dimen" name="settings_panel_dragzone_fraction">35%</item>
+    <!-- On tablets, panels drop from the statusbar instead of overlapping it. -->
+    <dimen name="panel_holder_padding_top">@*android:dimen/status_bar_height</dimen>
 
     <!-- Minimum fraction of the screen that should be taken up by the notification panel. -->
     <item type="dimen" name="notification_panel_min_height_frac">40%</item>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index 0188563..7929a30 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"โหมดคอนทราสต์ที่ปรับปรุงแล้ว"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"โหมดการแก้ไขสี"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ล่าสุด"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"ข้อมูลแอปพลิเคชัน"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ค้นหา"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"เครือข่ายอาจ\nถูกตรวจสอบ"</string>
     <string name="description_target_search" msgid="3091587249776033139">"ค้นหา"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"เลื่อนขึ้นเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"เลื่อนไปทางซ้ายเพื่อ <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"ซ่อนการแจ้งเตือนแล้ว"</item>
+    <item quantity="other" msgid="7388721375827338153">"ซ่อน %d การแจ้งเตือนแล้ว"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"แตะเพื่อแสดง"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"ห้ามรบกวน"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"อีก %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"แตะอีกครั้งเพื่อเปิด"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"กวาดขึ้นเพื่อปลดล็อก"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index d7502cb..92473a4 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Mode na dinagdagan ang contrast"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Mode ng pagtatama ng kulay"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"MGA KAMAKAILAN"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Impormasyon ng Application"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"maghanap"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Maaaring\nsinusubaybayan ang network"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Maghanap"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Mag-slide pataas para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Mag-slide pakaliwa para sa <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Nakatago ang notification"</item>
+    <item quantity="other" msgid="7388721375827338153">"Nakatago ang %d (na) notification"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Pindutin upang ipakita"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Huwag istorbohin"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d pa"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"I-tap ulit upang buksan"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Mag-swipe pataas upang i-unlock"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index f56293b..9837ff8 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Geliştirilmiş kontrast modu"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Renk düzeltme modu"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"SON İLETİLER"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Uygulama Bilgileri"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"ara"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Ağ izleniyor\nolabilir"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Ara"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için yukarı kaydırın."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g> için sola kaydırın."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Bildirim gizli"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d bildirim gizli"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Görüntülemek için dokunun"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Rahatsız etmeyin"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d adet daha"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Açmak için tekrar hafifçe vurun"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Kilidi açmak için hızlıca yukarı kaydırın"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index df94b26..534f520 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Режим посиленого контрасту"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Режим коригування кольору"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"ОСТАННІ"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Інформація про додаток"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"пошук"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Мережа може\nвідстежуватися"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Пошук"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Проведіть пальцем угору, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Проведіть пальцем ліворуч, щоб <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Сповіщення сховано"</item>
+    <item quantity="other" msgid="7388721375827338153">"Сховано сповіщень: %d"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Торкніться, щоб показати"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Не турбувати"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"Ще %d"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Торкніться знову, щоб відкрити"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Проведіть пальцем угору, щоб розблокувати"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 471cbd3..56fc89c 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Chế độ tương phản tăng cường"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Chế độ hiệu chỉnh màu sắc"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"GẦN ĐÂY"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Thông tin ứng dụng"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"tìm kiếm"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Mạng có thể\nđược giám sát"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Tìm kiếm"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Trượt lên để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Trượt sang trái để <xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Thông báo ẩn"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d thông báo ẩn"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Chạm để hiển thị"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Không làm phiền"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d thông báo khác"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Nhấn lại để mở"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Vuốt lên để mở khóa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 7fb5868..442fdb7 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"增强对比度模式"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"颜色校正模式"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"最近"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"应用信息"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"搜索"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"网络可能会\n受到监控"</string>
     <string name="description_target_search" msgid="3091587249776033139">"搜索"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑动以<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"隐藏了1条通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"隐藏了%d条通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"触摸即可显示"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"勿扰"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"还有%d条"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"再次点按即可打开"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"向上滑动即可解锁"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index d4defa4..54a3b1e 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"增強對比模式"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"色彩校準模式"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資料"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網絡可能會\n受到監控"</string>
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"請勿騷擾"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"還有 %d 個"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"向上快速滑動即可解鎖"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 163ef2a..fc74f53 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -207,8 +207,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"增強對比模式"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"色彩校正模式"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"近期"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"應用程式資訊"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"搜尋"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"網路可能\n受到監控"</string>
     <string name="description_target_search" msgid="3091587249776033139">"搜尋"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"向上滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
     <string name="description_direction_left" msgid="7207478719805562165">"向左滑動即可<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>。"</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"已隱藏通知"</item>
+    <item quantity="other" msgid="7388721375827338153">"已隱藏 %d 則通知"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"輕觸即可顯示"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"請勿打擾"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"還有 %d 則"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"再次輕按即可開啟"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"向上滑動即可解鎖"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 92e3382..dfe8838 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -205,8 +205,21 @@
     <string name="quick_settings_contrast_label" msgid="3319507551689108692">"Imodi ethuthukisiwe yokugqama"</string>
     <string name="quick_settings_color_space_label" msgid="853443689745584770">"Imodi yokulungisa umbala"</string>
     <string name="recents_empty_message" msgid="2269156590813544104">"OKWAKAMUVA"</string>
+    <string name="recents_app_info_button_label" msgid="2890317189376000030">"Ulwazi lohlelo lokusebenza"</string>
+    <string name="recents_search_bar_label" msgid="8074997400187836677">"sesha"</string>
     <string name="ssl_ca_cert_warning" msgid="9005954106902053641">"Kungenzeka inethiwekhi\niqashiwe"</string>
     <string name="description_target_search" msgid="3091587249776033139">"Sesha"</string>
     <string name="description_direction_up" msgid="7169032478259485180">"Shelelisela ngenhla ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
     <string name="description_direction_left" msgid="7207478719805562165">"Shelelisela ngakwesokunxele ku-<xliff:g id="TARGET_DESCRIPTION">%s</xliff:g>."</string>
+  <plurals name="zen_mode_notification_title">
+    <item quantity="one" msgid="7809876956258040354">"Isaziso sifihliwe"</item>
+    <item quantity="other" msgid="7388721375827338153">"%d izaziso zifihliwe"</item>
+  </plurals>
+    <string name="zen_mode_notification_text" msgid="8336623711388065713">"Thinta ukuze ubonise"</string>
+    <string name="zen_mode_title" msgid="8793432092004749188">"Ungaphazamisi"</string>
+  <plurals name="keyguard_more_overflow_text">
+    <item quantity="other" msgid="9180696159506883684">"%d okuningi"</item>
+  </plurals>
+    <string name="notification_tap_again" msgid="7590196980943943842">"Thepha futhi ukuze uvule"</string>
+    <string name="keyguard_unlock" msgid="8043466894212841998">"Swayiphela phezulu ukuze uvule"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 5cf0453..9281265 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -31,7 +31,8 @@
     <drawable name="notification_item_background_legacy_color">#ffaaaaaa</drawable>
     <drawable name="heads_up_notification_bg_pressed">#ff33B5E5</drawable>
     <drawable name="notification_header_bg">#FF000000</drawable>
-    <color name="notification_panel_scrim_color">#B0000000</color>
+    <color name="notification_panel_scrim_color">#A0000000</color>
+    <color name="notification_panel_scrim_color_keyguard">#80000000</color>
     <color name="batterymeter_frame_color">#66FFFFFF</color><!-- 40% white -->
     <color name="batterymeter_charge_color">#FFFFFFFF</color>
     <color name="batterymeter_bolt_color">#FFFFFFFF</color>
@@ -45,4 +46,17 @@
 
     <!-- Tint color for active Quick Settings icons. -->
     <color name="ic_qs_on">#ffffffff</color>
+
+    <!-- Tint color for the content on the notification overflow card. -->
+    <color name="keyguard_overflow_content_color">#ff666666</color>
+
+    <!-- The default recents task bar background color. -->
+    <color name="recents_task_bar_default_background_color">#e6444444</color>
+    <!-- The default recents task bar text color. -->
+    <color name="recents_task_bar_default_text_color">#ffffffff</color>
+    <!-- The recents task bar light text color to be drawn on top of dark backgrounds. -->
+    <color name="recents_task_bar_light_text_color">#ffffffff</color>
+    <!-- The recents task bar dark text color to be drawn on top of light backgrounds. -->
+    <color name="recents_task_bar_dark_text_color">#ff222222</color>
+
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 77944c8..722ca15 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -72,7 +72,7 @@
     <!-- decay duration (from size_max -> size), in ms -->
     <integer name="navigation_bar_deadzone_hold">333</integer>
     <integer name="navigation_bar_deadzone_decay">333</integer>
-    
+
     <bool name="config_dead_zone_flash">false</bool>
 
     <!-- Min alpha % that recent items will fade to while being dismissed -->
@@ -81,6 +81,12 @@
     <!-- The number of columns in the QuickSettings -->
     <integer name="quick_settings_num_columns">3</integer>
 
+    <!-- The maximum number of rows in the QuickSettings -->
+    <integer name="quick_settings_max_rows">4</integer>
+
+    <!-- The maximum number of rows in the QuickSettings when on the keyguard -->
+    <integer name="quick_settings_max_rows_keyguard">3</integer>
+
     <!-- The number of columns that the top level tiles span in the QuickSettings -->
     <integer name="quick_settings_user_time_settings_tile_span">1</integer>
 
@@ -93,11 +99,8 @@
 
     <integer name="blinds_pop_duration_ms">10</integer>
 
-    <!-- Disable the separate quick settings panel -->
-    <bool name="config_hasSettingsPanel">true</bool>
-
-    <!-- Enable the "flip settings" panel -->
-    <bool name="config_hasFlipSettingsPanel">true</bool>
+    <!-- The device supports quick settings. -->
+    <bool name="config_hasQuickSettings">true</bool>
 
     <!-- Should "4G" be shown instead of "LTE" when the network is NETWORK_TYPE_LTE? -->
     <bool name="config_show4GForLTE">true</bool>
@@ -112,5 +115,18 @@
     <integer name="recents_filter_animate_current_views_min_duration">175</integer>
     <!-- The min animation duration for animating views that are newly visible. -->
     <integer name="recents_filter_animate_new_views_min_duration">125</integer>
+    <!-- The min animation duration for animating views that are newly visible. -->
+    <integer name="recents_animate_task_bar_enter_duration">200</integer>
+    <!-- The animation duration for animating in the info pane. -->
+    <integer name="recents_animate_task_view_info_pane_duration">150</integer>
+    <!-- The minimum alpha for the dim applied to cards that go deeper into the stack. -->
+    <integer name="recents_max_task_stack_view_dim">96</integer>
+
+    <!-- Whether to enable KeyguardService or not -->
+    <bool name="config_enableKeyguardService">true</bool>
+
+    <!-- The maximum count of notifications on Keyguard. The rest will be collapsed in an overflow
+     card. -->
+    <integer name="keyguard_max_notification_count">4</integer>
 </resources>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 2c8f9a1..9837d9b 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -82,12 +82,6 @@
     <!-- Height of a medium notification in the status bar -->
     <dimen name="notification_mid_height">128dp</dimen>
 
-    <!-- Height of a small notification in the status bar plus glow, padding, etc -->
-    <dimen name="notification_row_min_height">70dp</dimen>
-
-    <!-- Height of a large notification in the status bar plus glow, padding, etc -->
-    <dimen name="notification_row_max_height">260dp</dimen>
-
     <!-- size at which Notification icons will be drawn in the status bar -->
     <dimen name="status_bar_icon_drawing_size">18dip</dimen>
 
@@ -98,7 +92,7 @@
     <dimen name="status_bar_icon_padding">0dp</dimen>
 
     <!-- half the distance between notifications in the panel -->
-    <dimen name="notification_divider_height">3dp</dimen>
+    <dimen name="notification_divider_height">2dp</dimen>
 
     <!-- Notification drawer tuning parameters (phone UI) -->
     <!-- Initial velocity of the shade when expanding on its own -->
@@ -167,28 +161,22 @@
     <!-- Extra space above the clock in the panel -->
     <dimen name="notification_panel_header_padding_top">0dp</dimen>
 
+    <!-- Extra space above the panel holder -->
+    <dimen name="panel_holder_padding_top">0dp</dimen>
+
     <!-- Layout parameters for the notification panel -->
     <dimen name="notification_panel_margin_bottom">0dp</dimen>
     <dimen name="notification_panel_margin_left">0dp</dimen>
 
-    <!-- Gravity for the notification & quick settings panels -->
+    <!-- Gravity for the notification panel -->
     <!-- 0x37 = fill_horizontal|top -->
     <integer name="notification_panel_layout_gravity">0x37</integer>
-    <integer name="settings_panel_layout_gravity">0x37</integer>
-
-    <!-- Fraction of the status bar that, when dragged, will produce the quick settings panel
-         instead of the notification panel. See also @dimen/settings_panel_dragzone_min.
-         If zero, the settings panel will not be directly draggable from the status bar. -->
-    <item type="dimen" name="settings_panel_dragzone_fraction">0%</item>
-
-    <!-- Quick settings dragzone, if used, should be at least this big (may be zero). -->
-    <dimen name="settings_panel_dragzone_min">100dp</dimen>
 
     <!-- Height of the carrier/wifi name label -->
     <dimen name="carrier_label_height">24dp</dimen>
 
     <!-- The distance you can pull a notification before it pops open -->
-    <dimen name="one_finger_pop_limit">32dp</dimen>
+    <dimen name="one_finger_pop_limit">0dp</dimen>
 
     <!-- The fixed height of each tile -->
     <dimen name="quick_settings_cell_height">110dp</dimen>
@@ -200,7 +188,7 @@
          Not used at this screen size. -->
     <item type="dimen" name="notification_panel_min_height_frac">0%</item>
 
-    <dimen name="blinds_pop_threshold">32dp</dimen>
+    <dimen name="blinds_pop_threshold">0dp</dimen>
 
     <!-- The size of the gesture span needed to activate the "pull" notification expansion -->
     <dimen name="pull_span_min">25dp</dimen>
@@ -236,6 +224,18 @@
     <!-- The size of the activity icon in the recents task view. -->
     <dimen name="recents_task_view_activity_icon_size">60dp</dimen>
 
+    <!-- The radius of the rounded corners on a task view. -->
+    <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
+
+    <!-- The amount of space a user has to scroll to dismiss any info panes. -->
+    <dimen name="recents_task_stack_scroll_dismiss_info_pane_distance">50dp</dimen>
+
+    <!-- The height of the search bar space. -->
+    <dimen name="recents_search_bar_space_height">40dp</dimen>
+
+    <!-- The search bar edge margins. -->
+    <dimen name="recents_search_bar_space_edge_margins">12dp</dimen>
+
     <!-- Used to calculate the translation animation duration, the expected amount of movement 
          in dps over one second of time. -->
     <dimen name="recents_animation_movement_in_dps_per_second">800dp</dimen>
@@ -244,7 +244,7 @@
     <dimen name="notification_stack_margin_bottom">0dp</dimen>
 
     <!-- Space reserved for the cards behind the top card in the top stack -->
-    <dimen name="top_stack_peek_amount">24dp</dimen>
+    <dimen name="top_stack_peek_amount">12dp</dimen>
 
     <!-- Space reserved for the cards behind the top card in the bottom stack -->
     <dimen name="bottom_stack_peek_amount">18dp</dimen>
@@ -255,6 +255,17 @@
     <!-- Z distance between notifications if they are in the stack -->
     <dimen name="z_distance_between_notifications">2dp</dimen>
 
+    <!-- The padding between the individual notification cards. -->
+    <dimen name="notification_padding">3dp</dimen>
+
     <!-- Width of the zen mode interstitial dialog. -->
     <dimen name="zen_mode_dialog_width">320dp</dimen>
+
+    <!-- Camera affordance drag distance -->
+    <dimen name="camera_drag_distance">100dp</dimen>
+
+    <dimen name="quick_settings_tmp_scrim_stroke_width">8dp</dimen>
+    <dimen name="quick_settings_tmp_scrim_text_size">30dp</dimen>
+
+    <dimen name="notifications_top_padding">8dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/packages/SystemUI/res/values/internal.xml
similarity index 63%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to packages/SystemUI/res/values/internal.xml
index 15d0890..ddaab942 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/packages/SystemUI/res/values/internal.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<resources>
+    <dimen name="status_bar_height">@*android:dimen/status_bar_height</dimen>
+    <dimen name="navigation_bar_height">@*android:dimen/navigation_bar_height</dimen>
+    <drawable name="notification_quantum_bg">@*android:drawable/notification_quantum_bg</drawable>
+</resources>
+
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index ce05639..b4a13d4 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -509,6 +509,10 @@
 
     <!-- Recents: The empty recents string. [CHAR LIMIT=NONE] -->
     <string name="recents_empty_message">RECENTS</string>
+    <!-- Recents: The info panel app info button string. [CHAR LIMIT=NONE] -->
+    <string name="recents_app_info_button_label">Application Info</string>
+    <!-- Recents: Temporary string for the button in the recents search bar. [CHAR LIMIT=NONE] -->
+    <string name="recents_search_bar_label">search</string>
 
 
     <!-- Glyph to be overlaid atop the battery when the level is extremely low. Do not translate. -->
@@ -526,4 +530,26 @@
     <string name="description_direction_up">Slide up for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
     <!-- Description of the left direction in which one can to slide the handle in the Slide unlock screen. [CHAR LIMIT=NONE] -->
     <string name="description_direction_left">"Slide left for <xliff:g id="target_description" example="Unlock">%s</xliff:g>.</string>
+
+    <!-- Zen mode: Summary notification content title. [CHAR LIMIT=NONE] -->
+    <plurals name="zen_mode_notification_title">
+        <item quantity="one">Notification hidden</item>
+        <item quantity="other">%d notifications hidden</item>
+    </plurals>
+    <!-- Zen mode: Summary notification content text. [CHAR LIMIT=NONE] -->
+    <string name="zen_mode_notification_text">Touch to show</string>
+
+    <!-- Zen mode: Short title. [CHAR LIMIT=40] -->
+    <string name="zen_mode_title">Do not disturb</string>
+
+    <!-- Text for overflow card on Keyguard when there is not enough space for all notifications on Keyguard. [CHAR LIMIT=12] -->
+    <plurals name="keyguard_more_overflow_text">
+        <item quantity="other">%d more</item>
+    </plurals>
+
+    <!-- Shows to explain the double tap interaction with notifications: After tapping a notification on Keyguard, this will explain users to tap again to launch a notification. [CHAR LIMIT=60] -->
+    <string name="notification_tap_again">Tap again to open</string>
+
+    <!-- Shows when people have pressed the unlock icon to explain how to unlock. [CHAR LIMIT=60] -->
+    <string name="keyguard_unlock">Swipe up to unlock</string>
 </resources>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 76cadd7..8ab646d 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -137,10 +137,9 @@
     <style name="BaseBrightnessDialogContainer">
         <item name="android:layout_width">match_parent</item>
         <item name="android:layout_height">wrap_content</item>
-        <item name="android:layout_marginLeft">8dp</item>
-        <item name="android:layout_marginRight">8dp</item>
         <item name="android:padding">16dp</item>
     </style>
+
     <style name="BrightnessDialogContainer" parent="@style/BaseBrightnessDialogContainer" />
 
     <style name="Animation" />
@@ -169,5 +168,7 @@
         <!-- Note: must be dp to fit in status bar -->
         <item name="android:textSize">14dp</item>
     </style>
-    
+
+    <style name="systemui_theme" parent="@android:style/Theme.DeviceDefault" />
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
index 1832d37..61c268e 100644
--- a/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/ExpandHelper.java
@@ -19,7 +19,6 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
-import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.media.AudioManager;
@@ -32,8 +31,9 @@
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewConfiguration;
-import android.view.ViewGroup;
 
+import com.android.systemui.statusbar.ExpandableView;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
 public class ExpandHelper implements Gefingerpoken, OnClickListener {
@@ -81,8 +81,6 @@
     private boolean mHasPopped;
     private View mEventSource;
     private View mCurrView;
-    private View mCurrViewTopGlow;
-    private View mCurrViewBottomGlow;
     private float mOldHeight;
     private float mNaturalHeight;
     private float mInitialTouchFocusY;
@@ -99,9 +97,6 @@
     private ScaleGestureDetector mSGD;
     private ViewScaler mScaler;
     private ObjectAnimator mScaleAnimation;
-    private AnimatorSet mGlowAnimationSet;
-    private ObjectAnimator mGlowTopAnimation;
-    private ObjectAnimator mGlowBottomAnimation;
     private Vibrator mVibrator;
 
     private int mSmallSize;
@@ -121,9 +116,7 @@
             float focusY = detector.getFocusY();
 
             final View underFocus = findView(focusX, focusY);
-            if (underFocus != null) {
-                startExpanding(underFocus, STRETCH);
-            }
+            startExpanding(underFocus, STRETCH);
             return mExpanding;
         }
 
@@ -139,41 +132,21 @@
     };
 
     private class ViewScaler {
-        View mView;
+        ExpandableView mView;
 
         public ViewScaler() {}
-        public void setView(View v) {
+        public void setView(ExpandableView v) {
             mView = v;
         }
         public void setHeight(float h) {
             if (DEBUG_SCALE) Log.v(TAG, "SetHeight: setting to " + h);
-            ViewGroup.LayoutParams lp = mView.getLayoutParams();
-            lp.height = (int)h;
-            mView.setLayoutParams(lp);
-            mView.requestLayout();
+            mView.setActualHeight((int) h);
         }
         public float getHeight() {
-            int height = mView.getLayoutParams().height;
-            if (height < 0) {
-                height = mView.getMeasuredHeight();
-            }
-            return height;
+            return mView.getActualHeight();
         }
         public int getNaturalHeight(int maximum) {
-            ViewGroup.LayoutParams lp = mView.getLayoutParams();
-            if (DEBUG_SCALE) Log.v(TAG, "Inspecting a child of type: " +
-                    mView.getClass().getName());
-            int oldHeight = lp.height;
-            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
-            mView.setLayoutParams(lp);
-            mView.measure(
-                    View.MeasureSpec.makeMeasureSpec(mView.getMeasuredWidth(),
-                                                     View.MeasureSpec.EXACTLY),
-                    View.MeasureSpec.makeMeasureSpec(maximum,
-                                                     View.MeasureSpec.AT_MOST));
-            lp.height = oldHeight;
-            mView.setLayoutParams(lp);
-            return mView.getMeasuredHeight();
+            return Math.min(maximum, mView.getMaxHeight());
         }
     }
 
@@ -217,14 +190,6 @@
             }
         };
 
-        mGlowTopAnimation = ObjectAnimator.ofFloat(null, "alpha", 0f);
-        mGlowTopAnimation.addListener(glowVisibilityController);
-        mGlowBottomAnimation = ObjectAnimator.ofFloat(null, "alpha", 0f);
-        mGlowBottomAnimation.addListener(glowVisibilityController);
-        mGlowAnimationSet = new AnimatorSet();
-        mGlowAnimationSet.play(mGlowTopAnimation).with(mGlowBottomAnimation);
-        mGlowAnimationSet.setDuration(GLOW_DURATION);
-
         final ViewConfiguration configuration = ViewConfiguration.get(mContext);
         mTouchSlop = configuration.getScaledTouchSlop();
 
@@ -245,7 +210,6 @@
         float newHeight = clamp(target);
         mScaler.setHeight(newHeight);
 
-        setGlow(calculateGlow(target, newHeight));
         mLastFocusY = mSGD.getFocusY();
         mLastSpanY = mSGD.getCurrentSpan();
     }
@@ -316,37 +280,6 @@
         return (GLOW_BASE + strength * (1f - GLOW_BASE));
     }
 
-    public void setGlow(float glow) {
-        if (!mGlowAnimationSet.isRunning() || glow == 0f) {
-            if (mGlowAnimationSet.isRunning()) {
-                mGlowAnimationSet.end();
-            }
-            if (mCurrViewTopGlow != null && mCurrViewBottomGlow != null) {
-                if (glow == 0f || mCurrViewTopGlow.getAlpha() == 0f) {
-                    // animate glow in and out
-                    mGlowTopAnimation.setTarget(mCurrViewTopGlow);
-                    mGlowBottomAnimation.setTarget(mCurrViewBottomGlow);
-                    mGlowTopAnimation.setFloatValues(glow);
-                    mGlowBottomAnimation.setFloatValues(glow);
-                    mGlowAnimationSet.setupStartValues();
-                    mGlowAnimationSet.start();
-                } else {
-                    // set it explicitly in reponse to touches.
-                    mCurrViewTopGlow.setAlpha(glow);
-                    mCurrViewBottomGlow.setAlpha(glow);
-                    handleGlowVisibility();
-                }
-            }
-        }
-    }
-
-    private void handleGlowVisibility() {
-        mCurrViewTopGlow.setVisibility(mCurrViewTopGlow.getAlpha() <= 0.0f ?
-                View.INVISIBLE : View.VISIBLE);
-        mCurrViewBottomGlow.setVisibility(mCurrViewBottomGlow.getAlpha() <= 0.0f ?
-                View.INVISIBLE : View.VISIBLE);
-    }
-
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         final int action = ev.getAction();
@@ -381,9 +314,7 @@
                 if (DEBUG_SCALE) Log.v(TAG, "got pull gesture (xspan=" + xspan + "px)");
 
                 final View underFocus = findView(x, y);
-                if (underFocus != null) {
-                    startExpanding(underFocus, PULL);
-                }
+                startExpanding(underFocus, PULL);
                 return true;
             }
             if (mScrollAdapter != null && !mScrollAdapter.isScrolledToTop()) {
@@ -398,8 +329,7 @@
                         if (DEBUG) Log.v(TAG, "got venetian gesture (dy=" + yDiff + "px)");
                         mLastMotionY = y;
                         final View underFocus = findView(x, y);
-                        if (underFocus != null) {
-                            startExpanding(underFocus, BLINDS);
+                        if (startExpanding(underFocus, BLINDS)) {
                             mInitialTouchY = mLastMotionY;
                             mHasPopped = false;
                         }
@@ -460,9 +390,6 @@
 
                     if (mHasPopped) {
                         mScaler.setHeight(newHeight);
-                        setGlow(GLOW_BASE);
-                    } else {
-                        setGlow(calculateGlow(4f * pull, 0f));
                     }
 
                     final int x = (int) mSGD.getFocusX();
@@ -502,17 +429,22 @@
         return true;
     }
 
-    private void startExpanding(View v, int expandType) {
+    /**
+     * @return True if the view is expandable, false otherwise.
+     */
+    private boolean startExpanding(View v, int expandType) {
+        if (!(v instanceof ExpandableNotificationRow)) {
+            return false;
+        }
         mExpansionStyle = expandType;
-        if (mExpanding &&  v == mCurrView) {
-            return;
+        if (mExpanding && v == mCurrView) {
+            return true;
         }
         mExpanding = true;
         if (DEBUG) Log.d(TAG, "scale type " + expandType + " beginning on view: " + v);
         mCallback.setUserLockedChild(v, true);
         setView(v);
-        setGlow(GLOW_BASE);
-        mScaler.setView(v);
+        mScaler.setView((ExpandableView) v);
         mOldHeight = mScaler.getHeight();
         if (mCallback.canChildBeExpanded(v)) {
             if (DEBUG) Log.d(TAG, "working on an expandable child");
@@ -524,6 +456,7 @@
         if (DEBUG) Log.d(TAG, "got mOldHeight: " + mOldHeight +
                     " mNaturalHeight: " + mNaturalHeight);
         v.getParent().requestDisallowInterceptTouchEvent(true);
+        return true;
     }
 
     private void finishExpanding(boolean force) {
@@ -543,14 +476,22 @@
         if (mScaleAnimation.isRunning()) {
             mScaleAnimation.cancel();
         }
-        setGlow(0f);
-        mCallback.setUserExpandedChild(mCurrView, h == mNaturalHeight);
+        mCallback.setUserExpandedChild(mCurrView, targetHeight == mNaturalHeight);
         if (targetHeight != currentHeight) {
             mScaleAnimation.setFloatValues(targetHeight);
             mScaleAnimation.setupStartValues();
+            final View scaledView = mCurrView;
+            mScaleAnimation.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mCallback.setUserLockedChild(scaledView, false);
+                    mScaleAnimation.removeListener(this);
+                }
+            });
             mScaleAnimation.start();
+        } else {
+            mCallback.setUserLockedChild(mCurrView, false);
         }
-        mCallback.setUserLockedChild(mCurrView, false);
 
         mExpanding = false;
         mExpansionStyle = NONE;
@@ -564,23 +505,11 @@
 
     private void clearView() {
         mCurrView = null;
-        mCurrViewTopGlow = null;
-        mCurrViewBottomGlow = null;
+
     }
 
     private void setView(View v) {
         mCurrView = v;
-        if (v instanceof ViewGroup) {
-            ViewGroup g = (ViewGroup) v;
-            mCurrViewTopGlow = g.findViewById(R.id.top_glow);
-            mCurrViewBottomGlow = g.findViewById(R.id.bottom_glow);
-            if (DEBUG) {
-                String debugLog = "Looking for glows: " +
-                        (mCurrViewTopGlow != null ? "found top " : "didn't find top") +
-                        (mCurrViewBottomGlow != null ? "found bottom " : "didn't find bottom");
-                Log.v(TAG,  debugLog);
-            }
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 74483cc..4857adc 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -211,6 +211,7 @@
             if (mReceiver != null) {
                 unregisterReceiver(mReceiver);
             }
+            mBackground = null;
         }
 
         void updateSurfaceSize(SurfaceHolder surfaceHolder) {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUI.java b/packages/SystemUI/src/com/android/systemui/SystemUI.java
index cb624ad..85befff 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUI.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUI.java
@@ -35,6 +35,9 @@
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
     }
 
+    protected void onBootCompleted() {
+    }
+
     @SuppressWarnings("unchecked")
     public <T> T getComponent(Class<T> interfaceType) {
         return (T) (mComponents != null ? mComponents.get(interfaceType) : null);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
new file mode 100644
index 0000000..103991a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui;
+
+import android.app.Application;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Configuration;
+import android.os.SystemProperties;
+import android.util.Log;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Application class for SystemUI.
+ */
+public class SystemUIApplication extends Application {
+
+    private static final String TAG = "SystemUIService";
+    private static final boolean DEBUG = false;
+
+    /**
+     * The classes of the stuff to start.
+     */
+    private final Class<?>[] SERVICES = new Class[] {
+            com.android.systemui.keyguard.KeyguardViewMediator.class,
+            com.android.systemui.recent.Recents.class,
+            com.android.systemui.statusbar.SystemBars.class,
+            com.android.systemui.usb.StorageNotification.class,
+            com.android.systemui.power.PowerUI.class,
+            com.android.systemui.media.RingtonePlayer.class,
+            com.android.systemui.settings.SettingsUI.class,
+    };
+
+    /**
+     * Hold a reference on the stuff we start.
+     */
+    private final SystemUI[] mServices = new SystemUI[SERVICES.length];
+    private boolean mServicesStarted;
+    private boolean mBootCompleted;
+    private final Map<Class<?>, Object> mComponents = new HashMap<Class<?>, Object>();
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        // Set the application theme that is inherited by all services. Note that setting the
+        // application theme in the manifest does only work for activities. Keep this in sync with
+        // the theme set there.
+        setTheme(R.style.systemui_theme);
+
+        registerReceiver(new BroadcastReceiver() {
+            @Override
+            public void onReceive(Context context, Intent intent) {
+                if (mBootCompleted) return;
+
+                if (DEBUG) Log.v(TAG, "BOOT_COMPLETED received");
+                unregisterReceiver(this);
+                mBootCompleted = true;
+                if (mServicesStarted) {
+                    final int N = mServices.length;
+                    for (int i = 0; i < N; i++) {
+                        mServices[i].onBootCompleted();
+                    }
+                }
+            }
+        }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED));
+    }
+
+    /**
+     * Makes sure that all the SystemUI services are running. If they are already running, this is a
+     * no-op. This is needed to conditinally start all the services, as we only need to have it in
+     * the main process.
+     *
+     * <p>This method must only be called from the main thread.</p>
+     */
+    public void startServicesIfNeeded() {
+        if (mServicesStarted) {
+            return;
+        }
+
+        if (!mBootCompleted) {
+            // check to see if maybe it was already completed long before we began
+            // see ActivityManagerService.finishBooting()
+            if ("1".equals(SystemProperties.get("sys.boot_completed"))) {
+                mBootCompleted = true;
+                if (DEBUG) Log.v(TAG, "BOOT_COMPLETED was already sent");
+            }
+        }
+
+        Log.v(TAG, "Starting SystemUI services.");
+        final int N = SERVICES.length;
+        for (int i=0; i<N; i++) {
+            Class<?> cl = SERVICES[i];
+            if (DEBUG) Log.d(TAG, "loading: " + cl);
+            try {
+                mServices[i] = (SystemUI)cl.newInstance();
+            } catch (IllegalAccessException ex) {
+                throw new RuntimeException(ex);
+            } catch (InstantiationException ex) {
+                throw new RuntimeException(ex);
+            }
+            mServices[i].mContext = this;
+            mServices[i].mComponents = mComponents;
+            if (DEBUG) Log.d(TAG, "running: " + mServices[i]);
+            mServices[i].start();
+
+            if (mBootCompleted) {
+                mServices[i].onBootCompleted();
+            }
+        }
+        mServicesStarted = true;
+    }
+
+    @Override
+    public void onConfigurationChanged(Configuration newConfig) {
+        if (mServicesStarted) {
+            int len = mServices.length;
+            for (int i = 0; i < len; i++) {
+                mServices[i].onConfigurationChanged(newConfig);
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public <T> T getComponent(Class<T> interfaceType) {
+        return (T) mComponents.get(interfaceType);
+    }
+
+    public SystemUI[] getServices() {
+        return mServices;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIService.java b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
index ca5f7d1..05e5f6b 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIService.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIService.java
@@ -18,80 +18,35 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.content.res.Configuration;
 import android.os.IBinder;
-import android.util.Log;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.HashMap;
 
 public class SystemUIService extends Service {
-    private static final String TAG = "SystemUIService";
-
-    /**
-     * The classes of the stuff to start.
-     */
-    private final Class<?>[] SERVICES = new Class[] {
-            com.android.systemui.recent.Recents.class,
-            com.android.systemui.statusbar.SystemBars.class,
-            com.android.systemui.usb.StorageNotification.class,
-            com.android.systemui.power.PowerUI.class,
-            com.android.systemui.media.RingtonePlayer.class,
-            com.android.systemui.settings.SettingsUI.class,
-        };
-
-    /**
-     * Hold a reference on the stuff we start.
-     */
-    private final SystemUI[] mServices = new SystemUI[SERVICES.length];
 
     @Override
     public void onCreate() {
-        HashMap<Class<?>, Object> components = new HashMap<Class<?>, Object>();
-        final int N = SERVICES.length;
-        for (int i=0; i<N; i++) {
-            Class<?> cl = SERVICES[i];
-            Log.d(TAG, "loading: " + cl);
-            try {
-                mServices[i] = (SystemUI)cl.newInstance();
-            } catch (IllegalAccessException ex) {
-                throw new RuntimeException(ex);
-            } catch (InstantiationException ex) {
-                throw new RuntimeException(ex);
-            }
-            mServices[i].mContext = this;
-            mServices[i].mComponents = components;
-            Log.d(TAG, "running: " + mServices[i]);
-            mServices[i].start();
-        }
+        super.onCreate();
+        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
     }
 
     @Override
-    public void onConfigurationChanged(Configuration newConfig) {
-        for (SystemUI ui: mServices) {
-            ui.onConfigurationChanged(newConfig);
-        }
-    }
-
-    /**
-     * Nobody binds to us.
-     */
-    @Override
     public IBinder onBind(Intent intent) {
         return null;
     }
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        SystemUI[] services = ((SystemUIApplication) getApplication()).getServices();
         if (args == null || args.length == 0) {
-            for (SystemUI ui: mServices) {
+            for (SystemUI ui: services) {
                 pw.println("dumping service: " + ui.getClass().getName());
                 ui.dump(fd, pw, args);
             }
         } else {
             String svc = args[0];
-            for (SystemUI ui: mServices) {
+            for (SystemUI ui: services) {
                 String name = ui.getClass().getName();
                 if (name.endsWith(svc)) {
                     ui.dump(fd, pw, args);
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
similarity index 65%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardService.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 36b2446..41c0e78 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 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.
@@ -11,18 +11,13 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.keyguard;
-
-import java.io.FileDescriptor;
-import java.io.PrintWriter;
+package com.android.systemui.keyguard;
 
 import android.app.Service;
 import android.content.Intent;
-import static android.content.pm.PackageManager.PERMISSION_GRANTED;
-
 import android.os.Binder;
 import android.os.Bundle;
 import android.os.Debug;
@@ -30,23 +25,25 @@
 import android.util.Log;
 import android.view.MotionEvent;
 
-import com.android.internal.policy.IKeyguardService;
 import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.IKeyguardShowCallback;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.systemui.SystemUIApplication;
+
+import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 
 public class KeyguardService extends Service {
     static final String TAG = "KeyguardService";
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
+
     private KeyguardViewMediator mKeyguardViewMediator;
 
     @Override
     public void onCreate() {
-        if (mKeyguardViewMediator == null) {
-            mKeyguardViewMediator = new KeyguardViewMediator(
-                    KeyguardService.this, new LockPatternUtils(KeyguardService.this));
-        }
-        Log.v(TAG, "onCreate()");
+        ((SystemUIApplication) getApplication()).startServicesIfNeeded();
+        mKeyguardViewMediator =
+                ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
     }
 
     @Override
@@ -54,11 +51,6 @@
         return mBinder;
     }
 
-    @Override
-    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        // TODO
-    }
-
     void checkPermission() {
         if (getBaseContext().checkCallingOrSelfPermission(PERMISSION) != PERMISSION_GRANTED) {
             Log.w(TAG, "Caller needs permission '" + PERMISSION + "' to call " + Debug.getCaller());
@@ -68,84 +60,148 @@
     }
 
     private final IKeyguardService.Stub mBinder = new IKeyguardService.Stub() {
+
+        private boolean mIsOccluded;
+
+        @Override
         public boolean isShowing() {
             return mKeyguardViewMediator.isShowing();
         }
+
+        @Override
         public boolean isSecure() {
             return mKeyguardViewMediator.isSecure();
         }
-        public boolean isShowingAndNotHidden() {
-            return mKeyguardViewMediator.isShowingAndNotHidden();
+
+        @Override
+        public boolean isShowingAndNotOccluded() {
+            return mKeyguardViewMediator.isShowingAndNotOccluded();
         }
+
+        @Override
         public boolean isInputRestricted() {
             return mKeyguardViewMediator.isInputRestricted();
         }
+
+        @Override
         public void verifyUnlock(IKeyguardExitCallback callback) {
+            checkPermission();
             mKeyguardViewMediator.verifyUnlock(callback);
         }
+
+        @Override
         public void keyguardDone(boolean authenticated, boolean wakeup) {
             checkPermission();
             mKeyguardViewMediator.keyguardDone(authenticated, wakeup);
         }
-        public void setHidden(boolean isHidden) {
+
+        @Override
+        public int setOccluded(boolean isOccluded) {
             checkPermission();
-            mKeyguardViewMediator.setHidden(isHidden);
+            synchronized (this) {
+                int result;
+                if (isOccluded && mKeyguardViewMediator.isShowing()
+                        && !mIsOccluded) {
+                    result = IKeyguardServiceConstants
+                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS;
+                } else if (!isOccluded && mKeyguardViewMediator.isShowing()
+                        && mIsOccluded) {
+                    result = IKeyguardServiceConstants
+                            .KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS;
+                } else {
+                    result = IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
+                }
+                if (mIsOccluded != isOccluded) {
+                    mKeyguardViewMediator.setOccluded(isOccluded);
+
+                    // Cache the value so we always have a fresh view in whether Keyguard is occluded.
+                    // If we would just call mKeyguardViewMediator.isOccluded(), this might be stale
+                    // because that value gets updated in another thread.
+                    mIsOccluded = isOccluded;
+                }
+                return result;
+            }
         }
+
+        @Override
         public void dismiss() {
+            checkPermission();
             mKeyguardViewMediator.dismiss();
         }
+
+        @Override
         public void onDreamingStarted() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStarted();
         }
+
+        @Override
         public void onDreamingStopped() {
             checkPermission();
             mKeyguardViewMediator.onDreamingStopped();
         }
+
+        @Override
         public void onScreenTurnedOff(int reason) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOff(reason);
         }
+
+        @Override
         public void onScreenTurnedOn(IKeyguardShowCallback callback) {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOn(callback);
         }
+
+        @Override
         public void setKeyguardEnabled(boolean enabled) {
             checkPermission();
             mKeyguardViewMediator.setKeyguardEnabled(enabled);
         }
+
+        @Override
         public boolean isDismissable() {
             return mKeyguardViewMediator.isDismissable();
         }
+
+        @Override
         public void onSystemReady() {
             checkPermission();
             mKeyguardViewMediator.onSystemReady();
         }
+
+        @Override
         public void doKeyguardTimeout(Bundle options) {
             checkPermission();
             mKeyguardViewMediator.doKeyguardTimeout(options);
         }
+
+        @Override
         public void setCurrentUser(int userId) {
             checkPermission();
             mKeyguardViewMediator.setCurrentUser(userId);
         }
+
+        @Override
         public void showAssistant() {
             checkPermission();
-            mKeyguardViewMediator.showAssistant();
         }
+
+        @Override
         public void dispatch(MotionEvent event) {
             checkPermission();
-            mKeyguardViewMediator.dispatch(event);
         }
+
+        @Override
         public void launchCamera() {
             checkPermission();
-            mKeyguardViewMediator.launchCamera();
         }
+
+        @Override
         public void onBootCompleted() {
             checkPermission();
             mKeyguardViewMediator.onBootCompleted();
         }
     };
-
 }
 
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
similarity index 82%
rename from packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
rename to packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 354d13f..ffdb620 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007 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.
@@ -11,15 +11,10 @@
  * 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.
+ * limitations under the License
  */
 
-package com.android.keyguard;
-
-import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+package com.android.systemui.keyguard;
 
 import android.app.Activity;
 import android.app.ActivityManagerNative;
@@ -50,17 +45,31 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
-import android.view.MotionEvent;
+import android.view.ViewGroup;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 
+import com.android.internal.policy.IKeyguardExitCallback;
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.telephony.IccCardConstants;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.analytics.Session;
+import com.android.keyguard.KeyguardDisplayManager;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.MultiUserAvatarCache;
+import com.android.keyguard.ViewMediatorCallback;
 import com.android.keyguard.analytics.KeyguardAnalytics;
+import com.android.keyguard.analytics.Session;
+import com.android.systemui.SystemUI;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowManager;
 
 import java.io.File;
 
+import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
+import static com.android.keyguard.analytics.KeyguardAnalytics.SessionTypeAdapter;
+
 
 /**
  * Mediates requests related to the keyguard.  This includes queries about the
@@ -95,15 +104,15 @@
  * false, this will override all other conditions for turning on the keyguard.
  *
  * Threading and synchronization:
- * This class is created by the initialization routine of the {@link WindowManagerPolicy},
+ * This class is created by the initialization routine of the {@link android.view.WindowManagerPolicy},
  * and runs on its thread.  The keyguard UI is created from that thread in the
  * constructor of this class.  The apis may be called from other threads, including the
  * {@link com.android.server.input.InputManagerService}'s and {@link android.view.WindowManager}'s.
  * Therefore, methods on this class are synchronized, and any action that is pointed
- * directly to the keyguard UI is posted to a {@link Handler} to ensure it is taken on the UI
+ * directly to the keyguard UI is posted to a {@link android.os.Handler} to ensure it is taken on the UI
  * thread of the keyguard.
  */
-public class KeyguardViewMediator {
+public class KeyguardViewMediator extends SystemUI {
     private static final int KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000;
     final static boolean DEBUG = false;
     private static final boolean ENABLE_ANALYTICS = Build.IS_DEBUGGABLE;
@@ -124,17 +133,14 @@
     private static final int KEYGUARD_DONE = 9;
     private static final int KEYGUARD_DONE_DRAWING = 10;
     private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
-    private static final int SET_HIDDEN = 12;
+    private static final int SET_OCCLUDED = 12;
     private static final int KEYGUARD_TIMEOUT = 13;
-    private static final int SHOW_ASSISTANT = 14;
-    private static final int DISPATCH_EVENT = 15;
-    private static final int LAUNCH_CAMERA = 16;
     private static final int DISMISS = 17;
 
     /**
      * The default amount of time we stay awake (used for all key input)
      */
-    protected static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
+    public static final int AWAKE_INTERVAL_DEFAULT_MS = 10000;
 
     /**
      * How long to wait after the screen turns off due to timeout before
@@ -151,24 +157,6 @@
     private static final int KEYGUARD_DONE_DRAWING_TIMEOUT_MS = 2000;
 
     /**
-     * Allow the user to expand the status bar when the keyguard is engaged
-     * (without a pattern or password).
-     */
-    private static final boolean ENABLE_INSECURE_STATUS_BAR_EXPAND = true;
-
-    /**
-     * Allow the user to expand the status bar when a SECURE keyguard is engaged
-     * and {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS} is set
-     * (private notifications will be masked).
-     */
-    private static final boolean ENABLE_SECURE_STATUS_BAR_EXPAND = true;
-
-    /**
-     * Default value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
-     */
-    private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
-
-    /**
      * Secure setting whether analytics are collected on the keyguard.
      */
     private static final String KEYGUARD_ANALYTICS_SETTING = "keyguard_analytics";
@@ -176,7 +164,6 @@
     /** The stream type that the lock sounds are tied to. */
     private int mMasterStreamType;
 
-    private Context mContext;
     private AlarmManager mAlarmManager;
     private AudioManager mAudioManager;
     private StatusBarManager mStatusBarManager;
@@ -204,9 +191,9 @@
      */
     private PowerManager.WakeLock mShowKeyguardWakeLock;
 
-    private KeyguardViewManager mKeyguardViewManager;
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
 
-    private final KeyguardAnalytics mKeyguardAnalytics;
+    private KeyguardAnalytics mKeyguardAnalytics;
 
     // these are protected by synchronized (this)
 
@@ -227,7 +214,7 @@
     private boolean mShowing;
 
     // true if the keyguard is hidden by another window
-    private boolean mHidden = false;
+    private boolean mOccluded = false;
 
     /**
      * Helps remember whether the screen has turned on since the last time
@@ -272,79 +259,15 @@
     private int mLockSoundStreamId;
 
     /**
-     * Tracks value of {@link Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
-     */
-    private boolean mAllowNotificationsWhenSecure;
-
-    /**
      * The volume applied to the lock/unlock sounds.
      */
-    private final float mLockSoundVolume;
+    private float mLockSoundVolume;
 
     /**
      * For managing external displays
      */
     private KeyguardDisplayManager mKeyguardDisplayManager;
 
-    /**
-     * Cache of avatar drawables, for use by KeyguardMultiUserAvatar.
-     */
-    private static MultiUserAvatarCache sMultiUserAvatarCache = new MultiUserAvatarCache();
-
-    /**
-     * The callback used by the keyguard view to tell the {@link KeyguardViewMediator}
-     * various things.
-     */
-    public interface ViewMediatorCallback {
-        /**
-         * Reports user activity and requests that the screen stay on.
-         */
-        void userActivity();
-
-        /**
-         * Reports user activity and requests that the screen stay on for at least
-         * the specified amount of time.
-         * @param millis The amount of time in millis.  This value is currently ignored.
-         */
-        void userActivity(long millis);
-
-        /**
-         * Report that the keyguard is done.
-         * @param authenticated Whether the user securely got past the keyguard.
-         *   the only reason for this to be false is if the keyguard was instructed
-         *   to appear temporarily to verify the user is supposed to get past the
-         *   keyguard, and the user fails to do so.
-         */
-        void keyguardDone(boolean authenticated);
-
-        /**
-         * Report that the keyguard is done drawing.
-         */
-        void keyguardDoneDrawing();
-
-        /**
-         * Tell ViewMediator that the current view needs IME input
-         * @param needsInput
-         */
-        void setNeedsInput(boolean needsInput);
-
-        /**
-         * Tell view mediator that the keyguard view's desired user activity timeout
-         * has changed and needs to be reapplied to the window.
-         */
-        void onUserActivityTimeoutChanged();
-
-        /**
-         * Report that the keyguard is dismissable, pending the next keyguardDone call.
-         */
-        void keyguardDonePending();
-
-        /**
-         * Report when keyguard is actually gone
-         */
-        void keyguardGone();
-    }
-
     KeyguardUpdateMonitorCallback mUpdateCallback = new KeyguardUpdateMonitorCallback() {
 
         @Override
@@ -354,7 +277,7 @@
             // ActivityManagerService) will not reconstruct the keyguard if it is already showing.
             synchronized (KeyguardViewMediator.this) {
                 mSwitchingUser = true;
-                resetStateLocked(null);
+                resetStateLocked();
                 adjustStatusBarLocked();
                 // When we switch users we want to bring the new user to the biometric unlock even
                 // if the current user has gone to the backup.
@@ -370,16 +293,16 @@
         @Override
         public void onUserRemoved(int userId) {
             mLockPatternUtils.removeUser(userId);
-            sMultiUserAvatarCache.clear(userId);
+            MultiUserAvatarCache.getInstance().clear(userId);
         }
 
         @Override
         public void onUserInfoChanged(int userId) {
-            sMultiUserAvatarCache.clear(userId);
+            MultiUserAvatarCache.getInstance().clear(userId);
         }
 
         @Override
-        void onPhoneStateChanged(int phoneState) {
+        public void onPhoneStateChanged(int phoneState) {
             synchronized (KeyguardViewMediator.this) {
                 if (TelephonyManager.CALL_STATE_IDLE == phoneState  // call ending
                         && !mScreenOn                           // screen off
@@ -394,7 +317,7 @@
                     doKeyguardLocked(null);
                 }
             }
-        };
+        }
 
         @Override
         public void onClockVisibilityChanged() {
@@ -423,7 +346,7 @@
                                         + "device isn't provisioned yet.");
                                 doKeyguardLocked(null);
                             } else {
-                                resetStateLocked(null);
+                                resetStateLocked();
                             }
                         }
                     }
@@ -436,7 +359,7 @@
                                     + "showing; need to show keyguard so user can enter sim pin");
                             doKeyguardLocked(null);
                         } else {
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
@@ -449,14 +372,14 @@
                         } else {
                             if (DEBUG) Log.d(TAG, "PERM_DISABLED, resetStateLocked to"
                                   + "show permanently disabled message in lockscreen.");
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
                 case READY:
                     synchronized (this) {
                         if (isShowing()) {
-                            resetStateLocked(null);
+                            resetStateLocked();
                         }
                     }
                     break;
@@ -466,6 +389,7 @@
     };
 
     ViewMediatorCallback mViewMediatorCallback = new ViewMediatorCallback() {
+
         public void userActivity() {
             KeyguardViewMediator.this.userActivity();
         }
@@ -484,12 +408,12 @@
 
         @Override
         public void setNeedsInput(boolean needsInput) {
-            mKeyguardViewManager.setNeedsInput(needsInput);
+            mStatusBarKeyguardViewManager.setNeedsInput(needsInput);
         }
 
         @Override
         public void onUserActivityTimeoutChanged() {
-            mKeyguardViewManager.updateUserActivityTimeout();
+            mStatusBarKeyguardViewManager.updateUserActivityTimeout();
         }
 
         @Override
@@ -513,40 +437,34 @@
         mPM.userActivity(SystemClock.uptimeMillis(), false);
     }
 
-    /**
-     * Construct a KeyguardViewMediator
-     * @param context
-     * @param lockPatternUtils optional mock interface for LockPatternUtils
-     */
-    public KeyguardViewMediator(Context context, LockPatternUtils lockPatternUtils) {
-        mContext = context;
-        mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
+    private void setup() {
+        mPM = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mUserManager = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
         mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
         mShowKeyguardWakeLock.setReferenceCounted(false);
 
         mContext.registerReceiver(mBroadcastReceiver, new IntentFilter(DELAYED_KEYGUARD_ACTION));
 
-        mKeyguardDisplayManager = new KeyguardDisplayManager(context);
+        mKeyguardDisplayManager = new KeyguardDisplayManager(mContext);
 
-        mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
+        mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
 
-        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(context);
+        mUpdateMonitor = KeyguardUpdateMonitor.getInstance(mContext);
 
-        mLockPatternUtils = lockPatternUtils != null
-                ? lockPatternUtils : new LockPatternUtils(mContext);
+        mLockPatternUtils = new LockPatternUtils(mContext);
         mLockPatternUtils.setCurrentUser(UserHandle.USER_OWNER);
 
         // Assume keyguard is showing (unless it's disabled) until we know for sure...
         mShowing = (mUpdateMonitor.isDeviceProvisioned() || mLockPatternUtils.isSecure())
                 && !mLockPatternUtils.isLockScreenDisabled();
 
-        WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
+        mStatusBarKeyguardViewManager = new StatusBarKeyguardViewManager(mContext,
+                mViewMediatorCallback, mLockPatternUtils);
         final ContentResolver cr = mContext.getContentResolver();
 
         if (ENABLE_ANALYTICS && !LockPatternUtils.isSafeModeEnabled() &&
                 Settings.Secure.getInt(cr, KEYGUARD_ANALYTICS_SETTING, 0) == 1) {
-            mKeyguardAnalytics = new KeyguardAnalytics(context, new SessionTypeAdapter() {
+            mKeyguardAnalytics = new KeyguardAnalytics(mContext, new SessionTypeAdapter() {
 
                 @Override
                 public int getSessionType() {
@@ -559,9 +477,6 @@
         } else {
             mKeyguardAnalytics = null;
         }
-        mKeyguardViewManager = new KeyguardViewManager(context, wm, mViewMediatorCallback,
-                mLockPatternUtils,
-                mKeyguardAnalytics != null ? mKeyguardAnalytics.getCallback() : null);
 
         mScreenOn = mPM.isScreenOn();
 
@@ -580,11 +495,17 @@
         if (soundPath == null || mUnlockSoundId == 0) {
             Log.w(TAG, "failed to load unlock sound from " + soundPath);
         }
-        int lockSoundDefaultAttenuation = context.getResources().getInteger(
+        int lockSoundDefaultAttenuation = mContext.getResources().getInteger(
                 com.android.internal.R.integer.config_lockSoundVolumeDb);
         mLockSoundVolume = (float)Math.pow(10, (float)lockSoundDefaultAttenuation/20);
     }
 
+    @Override
+    public void start() {
+        setup();
+        putComponent(KeyguardViewMediator.class, this);
+    }
+
     /**
      * Let us know that the system is ready after startup.
      */
@@ -621,9 +542,9 @@
 
     /**
      * Called to let us know the screen was turned off.
-     * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER},
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
-     *   {@link WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
+     * @param why either {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_USER},
+     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT} or
+     *   {@link android.view.WindowManagerPolicy#OFF_BECAUSE_OF_PROX_SENSOR}.
      */
     public void onScreenTurnedOff(int why) {
         synchronized (this) {
@@ -651,7 +572,7 @@
                 }
             } else if (mShowing) {
                 notifyScreenOffLocked();
-                resetStateLocked(null);
+                resetStateLocked();
             } else if (why == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT
                    || (why == WindowManagerPolicy.OFF_BECAUSE_OF_USER && !lockImmediately)) {
                 doKeyguardLaterLocked();
@@ -768,7 +689,7 @@
     }
 
     /**
-     * Same semantics as {@link WindowManagerPolicy#enableKeyguard}; provide
+     * Same semantics as {@link android.view.WindowManagerPolicy#enableKeyguard}; provide
      * a way for external stuff to override normal keyguard behavior.  For instance
      * the phone app disables the keyguard when it receives incoming calls.
      */
@@ -805,7 +726,7 @@
                         Slog.w(TAG, "Failed to call onKeyguardExitResult(false)", e);
                     }
                     mExitSecureCallback = null;
-                    resetStateLocked(null);
+                    resetStateLocked();
                 } else {
                     showLocked(null);
 
@@ -873,36 +794,41 @@
         return mShowing;
     }
 
-    /**
-     * Is the keyguard currently showing and not being force hidden?
-     */
-    public boolean isShowingAndNotHidden() {
-        return mShowing && !mHidden;
+    public boolean isOccluded() {
+        return mOccluded;
     }
 
     /**
-     * Notify us when the keyguard is hidden by another window
+     * Is the keyguard currently showing and not being force hidden?
      */
-    public void setHidden(boolean isHidden) {
-        if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
-        mUpdateMonitor.sendKeyguardVisibilityChanged(!isHidden);
-        mHandler.removeMessages(SET_HIDDEN);
-        Message msg = mHandler.obtainMessage(SET_HIDDEN, (isHidden ? 1 : 0), 0);
+    public boolean isShowingAndNotOccluded() {
+        return mShowing && !mOccluded;
+    }
+
+    /**
+     * Notify us when the keyguard is occluded by another window
+     */
+    public void setOccluded(boolean isOccluded) {
+        if (DEBUG) Log.d(TAG, "setOccluded " + isOccluded);
+        mUpdateMonitor.sendKeyguardVisibilityChanged(!isOccluded);
+        mHandler.removeMessages(SET_OCCLUDED);
+        Message msg = mHandler.obtainMessage(SET_OCCLUDED, (isOccluded ? 1 : 0), 0);
         mHandler.sendMessage(msg);
     }
 
     /**
-     * Handles SET_HIDDEN message sent by setHidden()
+     * Handles SET_OCCLUDED message sent by setOccluded()
      */
-    private void handleSetHidden(boolean isHidden) {
+    private void handleSetOccluded(boolean isOccluded) {
         synchronized (KeyguardViewMediator.this) {
-            if (mHidden != isHidden) {
-                mHidden = isHidden;
+            if (mOccluded != isOccluded) {
+                mOccluded = isOccluded;
+                mStatusBarKeyguardViewManager.setOccluded(isOccluded);
                 updateActivityLockScreenState();
                 adjustStatusBarLocked();
             }
             if (ENABLE_ANALYTICS && mKeyguardAnalytics != null) {
-                mKeyguardAnalytics.getCallback().onSetHidden(isHidden);
+                mKeyguardAnalytics.getCallback().onSetOccluded(isOccluded);
             }
         }
     }
@@ -946,15 +872,8 @@
             return;
         }
 
-        // note whether notification access should be allowed
-        mAllowNotificationsWhenSecure = ENABLE_SECURE_STATUS_BAR_EXPAND
-                && 0 != Settings.Global.getInt(
-                        mContext.getContentResolver(),
-                        Settings.Global.LOCK_SCREEN_SHOW_NOTIFICATIONS,
-                        ALLOW_NOTIFICATIONS_DEFAULT ? 1 : 0);
-
         // if the keyguard is already showing, don't bother
-        if (mKeyguardViewManager.isShowing()) {
+        if (mStatusBarKeyguardViewManager.isShowing()) {
             if (DEBUG) Log.d(TAG, "doKeyguard: not showing because it is already showing");
             return;
         }
@@ -996,8 +915,8 @@
      * Dismiss the keyguard through the security layers.
      */
     public void handleDismiss() {
-        if (mShowing && !mHidden) {
-            mKeyguardViewManager.dismiss();
+        if (mShowing && !mOccluded) {
+            mStatusBarKeyguardViewManager.dismiss();
         }
     }
 
@@ -1007,12 +926,11 @@
 
     /**
      * Send message to keyguard telling it to reset its state.
-     * @param options options about how to show the keyguard
-     * @see #handleReset()
+     * @see #handleReset
      */
-    private void resetStateLocked(Bundle options) {
+    private void resetStateLocked() {
         if (DEBUG) Log.e(TAG, "resetStateLocked");
-        Message msg = mHandler.obtainMessage(RESET, options);
+        Message msg = mHandler.obtainMessage(RESET);
         mHandler.sendMessage(msg);
     }
 
@@ -1038,7 +956,7 @@
 
     /**
      * Send a message to keyguard telling it the screen just turned on.
-     * @see #onScreenTurnedOn()
+     * @see #onScreenTurnedOn
      * @see #handleNotifyScreenOn
      */
     private void notifyScreenOnLocked(IKeyguardShowCallback result) {
@@ -1049,7 +967,7 @@
 
     /**
      * Send message to keyguard telling it to show itself
-     * @see #handleShow()
+     * @see #handleShow
      */
     private void showLocked(Bundle options) {
         if (DEBUG) Log.d(TAG, "showLocked");
@@ -1130,7 +1048,7 @@
                     handleHide();
                     break;
                 case RESET:
-                    handleReset((Bundle) msg.obj);
+                    handleReset();
                     break;
                 case VERIFY_UNLOCK:
                     handleVerifyUnlock();
@@ -1150,23 +1068,14 @@
                 case KEYGUARD_DONE_AUTHENTICATING:
                     keyguardDone(true, true);
                     break;
-                case SET_HIDDEN:
-                    handleSetHidden(msg.arg1 != 0);
+                case SET_OCCLUDED:
+                    handleSetOccluded(msg.arg1 != 0);
                     break;
                 case KEYGUARD_TIMEOUT:
                     synchronized (KeyguardViewMediator.this) {
                         doKeyguardLocked((Bundle) msg.obj);
                     }
                     break;
-                case SHOW_ASSISTANT:
-                    handleShowAssistant();
-                    break;
-                case DISPATCH_EVENT:
-                    handleDispatchEvent((MotionEvent) msg.obj);
-                    break;
-                case LAUNCH_CAMERA:
-                    handleLaunchCamera();
-                    break;
                 case DISMISS:
                     handleDismiss();
                     break;
@@ -1206,21 +1115,13 @@
         sendUserPresentBroadcast();
     }
 
-    protected void handleLaunchCamera() {
-        mKeyguardViewManager.launchCamera();
-    }
-
-    protected void handleDispatchEvent(MotionEvent event) {
-        mKeyguardViewManager.dispatch(event);
-    }
-
     private void sendUserPresentBroadcast() {
         final UserHandle currentUser = new UserHandle(mLockPatternUtils.getCurrentUser());
         mContext.sendBroadcastAsUser(USER_PRESENT_INTENT, currentUser);
     }
 
     /**
-     * @see #keyguardDoneDrawing
+     * @see #keyguardDone
      * @see #KEYGUARD_DONE_DRAWING
      */
     private void handleKeyguardDoneDrawing() {
@@ -1269,7 +1170,7 @@
 
     private void updateActivityLockScreenState() {
         try {
-            ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mHidden);
+            ActivityManagerNative.getDefault().setLockScreenShown(mShowing && !mOccluded);
         } catch (RemoteException e) {
         }
     }
@@ -1287,16 +1188,12 @@
                 if (DEBUG) Log.d(TAG, "handleShow");
             }
 
-            mKeyguardViewManager.show(options);
+            mStatusBarKeyguardViewManager.show(options);
             mShowing = true;
             mKeyguardDonePending = false;
             updateActivityLockScreenState();
             adjustStatusBarLocked();
             userActivity();
-            try {
-                ActivityManagerNative.getDefault().closeSystemDialogs("lock");
-            } catch (RemoteException e) {
-            }
 
             // Do this at the end to not slow down display of the keyguard.
             playSounds(true);
@@ -1320,7 +1217,7 @@
                 playSounds(false);
             }
 
-            mKeyguardViewManager.hide();
+            mStatusBarKeyguardViewManager.hide();
             mShowing = false;
             mKeyguardDonePending = false;
             updateActivityLockScreenState();
@@ -1344,23 +1241,16 @@
                 // (like recents). Temporary enable/disable (e.g. the "back" button) are
                 // done in KeyguardHostView.
                 flags |= StatusBarManager.DISABLE_RECENT;
-                if ((isSecure() && !mAllowNotificationsWhenSecure)
-                        || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
-                    // showing secure lockscreen; disable expanding.
-                    flags |= StatusBarManager.DISABLE_EXPAND;
-                }
-                if (isSecure()) {
-                    // showing secure lockscreen; disable ticker and switch private notifications
-                    // to show their public versions, if available.
-                    flags |= StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS;
-                }
                 if (!isAssistantAvailable()) {
                     flags |= StatusBarManager.DISABLE_SEARCH;
                 }
             }
+            if (isShowingAndNotOccluded()) {
+                flags |= StatusBarManager.DISABLE_HOME;
+            }
 
             if (DEBUG) {
-                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mHidden=" + mHidden
+                Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
                         + " isSecure=" + isSecure() + " --> flags=0x" + Integer.toHexString(flags));
             }
 
@@ -1371,17 +1261,13 @@
     }
 
     /**
-     * Handle message sent by {@link #resetStateLocked(Bundle)}
+     * Handle message sent by {@link #resetStateLocked}
      * @see #RESET
      */
-    private void handleReset(Bundle options) {
-        if (options == null) {
-            options = new Bundle();
-        }
-        options.putBoolean(KeyguardViewManager.IS_SWITCHING_USER, mSwitchingUser);
+    private void handleReset() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleReset");
-            mKeyguardViewManager.reset(options);
+            mStatusBarKeyguardViewManager.reset();
         }
     }
 
@@ -1392,7 +1278,7 @@
     private void handleVerifyUnlock() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleVerifyUnlock");
-            mKeyguardViewManager.verifyUnlock();
+            mStatusBarKeyguardViewManager.verifyUnlock();
             mShowing = true;
             updateActivityLockScreenState();
         }
@@ -1405,18 +1291,18 @@
     private void handleNotifyScreenOff() {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenOff");
-            mKeyguardViewManager.onScreenTurnedOff();
+            mStatusBarKeyguardViewManager.onScreenTurnedOff();
         }
     }
 
     /**
-     * Handle message sent by {@link #notifyScreenOnLocked()}
+     * Handle message sent by {@link #notifyScreenOnLocked}
      * @see #NOTIFY_SCREEN_ON
      */
     private void handleNotifyScreenOn(IKeyguardShowCallback callback) {
         synchronized (KeyguardViewMediator.this) {
             if (DEBUG) Log.d(TAG, "handleNotifyScreenOn");
-            mKeyguardViewManager.onScreenTurnedOn(callback);
+            mStatusBarKeyguardViewManager.onScreenTurnedOn(callback);
         }
     }
 
@@ -1424,35 +1310,23 @@
         return mKeyguardDonePending || !isSecure();
     }
 
-    public void showAssistant() {
-        Message msg = mHandler.obtainMessage(SHOW_ASSISTANT);
-        mHandler.sendMessage(msg);
-    }
-
-    public void handleShowAssistant() {
-        mKeyguardViewManager.showAssistant();
-    }
-
     private boolean isAssistantAvailable() {
         return mSearchManager != null
                 && mSearchManager.getAssistIntent(mContext, false, UserHandle.USER_CURRENT) != null;
     }
 
-    public static MultiUserAvatarCache getAvatarCache() {
-        return sMultiUserAvatarCache;
-    }
-
-    public void dispatch(MotionEvent event) {
-        Message msg = mHandler.obtainMessage(DISPATCH_EVENT, event);
-        mHandler.sendMessage(msg);
-    }
-
-    public void launchCamera() {
-        Message msg = mHandler.obtainMessage(LAUNCH_CAMERA);
-        mHandler.sendMessage(msg);
-    }
-
     public void onBootCompleted() {
         mUpdateMonitor.dispatchBootCompleted();
     }
+
+    public StatusBarKeyguardViewManager registerStatusBar(PhoneStatusBar phoneStatusBar,
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+        mStatusBarKeyguardViewManager.registerStatusBar(phoneStatusBar, container,
+                statusBarWindowManager);
+        return mStatusBarKeyguardViewManager;
+    }
+
+    public ViewMediatorCallback getViewMediatorCallback() {
+        return mViewMediatorCallback;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
index eb09335..aa4e69a 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/RecentTasksLoader.java
@@ -17,10 +17,12 @@
 package com.android.systemui.recent;
 
 import android.app.ActivityManager;
+import android.app.AppGlobals;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
@@ -30,7 +32,9 @@
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Process;
+import android.os.RemoteException;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
@@ -162,9 +166,14 @@
             intent.setComponent(origActivity);
         }
         final PackageManager pm = mContext.getPackageManager();
+        final IPackageManager ipm = AppGlobals.getPackageManager();
         intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
                 | Intent.FLAG_ACTIVITY_NEW_TASK);
-        final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
+        ResolveInfo resolveInfo = null;
+        try {
+            resolveInfo = ipm.resolveIntent(intent, null, 0, userId);
+        } catch (RemoteException re) {
+        }
         if (resolveInfo != null) {
             final ActivityInfo info = resolveInfo.activityInfo;
             final String title = info.loadLabel(pm).toString();
@@ -192,7 +201,11 @@
         final PackageManager pm = mContext.getPackageManager();
         Bitmap thumbnail = am.getTaskTopThumbnail(td.persistentTaskId);
         Drawable icon = getFullResIcon(td.resolveInfo, pm);
-
+        if (td.userId != UserHandle.myUserId()) {
+            // Need to badge the icon
+            final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
+            icon = um.getBadgedDrawableForUser(icon, new UserHandle(td.userId));
+        }
         if (DEBUG) Log.v(TAG, "Loaded bitmap for task "
                 + td + ": " + thumbnail);
         synchronized (td) {
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index 10b6d49..ae18aa8 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -26,6 +26,7 @@
 import android.graphics.Paint;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.util.DisplayMetrics;
@@ -45,10 +46,12 @@
     // Which recents to use
     boolean mUseAlternateRecents;
     AlternateRecentsComponent mAlternateRecents;
+    boolean mBootCompleted = false;
 
     @Override
     public void start() {
-        mUseAlternateRecents = SystemProperties.getBoolean("persist.recents.use_alternate", false);
+        Configuration config = mContext.getResources().getConfiguration();
+        mUseAlternateRecents = (config.smallestScreenWidthDp < 600);
         if (mUseAlternateRecents) {
             if (mAlternateRecents == null) {
                 mAlternateRecents = new AlternateRecentsComponent(mContext);
@@ -60,6 +63,11 @@
     }
 
     @Override
+    protected void onBootCompleted() {
+        mBootCompleted = true;
+    }
+
+    @Override
     public void toggleRecents(Display display, int layoutDirection, View statusBarView) {
         if (mUseAlternateRecents) {
             // Launch the alternate recents if required
@@ -197,13 +205,11 @@
                                 Intent intent =
                                         new Intent(RecentsActivity.WINDOW_ANIMATION_START_INTENT);
                                 intent.setPackage("com.android.systemui");
-                                mContext.sendBroadcastAsUser(intent,
-                                        new UserHandle(UserHandle.USER_CURRENT));
+                                sendBroadcastSafely(intent);
                             }
                         });
                 intent.putExtra(RecentsActivity.WAITING_FOR_WINDOW_ANIMATION_PARAM, true);
-                mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
-                        UserHandle.USER_CURRENT));
+                startActivitySafely(intent, opts.toBundle());
             }
         } catch (ActivityNotFoundException e) {
             Log.e(TAG, "Failed to launch RecentAppsIntent", e);
@@ -225,7 +231,7 @@
             Intent intent = new Intent(RecentsActivity.PRELOAD_INTENT);
             intent.setClassName("com.android.systemui",
                     "com.android.systemui.recent.RecentsPreloadReceiver");
-            mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+            sendBroadcastSafely(intent);
 
             RecentTasksLoader.getInstance(mContext).preloadFirstTask();
         }
@@ -239,7 +245,7 @@
             Intent intent = new Intent(RecentsActivity.CANCEL_PRELOAD_INTENT);
             intent.setClassName("com.android.systemui",
                     "com.android.systemui.recent.RecentsPreloadReceiver");
-            mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+            sendBroadcastSafely(intent);
 
             RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
         }
@@ -252,9 +258,25 @@
         } else {
             Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
             intent.setPackage("com.android.systemui");
-            mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+            sendBroadcastSafely(intent);
 
             RecentTasksLoader.getInstance(mContext).cancelPreloadingFirstTask();
         }
     }
+
+    /**
+     * Send broadcast only if BOOT_COMPLETED
+     */
+    private void sendBroadcastSafely(Intent intent) {
+        if (!mBootCompleted) return;
+        mContext.sendBroadcastAsUser(intent, new UserHandle(UserHandle.USER_CURRENT));
+    }
+
+    /**
+     * Start activity only if BOOT_COMPLETED
+     */
+    private void startActivitySafely(Intent intent, Bundle opts) {
+        if (!mBootCompleted) return;
+        mContext.startActivityAsUser(intent, opts, new UserHandle(UserHandle.USER_CURRENT));
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
index 8543b97..f2e322d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/AlternateRecentsComponent.java
@@ -44,6 +44,8 @@
 import android.view.WindowManager;
 import com.android.systemui.R;
 
+import java.util.ArrayList;
+import java.util.Iterator;
 import java.util.List;
 
 /** A proxy implementation for the recents component */
@@ -57,8 +59,11 @@
                 Resources res = mContext.getResources();
                 float statusBarHeight = res.getDimensionPixelSize(
                         com.android.internal.R.dimen.status_bar_height);
-                mFirstTaskRect = (Rect) msg.getData().getParcelable("taskRect");
-                mFirstTaskRect.offset(0, (int) statusBarHeight);
+                Bundle replyData = msg.getData().getParcelable(KEY_CONFIGURATION_DATA);
+                mSingleCountFirstTaskRect = replyData.getParcelable(KEY_SINGLE_TASK_STACK_RECT);
+                mSingleCountFirstTaskRect.offset(0, (int) statusBarHeight);
+                mMultipleCountFirstTaskRect = replyData.getParcelable(KEY_MULTIPLE_TASK_STACK_RECT);
+                mMultipleCountFirstTaskRect.offset(0, (int) statusBarHeight);
             }
         }
     }
@@ -89,12 +94,20 @@
         }
     }
 
-    final static int MSG_UPDATE_FOR_CONFIGURATION = 0;
-    final static int MSG_UPDATE_TASK_THUMBNAIL = 1;
-    final static int MSG_PRELOAD_TASKS = 2;
-    final static int MSG_CANCEL_PRELOAD_TASKS = 3;
-    final static int MSG_CLOSE_RECENTS = 4;
-    final static int MSG_TOGGLE_RECENTS = 5;
+    final public static int MSG_UPDATE_FOR_CONFIGURATION = 0;
+    final public static int MSG_UPDATE_TASK_THUMBNAIL = 1;
+    final public static int MSG_PRELOAD_TASKS = 2;
+    final public static int MSG_CANCEL_PRELOAD_TASKS = 3;
+    final public static int MSG_CLOSE_RECENTS = 4;
+    final public static int MSG_TOGGLE_RECENTS = 5;
+
+    final public static String EXTRA_ANIMATING_WITH_THUMBNAIL = "recents.animatingWithThumbnail";
+    final public static String KEY_CONFIGURATION_DATA = "recents.data.updateForConfiguration";
+    final public static String KEY_WINDOW_RECT = "recents.windowRect";
+    final public static String KEY_SYSTEM_INSETS = "recents.systemInsets";
+    final public static String KEY_SINGLE_TASK_STACK_RECT = "recents.singleCountTaskRect";
+    final public static String KEY_MULTIPLE_TASK_STACK_RECT = "recents.multipleCountTaskRect";
+
 
     final static int sMinToggleDelay = 425;
 
@@ -114,7 +127,8 @@
     RecentsServiceConnection mConnection = new RecentsServiceConnection();
 
     View mStatusBarView;
-    Rect mFirstTaskRect = new Rect();
+    Rect mSingleCountFirstTaskRect = new Rect();
+    Rect mMultipleCountFirstTaskRect = new Rect();
     long mLastToggleTime;
 
     public AlternateRecentsComponent(Context context) {
@@ -190,8 +204,8 @@
             // Try and update the recents configuration
             try {
                 Bundle data = new Bundle();
-                data.putParcelable("windowRect", rect);
-                data.putParcelable("systemInsets", new Rect(0, statusBarHeight, 0, 0));
+                data.putParcelable(KEY_WINDOW_RECT, rect);
+                data.putParcelable(KEY_SYSTEM_INSETS, new Rect(0, statusBarHeight, 0, 0));
                 Message msg = Message.obtain(null, MSG_UPDATE_FOR_CONFIGURATION, 0, 0);
                 msg.setData(data);
                 msg.replyTo = mMessenger;
@@ -221,24 +235,36 @@
                 return null;
             }
 
-            Bitmap thumbnail = ssp.getTaskThumbnail(t.persistentId);
-            return thumbnail;
+            return ssp.getTaskThumbnail(t.persistentId);
         }
         return null;
     }
 
-    /** Returns whether there is a first task */
-    boolean hasFirstTask() {
+    /** Returns whether there is are multiple recents tasks */
+    boolean hasMultipleRecentsTask(List<ActivityManager.RecentTaskInfo> tasks) {
+        // NOTE: Currently there's no method to get the number of non-home tasks, so we have to
+        // compute this ourselves
         SystemServicesProxy ssp = mSystemServicesProxy;
-        List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks(1,
-                UserHandle.CURRENT.getIdentifier());
-        for (ActivityManager.RecentTaskInfo t : tasks) {
+        Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator();
+        while (iter.hasNext()) {
+            ActivityManager.RecentTaskInfo t = iter.next();
+
             // Skip tasks in the home stack
             if (ssp.isInHomeStack(t.persistentId)) {
+                iter.remove();
                 continue;
             }
+        }
+        return (tasks.size() > 1);
+    }
 
-            return true;
+    /** Returns whether the base intent of the top task stack was launched with the flag
+     * Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS. */
+    boolean isTopTaskExcludeFromRecents(List<ActivityManager.RecentTaskInfo> tasks) {
+        if (tasks.size() > 0) {
+            ActivityManager.RecentTaskInfo t = tasks.get(0);
+            Console.log(t.baseIntent.toString());
+            return (t.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
         }
         return false;
     }
@@ -287,8 +313,10 @@
         // to launch the first task or dismiss itself
         SystemServicesProxy ssp = mSystemServicesProxy;
         List<ActivityManager.RunningTaskInfo> tasks = ssp.getRunningTasks(1);
+        boolean isTopTaskHome = false;
         if (!tasks.isEmpty()) {
-            ComponentName topActivity = tasks.get(0).topActivity;
+            ActivityManager.RunningTaskInfo topTask = tasks.get(0);
+            ComponentName topActivity = topTask.topActivity;
 
             // Check if the front most activity is recents
             if (topActivity.getPackageName().equals(sRecentsPackage) &&
@@ -311,16 +339,38 @@
                 mLastToggleTime = System.currentTimeMillis();
                 return;
             }
+
+            // Determine whether the top task is currently home
+            isTopTaskHome = ssp.isInHomeStack(topTask.id);
         }
 
-        // Otherwise, Recents is not the front-most activity and we should animate into it
-        Rect taskRect = mFirstTaskRect;
-        if (taskRect != null && taskRect.width() > 0 && taskRect.height() > 0 && hasFirstTask()) {
+        // Otherwise, Recents is not the front-most activity and we should animate into it.  If
+        // the activity at the root of the top task stack is excluded from recents, or if that
+        // task stack is in the home stack, then we just do a simple transition.  Otherwise, we
+        // animate to the rects defined by the Recents service, which can differ depending on the
+        // number of items in the list.
+        List<ActivityManager.RecentTaskInfo> recentTasks =
+                ssp.getRecentTasks(4, UserHandle.CURRENT.getIdentifier());
+        boolean hasMultipleTasks = hasMultipleRecentsTask(recentTasks);
+        boolean isTaskExcludedFromRecents = isTopTaskExcludeFromRecents(recentTasks);
+        Rect taskRect = hasMultipleTasks ? mMultipleCountFirstTaskRect : mSingleCountFirstTaskRect;
+        if (!isTopTaskHome && !isTaskExcludedFromRecents &&
+                (taskRect != null) && (taskRect.width() > 0) && (taskRect.height() > 0)) {
             // Loading from thumbnail
             Bitmap thumbnail;
             Bitmap firstThumbnail = loadFirstTaskThumbnail();
-            if (firstThumbnail == null) {
-                // Load the thumbnail from the screenshot
+            if (firstThumbnail != null) {// Create the thumbnail
+                thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
+                        Bitmap.Config.ARGB_8888);
+                int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
+                Canvas c = new Canvas(thumbnail);
+                c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
+                        new Rect(0, 0, taskRect.width(), taskRect.height()), null);
+                c.setBitmap(null);
+                // Recycle the old thumbnail
+                firstThumbnail.recycle();
+            } else {
+                // Load the thumbnail from the screenshot if can't get one from the system
                 WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
                 Display display = wm.getDefaultDisplay();
                 Bitmap screenshot = takeScreenshot(display);
@@ -328,35 +378,24 @@
                 int size = Math.min(screenshot.getWidth(), screenshot.getHeight());
                 int statusBarHeight = res.getDimensionPixelSize(
                         com.android.internal.R.dimen.status_bar_height);
-                thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
+                thumbnail = Bitmap.createBitmap(taskRect.width(), taskRect.height(),
                         Bitmap.Config.ARGB_8888);
                 Canvas c = new Canvas(thumbnail);
                 c.drawBitmap(screenshot, new Rect(0, statusBarHeight, size, statusBarHeight + size),
-                        new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
+                        new Rect(0, 0, taskRect.width(), taskRect.height()), null);
                 c.setBitmap(null);
-                // Recycle the old screenshot
+                // Recycle the temporary screenshot
                 screenshot.recycle();
-            } else {
-                // Create the thumbnail
-                thumbnail = Bitmap.createBitmap(mFirstTaskRect.width(), mFirstTaskRect.height(),
-                        Bitmap.Config.ARGB_8888);
-                int size = Math.min(firstThumbnail.getWidth(), firstThumbnail.getHeight());
-                Canvas c = new Canvas(thumbnail);
-                c.drawBitmap(firstThumbnail, new Rect(0, 0, size, size),
-                        new Rect(0, 0, mFirstTaskRect.width(), mFirstTaskRect.height()), null);
-                c.setBitmap(null);
-                // Recycle the old thumbnail
-                firstThumbnail.recycle();
             }
 
             ActivityOptions opts = ActivityOptions.makeThumbnailScaleDownAnimation(mStatusBarView,
-                    thumbnail, mFirstTaskRect.left, mFirstTaskRect.top, null);
-            startAlternateRecentsActivity(opts);
+                    thumbnail, taskRect.left, taskRect.top, null);
+            startAlternateRecentsActivity(opts, true);
         } else {
             ActivityOptions opts = ActivityOptions.makeCustomAnimation(mContext,
                     R.anim.recents_from_launcher_enter,
                     R.anim.recents_from_launcher_exit);
-            startAlternateRecentsActivity(opts);
+            startAlternateRecentsActivity(opts, false);
         }
 
         Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
@@ -365,11 +404,12 @@
     }
 
     /** Starts the recents activity */
-    void startAlternateRecentsActivity(ActivityOptions opts) {
+    void startAlternateRecentsActivity(ActivityOptions opts, boolean animatingWithThumbnail) {
         Intent intent = new Intent(sToggleRecentsAction);
         intent.setClassName(sRecentsPackage, sRecentsActivity);
         intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                 | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
+        intent.putExtra(EXTRA_ANIMATING_WITH_THUMBNAIL, animatingWithThumbnail);
         if (opts != null) {
             mContext.startActivityAsUser(intent, opts.toBundle(), new UserHandle(
                     UserHandle.USER_CURRENT));
diff --git a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
index b085211..95ab8e8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/BakedBezierInterpolator.java
@@ -24,9 +24,6 @@
      * P3 (1.0, 1.0)
      *
      * Values sampled with x at regular intervals between 0 and 1.
-     *
-     * These values were generated using:
-     *   ./scripts/bezier_interpolator_values_gen.py 0.4 0.2
      */
     private static final float[] VALUES = new float[] {
         0.0f, 0.0002f, 0.0009f, 0.0019f, 0.0036f, 0.0059f, 0.0086f, 0.0119f, 0.0157f, 0.0209f,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 86f188e..a996c1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -26,10 +26,12 @@
         public static final boolean Verbose = false;
 
         public static class App {
-            public static final boolean EnableTaskFiltering = true;
+            public static final boolean EnableTaskFiltering = false;
             public static final boolean EnableTaskStackClipping = false;
-            public static final boolean EnableToggleNewRecentsActivity = false;
-            // This disables the bitmap and icon caches to
+            public static final boolean EnableInfoPane = true;
+            public static final boolean EnableSearchButton = false;
+
+            // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // For debugging, this enables us to create mock recents tasks
             public static final boolean EnableSystemServicesProxy = false;
@@ -72,8 +74,6 @@
         public static class Window {
             // The dark background dim is set behind the empty recents view
             public static final float DarkBackgroundDim = 0.5f;
-            // The background dim is set behind the card stack
-            public static final float BackgroundDim = 0.35f;
         }
 
         public static class RecentsTaskLoader {
@@ -85,6 +85,9 @@
             public static final int TaskStackOverscrollRange = 150;
             public static final int FilterStartDelay = 25;
 
+            // The amount to inverse scale the movement if we are overscrolling
+            public static final float TouchOverscrollScaleFactor = 3f;
+
             // The padding will be applied to the smallest dimension, and then applied to all sides
             public static final float StackPaddingPct = 0.15f;
             // The overlap height relative to the task height
@@ -98,11 +101,8 @@
         }
 
         public static class TaskView {
-            public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
-            public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
-
-            public static final boolean UseRoundedCorners = false;
-            public static final float RoundedCornerRadiusDps = 3;
+            public static final boolean AnimateFrontTaskBarOnEnterRecents = true;
+            public static final boolean AnimateFrontTaskBarOnLeavingRecents = true;
         }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 64c67b1..71c45f2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -50,11 +50,7 @@
             String action = intent.getAction();
             Console.log(Constants.DebugFlags.App.SystemUIHandshake,
                     "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
-            if (action.equals(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY)) {
-                if (Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
-                    finish();
-                }
-            } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
+            if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
                 // Try and unfilter and filtered stacks
                 if (!mRecentsView.unfilterFilteredStacks()) {
                     // If there are no filtered stacks, dismiss recents and launch the first task
@@ -73,7 +69,12 @@
     };
 
     /** Updates the set of recent tasks */
-    void updateRecentsTasks() {
+    void updateRecentsTasks(Intent launchIntent) {
+        // Update the configuration based on the launch intent
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        config.launchedWithThumbnailAnimation = launchIntent.getBooleanExtra(
+                AlternateRecentsComponent.EXTRA_ANIMATING_WITH_THUMBNAIL, false);
+
         RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
         SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
         ArrayList<TaskStack> stacks = root.getStacks();
@@ -92,6 +93,12 @@
             getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         } else {
             mEmptyView.setVisibility(View.GONE);
+
+            // Un-dim the background
+            WindowManager.LayoutParams wlp = getWindow().getAttributes();
+            wlp.dimAmount = 0f;
+            getWindow().setAttributes(wlp);
+            getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
         }
     }
 
@@ -137,7 +144,7 @@
         setContentView(mContainerView);
 
         // Update the recent tasks
-        updateRecentsTasks();
+        updateRecentsTasks(getIntent());
     }
 
     @Override
@@ -157,7 +164,7 @@
         RecentsConfiguration.reinitialize(this);
 
         // Update the recent tasks
-        updateRecentsTasks();
+        updateRecentsTasks(intent);
     }
 
     @Override
@@ -185,7 +192,6 @@
         // Register the broadcast receiver to handle messages from our service
         IntentFilter filter = new IntentFilter();
         filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
-        filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
         registerReceiver(mServiceBroadcastReceiver, filter);
 
         // Register the broadcast receiver to handle messages when the screen is turned off
@@ -219,11 +225,6 @@
                 Console.AnsiRed);
         super.onStop();
 
-        // Finish the current recents activity after we have launched a task
-        if (mTaskLaunched && Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
-            finish();
-        }
-
         mVisible = false;
         mTaskLaunched = false;
     }
@@ -245,8 +246,18 @@
 
     @Override
     public void onBackPressed() {
-        if (!mRecentsView.unfilterFilteredStacks()) {
-            super.onBackPressed();
+        boolean interceptedByInfoPanelClose = false;
+
+        // Try and return from any open info panes
+        if (Constants.DebugFlags.App.EnableInfoPane) {
+            interceptedByInfoPanelClose = mRecentsView.closeOpenInfoPanes();
+        }
+
+        // If we haven't been intercepted already, then unfilter any stacks
+        if (!interceptedByInfoPanelClose) {
+            if (!mRecentsView.unfilterFilteredStacks()) {
+                super.onBackPressed();
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 94a655f..d54df13 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -39,6 +39,15 @@
 
     public int filteringCurrentViewsMinAnimDuration;
     public int filteringNewViewsMinAnimDuration;
+    public int taskBarEnterAnimDuration;
+    public int taskStackScrollDismissInfoPaneDistance;
+    public int taskStackMaxDim;
+    public int taskViewInfoPaneAnimDuration;
+    public int taskViewRoundedCornerRadiusPx;
+    public int searchBarSpaceHeightPx;
+    public int searchBarSpaceEdgeMarginsPx;
+
+    public boolean launchedWithThumbnailAnimation;
 
     /** Private constructor */
     private RecentsConfiguration() {}
@@ -76,12 +85,45 @@
                 res.getInteger(R.integer.recents_filter_animate_current_views_min_duration);
         filteringNewViewsMinAnimDuration =
                 res.getInteger(R.integer.recents_filter_animate_new_views_min_duration);
+        taskBarEnterAnimDuration =
+                res.getInteger(R.integer.recents_animate_task_bar_enter_duration);
+        taskStackScrollDismissInfoPaneDistance = res.getDimensionPixelSize(
+                R.dimen.recents_task_stack_scroll_dismiss_info_pane_distance);
+        taskStackMaxDim = res.getInteger(R.integer.recents_max_task_stack_view_dim);
+        taskViewInfoPaneAnimDuration =
+                res.getInteger(R.integer.recents_animate_task_view_info_pane_duration);
+        taskViewRoundedCornerRadiusPx =
+                res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+        searchBarSpaceHeightPx = res.getDimensionPixelSize(R.dimen.recents_search_bar_space_height);
+        searchBarSpaceEdgeMarginsPx =
+                res.getDimensionPixelSize(R.dimen.recents_search_bar_space_edge_margins);
     }
 
+    /** Updates the system insets */
     public void updateSystemInsets(Rect insets) {
         systemInsets.set(insets);
     }
 
+    /** Returns the search bar bounds in the specified orientation */
+    public void getSearchBarBounds(int width, int height,
+                                   Rect searchBarSpaceBounds, Rect searchBarBounds) {
+        // Return empty rects if search is not enabled
+        if (!Constants.DebugFlags.App.EnableSearchButton) {
+            searchBarSpaceBounds.set(0, 0, 0, 0);
+            searchBarBounds.set(0, 0, 0, 0);
+            return;
+        }
+
+        // Calculate the search bar bounds, and account for the system insets
+        int edgeMarginPx = searchBarSpaceEdgeMarginsPx;
+        int availableWidth = width - systemInsets.left - systemInsets.right;
+        searchBarSpaceBounds.set(0, 0, availableWidth, 2 * edgeMarginPx + searchBarSpaceHeightPx);
+
+        // Inset from the search bar space to get the search bar bounds
+        searchBarBounds.set(searchBarSpaceBounds);
+        searchBarBounds.inset(edgeMarginPx, edgeMarginPx);
+    }
+
     /** Converts from DPs to PXs */
     public int pxFromDp(float size) {
         return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 22363bb..36b761e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -26,6 +26,7 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.TaskStackView;
 import com.android.systemui.recents.views.TaskViewTransform;
@@ -50,36 +51,62 @@
         Context context = mContext.get();
         if (context == null) return;
 
-        if (msg.what == RecentsService.MSG_UPDATE_RECENTS_FOR_CONFIGURATION) {
+        if (msg.what == AlternateRecentsComponent.MSG_UPDATE_FOR_CONFIGURATION) {
             RecentsTaskLoader.initialize(context);
             RecentsConfiguration.reinitialize(context);
 
             try {
                 Bundle data = msg.getData();
-                Rect windowRect = (Rect) data.getParcelable("windowRect");
-                Rect systemInsets = (Rect) data.getParcelable("systemInsets");
+                Rect windowRect = data.getParcelable(AlternateRecentsComponent.KEY_WINDOW_RECT);
+                Rect systemInsets = data.getParcelable(AlternateRecentsComponent.KEY_SYSTEM_INSETS);
 
                 // Create a dummy task stack & compute the rect for the thumbnail to animate to
                 TaskStack stack = new TaskStack(context);
                 TaskStackView tsv = new TaskStackView(context, stack);
-                // Since the nav bar height is already accounted for in the windowRect, don't pass
-                // in a bottom inset
-                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
-                tsv.boundScroll();
-                TaskViewTransform transform = tsv.getStackTransform(0, tsv.getStackScroll());
-                Rect taskRect = new Rect(transform.rect);
+                Bundle replyData = new Bundle();
+                TaskViewTransform transform;
 
-                data.putParcelable("taskRect", taskRect);
+                // Get the search bar bounds so that we can account for its height in the children
+                Rect searchBarSpaceBounds = new Rect();
+                Rect searchBarBounds = new Rect();
+                RecentsConfiguration config = RecentsConfiguration.getInstance();
+                config.getSearchBarBounds(windowRect.width(), windowRect.height(),
+                        searchBarSpaceBounds, searchBarBounds);
+
+                // Calculate the target task rect for when there is one task
+                // NOTE: Since the nav bar height is already accounted for in the windowRect, don't
+                // pass in a bottom inset
+                stack.addTask(new Task());
+                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
+                        systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+                tsv.boundScroll();
+                transform = tsv.getStackTransform(0, tsv.getStackScroll());
+                transform.rect.offset(0, searchBarSpaceBounds.height());
+                replyData.putParcelable(AlternateRecentsComponent.KEY_SINGLE_TASK_STACK_RECT,
+                        new Rect(transform.rect));
+
+                // Also calculate the target task rect when there are multiple tasks
+                stack.addTask(new Task());
+                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top -
+                        systemInsets.bottom - searchBarSpaceBounds.height(), 0);
+                tsv.setStackScrollRaw(Integer.MAX_VALUE);
+                tsv.boundScroll();
+                transform = tsv.getStackTransform(1, tsv.getStackScroll());
+                transform.rect.offset(0, searchBarSpaceBounds.height());
+                replyData.putParcelable(AlternateRecentsComponent.KEY_MULTIPLE_TASK_STACK_RECT,
+                        new Rect(transform.rect));
+
+                data.putParcelable(AlternateRecentsComponent.KEY_CONFIGURATION_DATA, replyData);
                 Message reply = Message.obtain(null,
-                        RecentsService.MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
+                        AlternateRecentsComponent.MSG_UPDATE_FOR_CONFIGURATION, 0, 0);
                 reply.setData(data);
                 msg.replyTo.send(reply);
             } catch (RemoteException re) {
                 re.printStackTrace();
             }
-        } else if (msg.what == RecentsService.MSG_CLOSE_RECENTS) {
+        } else if (msg.what == AlternateRecentsComponent.MSG_CLOSE_RECENTS) {
             // Do nothing
-        } else if (msg.what == RecentsService.MSG_TOGGLE_RECENTS) {
+        } else if (msg.what == AlternateRecentsComponent.MSG_TOGGLE_RECENTS) {
             // Send a broadcast to toggle recents
             Intent intent = new Intent(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
             intent.setPackage(context.getPackageName());
@@ -96,14 +123,8 @@
 
 /* Service */
 public class RecentsService extends Service {
-    final static String ACTION_FINISH_RECENTS_ACTIVITY = "action_finish_recents_activity";
     final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
 
-    // XXX: This should be getting the message from recents definition
-    final static int MSG_UPDATE_RECENTS_FOR_CONFIGURATION = 0;
-    final static int MSG_CLOSE_RECENTS = 4;
-    final static int MSG_TOGGLE_RECENTS = 5;
-
     Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 754d956..52bba4a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -192,8 +192,9 @@
                                     " forceLoad: " + forceLoadTask);
                     // Load the application icon
                     if (loadIcon == null || forceLoadTask) {
-                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent());
-                        Drawable icon = ssp.getActivityIcon(info);
+                        ActivityInfo info = ssp.getActivityInfo(t.key.baseIntent.getComponent(),
+                                t.userId);
+                        Drawable icon = ssp.getActivityIcon(info, t.userId);
                         if (!mCancelled) {
                             if (icon != null) {
                                 Console.log(Constants.DebugFlags.App.TaskDataLoader,
@@ -358,18 +359,9 @@
         return mSystemServicesProxy;
     }
 
-    /** Reload the set of recent tasks */
-    SpaceNode reload(Context context, int preloadCount) {
-        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
-        Resources res = context.getResources();
-        ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
-        TaskStack stack = new TaskStack(context);
-        SpaceNode root = new SpaceNode(context);
-        root.setStack(stack);
-
+    private List<ActivityManager.RecentTaskInfo> getRecentTasks(Context context) {
         long t1 = System.currentTimeMillis();
 
-        // Get the recent tasks
         SystemServicesProxy ssp = mSystemServicesProxy;
         List<ActivityManager.RecentTaskInfo> tasks =
                 ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
@@ -397,15 +389,38 @@
             }
         }
 
+        return tasks;
+    }
+
+    /** Reload the set of recent tasks */
+    SpaceNode reload(Context context, int preloadCount) {
+        long t1 = System.currentTimeMillis();
+
+        Console.log(Constants.DebugFlags.App.TaskDataLoader, "[RecentsTaskLoader|reload]");
+        Resources res = context.getResources();
+        ArrayList<Task> tasksToForceLoad = new ArrayList<Task>();
+        TaskStack stack = new TaskStack(context);
+        SpaceNode root = new SpaceNode(context);
+        root.setStack(stack);
+
+        // Get the recent tasks
+        SystemServicesProxy ssp = mSystemServicesProxy;
+        List<ActivityManager.RecentTaskInfo> tasks = getRecentTasks(context);
+
         // Add each task to the task stack
         t1 = System.currentTimeMillis();
         int taskCount = tasks.size();
         for (int i = 0; i < taskCount; i++) {
             ActivityManager.RecentTaskInfo t = tasks.get(i);
-            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent());
+            ActivityInfo info = ssp.getActivityInfo(t.baseIntent.getComponent(), t.userId);
+            if (info == null) continue;
+
             String activityLabel = (t.activityLabel == null ? ssp.getActivityLabel(info) :
                     t.activityLabel.toString());
-            Bitmap activityIcon = t.activityIcon;
+            BitmapDrawable activityIcon = null;
+            if (t.activityIcon != null) {
+                activityIcon = new BitmapDrawable(res, t.activityIcon);
+            }
             boolean isForemostTask = (i == (taskCount - 1));
 
             // Create a new task
@@ -428,7 +443,7 @@
                     }
                 }
                 if (task.applicationIcon == null) {
-                    task.applicationIcon = ssp.getActivityIcon(info);
+                    task.applicationIcon = ssp.getActivityIcon(info, task.userId);
                     if (task.applicationIcon != null) {
                         mApplicationIconCache.put(task.key, task.applicationIcon);
                     } else {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
index 505238d..33ac0a8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/SystemServicesProxy.java
@@ -18,14 +18,25 @@
 
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.AppGlobals;
+import android.app.SearchManager;
+import android.content.ActivityNotFoundException;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.graphics.Bitmap;
+import android.graphics.Rect;
 import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.text.TextUtils;
+import android.util.Log;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -38,6 +49,9 @@
 public class SystemServicesProxy {
     ActivityManager mAm;
     PackageManager mPm;
+    IPackageManager mIpm;
+    UserManager mUm;
+    SearchManager mSm;
     String mPackage;
 
     Bitmap mDummyIcon;
@@ -46,6 +60,9 @@
     public SystemServicesProxy(Context context) {
         mAm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
         mPm = context.getPackageManager();
+        mUm = (UserManager) context.getSystemService(Context.USER_SERVICE);
+        mIpm = AppGlobals.getPackageManager();
+        mSm = (SearchManager) context.getSystemService(Context.SEARCH_SERVICE);
         mPackage = context.getPackageName();
 
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
@@ -142,14 +159,19 @@
         mAm.removeTask(taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
     }
 
-    /** Returns the activity info for a given component name */
-    public ActivityInfo getActivityInfo(ComponentName cn) {
-        if (mPm == null) return null;
+    /**
+     * Returns the activity info for a given component name.
+     * 
+     * @param ComponentName The component name of the activity.
+     * @param userId The userId of the user that this is for.
+     */
+    public ActivityInfo getActivityInfo(ComponentName cn, int userId) {
+        if (mIpm == null) return null;
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) return null;
 
         try {
-            return mPm.getActivityInfo(cn, PackageManager.GET_META_DATA);
-        } catch (PackageManager.NameNotFoundException e) {
+            return mIpm.getActivityInfo(cn, PackageManager.GET_META_DATA, userId);
+        } catch (RemoteException e) {
             e.printStackTrace();
             return null;
         }
@@ -167,15 +189,46 @@
         return info.loadLabel(mPm).toString();
     }
 
-    /** Returns the activity icon */
-    public Drawable getActivityIcon(ActivityInfo info) {
-        if (mPm == null) return null;
+    /**
+     * Returns the activity icon for the ActivityInfo for a user, badging if
+     * necessary.
+     */
+    public Drawable getActivityIcon(ActivityInfo info, int userId) {
+        if (mPm == null || mUm == null) return null;
 
         // If we are mocking, then return a mock label
         if (Constants.DebugFlags.App.EnableSystemServicesProxy) {
             return new ColorDrawable(0xFF666666);
         }
 
-        return info.loadIcon(mPm);
+        Drawable icon = info.loadIcon(mPm);
+        if (userId != UserHandle.myUserId()) {
+            icon = mUm.getBadgedDrawableForUser(icon, new UserHandle(userId));
+        }
+        return icon;
+    }
+
+
+    /**
+     * Composes an intent to launch the global search activity.
+     */
+    public Intent getGlobalSearchIntent(Rect sourceBounds) {
+        if (mSm == null) return null;
+
+        // Try and get the global search activity
+        ComponentName globalSearchActivity = mSm.getGlobalSearchActivity();
+        if (globalSearchActivity == null) return null;
+
+        // Bundle the source of the search
+        Bundle appSearchData = new Bundle();
+        appSearchData.putString("source", mPackage);
+
+        // Compose the intent and Start the search activity
+        Intent intent = new Intent(SearchManager.INTENT_ACTION_GLOBAL_SEARCH);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        intent.setComponent(globalSearchActivity);
+        intent.putExtra(SearchManager.APP_DATA, appSearchData);
+        intent.setSourceBounds(sourceBounds);
+        return intent;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
index a0ff3b7..1566a49 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/Task.java
@@ -18,6 +18,7 @@
 
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
 
 
@@ -37,41 +38,53 @@
     public static class TaskKey {
         public final int id;
         public final Intent baseIntent;
+        public final int userId;
 
-        public TaskKey(int id, Intent intent) {
+        public TaskKey(int id, Intent intent, int userId) {
             this.id = id;
             this.baseIntent = intent;
+            this.userId = userId;
         }
 
         @Override
         public boolean equals(Object o) {
-            return hashCode() == o.hashCode();
+            if (!(o instanceof TaskKey)) {
+                return false;
+            }
+            return id == ((TaskKey) o).id
+                    && userId == ((TaskKey) o).userId;
         }
 
         @Override
         public int hashCode() {
-            return id;
+            return (id << 5) + userId;
         }
 
         @Override
         public String toString() {
-            return "Task.Key: " + id + ", " + baseIntent.getComponent().getPackageName();
+            return "Task.Key: " + id + ", "
+                    + "u" + userId + ", "
+                    + baseIntent.getComponent().getPackageName();
         }
     }
 
     public TaskKey key;
     public Drawable applicationIcon;
+    public Drawable activityIcon;
     public String activityLabel;
-    public Bitmap activityIcon;
     public Bitmap thumbnail;
     public boolean isActive;
     public int userId;
 
     TaskCallbacks mCb;
 
+    public Task() {
+        // Only used by RecentsService for task rect calculations.
+    }
+
     public Task(int id, boolean isActive, Intent intent, String activityTitle,
-                Bitmap activityIcon, int userId) {
-        this.key = new TaskKey(id, intent);
+                BitmapDrawable activityIcon, int userId) {
+        this.key = new TaskKey(id, intent, userId);
         this.activityLabel = activityTitle;
         this.activityIcon = activityIcon;
         this.isActive = isActive;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index a0e5b6a..d2de185 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -43,7 +43,13 @@
         ArrayList<Task> prevFilteredTasks = new ArrayList<Task>(mFilteredTasks);
         mFilter = filter;
         updateFilteredTasks();
-        return !prevFilteredTasks.equals(mFilteredTasks);
+        if (!prevFilteredTasks.equals(mFilteredTasks)) {
+            return true;
+        } else {
+            // If the tasks are exactly the same pre/post filter, then just reset it
+            mFilter = null;
+            return false;
+        }
     }
 
     /** Removes the task filter and returns the previous touch state */
@@ -128,9 +134,9 @@
         /* Notifies when a task has been removed from the stack */
         public void onStackTaskRemoved(TaskStack stack, Task t);
         /** Notifies when the stack was filtered */
-        public void onStackFiltered(TaskStack newStack, ArrayList<Task> curStack, Task t);
+        public void onStackFiltered(TaskStack newStack, ArrayList<Task> curTasks, Task t);
         /** Notifies when the stack was un-filtered */
-        public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curStack);
+        public void onStackUnfiltered(TaskStack newStack, ArrayList<Task> curTasks);
     }
 
     Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index 141d870..a04cd3e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -17,15 +17,21 @@
 package com.android.systemui.recents.views;
 
 import android.app.ActivityOptions;
+import android.app.TaskStackBuilder;
 import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Rect;
+import android.net.Uri;
 import android.os.UserHandle;
+import android.provider.Settings;
+import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.View;
 import android.widget.FrameLayout;
+import android.widget.TextView;
 import com.android.systemui.recents.Console;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.RecentsConfiguration;
@@ -33,6 +39,7 @@
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
+import com.android.systemui.R;
 
 import java.util.ArrayList;
 
@@ -50,11 +57,16 @@
 
     // The space partitioning root of this container
     SpaceNode mBSP;
+    // Search bar view
+    View mSearchBar;
     // Recents view callbacks
     RecentsViewCallbacks mCb;
 
+    LayoutInflater mInflater;
+
     public RecentsView(Context context) {
         super(context);
+        mInflater = LayoutInflater.from(context);
         setWillNotDraw(false);
     }
 
@@ -68,12 +80,22 @@
         mBSP = n;
 
         // Create and add all the stacks for this partition of space.
+        boolean hasTasks = false;
         removeAllViews();
         ArrayList<TaskStack> stacks = mBSP.getStacks();
         for (TaskStack stack : stacks) {
             TaskStackView stackView = new TaskStackView(getContext(), stack);
             stackView.setCallbacks(this);
             addView(stackView);
+            hasTasks |= (stack.getTaskCount() > 0);
+        }
+
+        // Create the search bar (and hide it if we have no recent tasks)
+        if (Constants.DebugFlags.App.EnableSearchButton) {
+            createSearchBar();
+            if (!hasTasks) {
+                mSearchBar.setVisibility(View.GONE);
+            }
         }
     }
 
@@ -82,29 +104,45 @@
         // Get the first stack view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            TaskStackView stackView = (TaskStackView) getChildAt(i);
-            TaskStack stack = stackView.mStack;
-            ArrayList<Task> tasks = stack.getTasks();
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView) {
+                TaskStackView stackView = (TaskStackView) child;
+                TaskStack stack = stackView.mStack;
+                ArrayList<Task> tasks = stack.getTasks();
 
-            // Get the first task in the stack
-            if (!tasks.isEmpty()) {
-                Task task = tasks.get(tasks.size() - 1);
-                TaskView tv = null;
+                // Get the first task in the stack
+                if (!tasks.isEmpty()) {
+                    Task task = tasks.get(tasks.size() - 1);
+                    TaskView tv = null;
 
-                // Try and use the first child task view as the source of the launch animation
-                if (stackView.getChildCount() > 0) {
-                    TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
-                    if (stv.getTask() == task) {
-                        tv = stv;
+                    // Try and use the first child task view as the source of the launch animation
+                    if (stackView.getChildCount() > 0) {
+                        TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
+                        if (stv.getTask() == task) {
+                            tv = stv;
+                        }
                     }
+                    onTaskLaunched(stackView, tv, stack, task);
+                    return true;
                 }
-                onTaskLaunched(stackView, tv, stack, task);
-                return true;
             }
         }
         return false;
     }
 
+    /** Creates and adds the search bar */
+    void createSearchBar() {
+        // Create a temporary search bar
+        mSearchBar = mInflater.inflate(R.layout.recents_search_bar, this, false);
+        mSearchBar.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onSearchTriggered();
+            }
+        });
+        addView(mSearchBar);
+    }
+
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
         int width = MeasureSpec.getSize(widthMeasureSpec);
@@ -117,16 +155,26 @@
         Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
                 Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onMeasure");
 
-        // We measure our stack views sans the status bar.  It will handle the nav bar itself.
+        // Get the search bar bounds so that we can account for its height in the children
+        Rect searchBarSpaceBounds = new Rect();
+        Rect searchBarBounds = new Rect();
         RecentsConfiguration config = RecentsConfiguration.getInstance();
+        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+                searchBarSpaceBounds, searchBarBounds);
+        if (mSearchBar != null) {
+            mSearchBar.measure(MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.width(), widthMode),
+                    MeasureSpec.makeMeasureSpec(searchBarSpaceBounds.height(), heightMode));
+        }
+
+        // We measure our stack views sans the status bar.  It will handle the nav bar itself.
         int childWidth = width - config.systemInsets.right;
-        int childHeight = height - config.systemInsets.top;
+        int childHeight = height - config.systemInsets.top - searchBarSpaceBounds.height();
 
         // Measure each child
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() != GONE) {
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView && child.getVisibility() != GONE) {
                 child.measure(MeasureSpec.makeMeasureSpec(childWidth, widthMode),
                         MeasureSpec.makeMeasureSpec(childHeight, heightMode));
             }
@@ -142,18 +190,30 @@
         Console.logTraceTime(Constants.DebugFlags.App.TimeRecentsStartup,
                 Constants.DebugFlags.App.TimeRecentsStartupKey, "RecentsView.onLayout");
 
-        // We offset our stack views by the status bar height.  It will handle the nav bar itself.
+        // Get the search bar bounds so that we can account for its height in the children
+        Rect searchBarSpaceBounds = new Rect();
+        Rect searchBarBounds = new Rect();
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        top += config.systemInsets.top;
+        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+                searchBarSpaceBounds, searchBarBounds);
+        if (mSearchBar != null) {
+            mSearchBar.layout(config.systemInsets.left + searchBarSpaceBounds.left,
+                    config.systemInsets.top + searchBarSpaceBounds.top,
+                    config.systemInsets.left + mSearchBar.getMeasuredWidth(),
+                    config.systemInsets.top + mSearchBar.getMeasuredHeight());
+        }
+
+        // We offset our stack views by the status bar height.  It will handle the nav bar itself.
+        top += config.systemInsets.top + searchBarSpaceBounds.height();
 
         // Layout each child
         // XXX: Based on the space node for that task view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
-            final View child = getChildAt(i);
-            if (child.getVisibility() != GONE) {
-                final int width = child.getMeasuredWidth();
-                final int height = child.getMeasuredHeight();
+            View child = getChildAt(i);
+            if (child instanceof TaskStackView && child.getVisibility() != GONE) {
+                int width = child.getMeasuredWidth();
+                int height = child.getMeasuredHeight();
                 child.layout(left, top, left + width, top + height);
             }
         }
@@ -179,6 +239,24 @@
         return true;
     }
 
+    /** Closes any open info panes */
+    public boolean closeOpenInfoPanes() {
+        if (mBSP != null) {
+            // Get the first stack view
+            int childCount = getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                View child = getChildAt(i);
+                if (child instanceof TaskStackView) {
+                    TaskStackView stackView = (TaskStackView) child;
+                    if (stackView.closeOpenInfoPanes()) {
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
+
     /** Unfilters any filtered stacks */
     public boolean unfilterFilteredStacks() {
         if (mBSP != null) {
@@ -206,6 +284,9 @@
             mCb.onTaskLaunching();
         }
 
+        // Close any open info panes
+        closeOpenInfoPanes();
+
         final Runnable launchRunnable = new Runnable() {
             @Override
             public void run() {
@@ -245,7 +326,6 @@
                             b, offsetX, offsetY);
                 }
 
-
                 if (task.isActive) {
                     // Bring an active task to the foreground
                     RecentsTaskLoader.getInstance().getSystemServicesProxy()
@@ -277,10 +357,41 @@
                 Constants.DebugFlags.App.TimeRecentsLaunchKey, "onTaskLaunched");
 
         // Launch the app right away if there is no task view, otherwise, animate the icon out first
-        if (tv == null || !Constants.Values.TaskView.AnimateFrontTaskIconOnLeavingRecents) {
+        if (tv == null || !Constants.Values.TaskView.AnimateFrontTaskBarOnLeavingRecents) {
             post(launchRunnable);
         } else {
             tv.animateOnLeavingRecents(launchRunnable);
         }
     }
+
+    @Override
+    public void onTaskAppInfoLaunched(Task t) {
+        // Create a new task stack with the application info details activity
+        Intent baseIntent = t.key.baseIntent;
+        Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
+                Uri.fromParts("package", baseIntent.getComponent().getPackageName(), null));
+        intent.setComponent(intent.resolveActivity(getContext().getPackageManager()));
+        TaskStackBuilder.create(getContext())
+                .addNextIntentWithParentStack(intent).startActivities();
+    }
+
+    public void onSearchTriggered() {
+        // Get the search bar source bounds
+        Rect searchBarSpaceBounds = new Rect();
+        Rect searchBarBounds = new Rect();
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        config.getSearchBarBounds(getMeasuredWidth(), getMeasuredHeight(),
+                searchBarSpaceBounds, searchBarBounds);
+
+        // Get the search intent and start it
+        Intent searchIntent = RecentsTaskLoader.getInstance().getSystemServicesProxy()
+                .getGlobalSearchIntent(searchBarBounds);
+        if (searchIntent != null) {
+            try {
+                getContext().startActivity(searchIntent);
+            } catch (ActivityNotFoundException anfe) {
+                Console.logError(getContext(), "Could not start Search activity");
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index c9a6d67..124f11e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -31,7 +31,6 @@
     Task mTask;
 
     ImageView mApplicationIcon;
-    ImageView mActivityIcon;
     TextView mActivityDescription;
 
     public TaskBarView(Context context) {
@@ -54,23 +53,22 @@
     protected void onFinishInflate() {
         // Initialize the icon and description views
         mApplicationIcon = (ImageView) findViewById(R.id.application_icon);
-        mActivityIcon = (ImageView) findViewById(R.id.activity_icon);
         mActivityDescription = (TextView) findViewById(R.id.activity_description);
     }
 
     /** Binds the bar view to the task */
     void rebindToTask(Task t, boolean animate) {
         mTask = t;
-        if (t.applicationIcon != null) {
+        // If an activity icon is defined, then we use that as the primary icon to show in the bar,
+        // otherwise, we fall back to the application icon
+        if (t.activityIcon != null) {
+            mApplicationIcon.setImageDrawable(t.activityIcon);
+        } else if (t.applicationIcon != null) {
             mApplicationIcon.setImageDrawable(t.applicationIcon);
-            mActivityDescription.setText(t.activityLabel);
-            if (t.activityIcon != null) {
-                mActivityIcon.setImageBitmap(t.activityIcon);
-                mActivityIcon.setVisibility(View.VISIBLE);
-            }
-            if (animate) {
-                // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
-            }
+        }
+        mActivityDescription.setText(t.activityLabel);
+        if (animate) {
+            // XXX: Investigate how expensive it will be to create a second bitmap and crossfade
         }
     }
 
@@ -78,8 +76,6 @@
     void unbindFromTask() {
         mTask = null;
         mApplicationIcon.setImageDrawable(null);
-        mActivityIcon.setImageBitmap(null);
-        mActivityIcon.setVisibility(View.INVISIBLE);
         mActivityDescription.setText("");
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
new file mode 100644
index 0000000..a81d01c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskInfoView.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.recents.views;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Path;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.widget.Button;
+import android.widget.FrameLayout;
+import com.android.systemui.R;
+import com.android.systemui.recents.BakedBezierInterpolator;
+import com.android.systemui.recents.Utilities;
+
+
+/* The task info view */
+class TaskInfoView extends FrameLayout {
+
+    Button mAppInfoButton;
+
+    // Circular clip animation
+    boolean mCircularClipEnabled;
+    Path mClipPath = new Path();
+    float mClipRadius;
+    float mMaxClipRadius;
+    Point mClipOrigin = new Point();
+    ObjectAnimator mCircularClipAnimator;
+
+    public TaskInfoView(Context context) {
+        this(context, null);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr) {
+        this(context, attrs, defStyleAttr, 0);
+    }
+
+    public TaskInfoView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        // Initialize the buttons on the info panel
+        mAppInfoButton = (Button) findViewById(R.id.task_view_app_info_button);
+    }
+
+    /** Updates the positions of each of the items to fit in the rect specified */
+    void updateContents(Rect visibleRect) {
+        // Offset the app info button
+        mAppInfoButton.setTranslationY(visibleRect.top +
+                (visibleRect.height() - mAppInfoButton.getMeasuredHeight()) / 2);
+    }
+
+    /** Sets the circular clip radius on this panel */
+    public void setCircularClipRadius(float r) {
+        mClipRadius = r;
+        invalidate();
+    }
+
+    /** Gets the circular clip radius on this panel */
+    public float getCircularClipRadius() {
+        return mClipRadius;
+    }
+
+    /** Animates the circular clip radius on the icon */
+    void animateCircularClip(Point o, float fromRadius, float toRadius,
+                             final Runnable postRunnable, boolean animateInContent) {
+        if (mCircularClipAnimator != null) {
+            mCircularClipAnimator.cancel();
+        }
+
+        // Calculate the max clip radius to each of the corners
+        int w = getMeasuredWidth() - o.x;
+        int h = getMeasuredHeight() - o.y;
+        // origin to tl, tr, br, bl
+        mMaxClipRadius = (int) Math.ceil(Math.sqrt(o.x * o.x + o.y * o.y));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + o.y * o.y)));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(w * w + h * h)));
+        mMaxClipRadius = (int) Math.max(mMaxClipRadius, Math.ceil(Math.sqrt(o.x * o.x + h * h)));
+
+        mClipOrigin.set(o.x, o.y);
+        mClipRadius = fromRadius;
+        int duration = Utilities.calculateTranslationAnimationDuration((int) mMaxClipRadius);
+        mCircularClipAnimator = ObjectAnimator.ofFloat(this, "circularClipRadius", toRadius);
+        mCircularClipAnimator.setDuration(duration);
+        mCircularClipAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
+        mCircularClipAnimator.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                mCircularClipEnabled = false;
+                if (postRunnable != null) {
+                    postRunnable.run();
+                }
+            }
+        });
+        mCircularClipAnimator.start();
+        mCircularClipEnabled = true;
+
+        if (animateInContent) {
+            animateAppInfoButtonIn(duration);
+        }
+    }
+
+    /** Cancels the circular clip animation. */
+    void cancelCircularClipAnimation() {
+        if (mCircularClipAnimator != null) {
+            mCircularClipAnimator.cancel();
+        }
+    }
+
+    void animateAppInfoButtonIn(int duration) {
+        mAppInfoButton.setScaleX(0.75f);
+        mAppInfoButton.setScaleY(0.75f);
+        mAppInfoButton.animate()
+                .scaleX(1f)
+                .scaleY(1f)
+                .setDuration(duration)
+                .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                .withLayer()
+                .start();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        int saveCount = 0;
+        if (mCircularClipEnabled) {
+            saveCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+            mClipPath.reset();
+            mClipPath.addCircle(mClipOrigin.x, mClipOrigin.y, mClipRadius * mMaxClipRadius,
+                    Path.Direction.CW);
+            canvas.clipPath(mClipPath);
+        }
+        super.draw(canvas);
+        if (mCircularClipEnabled) {
+            canvas.restoreToCount(saveCount);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index c9a491e..0a8e76f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -26,6 +26,7 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.util.Pair;
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
@@ -45,16 +46,18 @@
 import com.android.systemui.recents.model.TaskStack;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 
 
 /* The visual representation of a task stack view */
 public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
         TaskView.TaskViewCallbacks, ViewPool.ViewPoolConsumer<TaskView, Task>,
-        View.OnClickListener {
+        View.OnClickListener, View.OnLongClickListener {
 
     /** The TaskView callbacks */
     interface TaskStackViewCallbacks {
         public void onTaskLaunched(TaskStackView stackView, TaskView tv, TaskStack stack, Task t);
+        public void onTaskAppInfoLaunched(Task t);
     }
 
     TaskStack mStack;
@@ -73,12 +76,10 @@
     int mMinScroll;
     int mMaxScroll;
     int mStashedScroll;
+    int mLastInfoPaneStackScroll;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
 
-    // Filtering
-    AnimatorSet mFilterChildrenAnimator;
-
     // Optimizations
     int mHwLayersRefCount;
     int mStackViewsAnimationDuration;
@@ -171,7 +172,7 @@
             transform.visible = false;
         } else {
             transform.rect.offset(0, transform.translationY);
-            Utilities.scaleRectAboutCenter(transform.rect, scale);
+            Utilities.scaleRectAboutCenter(transform.rect, transform.scale);
             transform.visible = Rect.intersects(mRect, transform.rect);
         }
         transform.t = t;
@@ -282,6 +283,17 @@
     public void setStackScroll(int value) {
         mStackScroll = value;
         requestSynchronizeStackViewsWithModel();
+
+        // Close any open info panes if the user has scrolled away from them
+        boolean isAnimatingScroll = (mScrollAnimator != null && mScrollAnimator.isRunning());
+        if (mLastInfoPaneStackScroll > -1 && !isAnimatingScroll) {
+            RecentsConfiguration config = RecentsConfiguration.getInstance();
+            if (Math.abs(mStackScroll - mLastInfoPaneStackScroll) >
+                    config.taskStackScrollDismissInfoPaneDistance) {
+                // Close any open info panes
+                closeOpenInfoPanes();
+            }
+        }
     }
     /** Sets the current stack scroll without synchronizing the stack view with the model */
     public void setStackScrollRaw(int value) {
@@ -301,19 +313,24 @@
             // Enable hw layers on the stack
             addHwLayersRefCount("animateBoundScroll");
 
-            // Abort any current animations
-            abortScroller();
-            abortBoundScrollAnimation();
-
             // Start a new scroll animation
-            animateScroll(curScroll, newScroll);
-            mScrollAnimator.start();
+            animateScroll(curScroll, newScroll, new Runnable() {
+                @Override
+                public void run() {
+                    // Disable hw layers on the stack
+                    decHwLayersRefCount("animateBoundScroll");
+                }
+            });
         }
         return mScrollAnimator;
     }
 
     /** Animates the stack scroll */
-    void animateScroll(int curScroll, int newScroll) {
+    void animateScroll(int curScroll, int newScroll, final Runnable postRunnable) {
+        // Abort any current animations
+        abortScroller();
+        abortBoundScrollAnimation();
+
         mScrollAnimator = ObjectAnimator.ofInt(this, "stackScroll", curScroll, newScroll);
         mScrollAnimator.setDuration(Utilities.calculateTranslationAnimationDuration(newScroll -
                 curScroll, 250));
@@ -327,20 +344,23 @@
         mScrollAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                // Disable hw layers on the stack
-                decHwLayersRefCount("animateBoundScroll");
+                if (postRunnable != null) {
+                    postRunnable.run();
+                }
+                mScrollAnimator.removeAllListeners();
             }
         });
+        mScrollAnimator.start();
     }
 
     /** Aborts any current stack scrolls */
     void abortBoundScrollAnimation() {
         if (mScrollAnimator != null) {
             mScrollAnimator.cancel();
-            mScrollAnimator.removeAllListeners();
         }
     }
 
+    /** Aborts the scroller and any current fling */
     void abortScroller() {
         if (!mScroller.isFinished()) {
             // Abort the scroller
@@ -375,9 +395,12 @@
         return false;
     }
 
-    /** Returns whether the current scroll is out of bounds */
+    /** Returns whether the specified scroll is out of bounds */
+    boolean isScrollOutOfBounds(int scroll) {
+        return (scroll < mMinScroll) || (scroll > mMaxScroll);
+    }
     boolean isScrollOutOfBounds() {
-        return (getStackScroll() < 0) || (getStackScroll() > mMaxScroll);
+        return isScrollOutOfBounds(getStackScroll());
     }
 
     /** Updates the min and max virtual scroll bounds */
@@ -388,8 +411,14 @@
         int stackHeight = mStackRectSansPeek.height();
         int maxScrollHeight = taskHeight + (int) ((numTasks - 1) *
                 Constants.Values.TaskStackView.StackOverlapPct * taskHeight);
-        mMinScroll = Math.min(stackHeight, maxScrollHeight) - stackHeight;
-        mMaxScroll = maxScrollHeight - stackHeight;
+
+        if (numTasks <= 1) {
+            // If there is only one task, then center the task in the stack rect (sans peek)
+            mMinScroll = mMaxScroll = -(stackHeight - taskHeight) / 2;
+        } else {
+            mMinScroll = Math.min(stackHeight, maxScrollHeight) - stackHeight;
+            mMaxScroll = maxScrollHeight - stackHeight;
+        }
 
         // Debug logging
         if (Constants.DebugFlags.UI.MeasureAndLayout) {
@@ -402,6 +431,21 @@
         }
     }
 
+    /** Closes any open info panes. */
+    boolean closeOpenInfoPanes() {
+        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            TaskView tv = (TaskView) getChildAt(i);
+            if (tv.isInfoPaneVisible()) {
+                tv.hideInfoPane();
+                return true;
+            }
+        }
+        return false;
+    }
+
     /** Enables the hw layers and increments the hw layer requirement ref count */
     void addHwLayersRefCount(String reason) {
         Console.log(Constants.DebugFlags.UI.HwLayers,
@@ -479,8 +523,8 @@
                 // Clip against the next view (if we aren't animating its alpha)
                 nextTv = (TaskView) getChildAt(curIndex + 1);
                 if (nextTv.getAlpha() == 1f) {
-                    Rect curRect = tv.getClippingRect(mTmpRect, false);
-                    Rect nextRect = nextTv.getClippingRect(mTmpRect2, true);
+                    Rect curRect = tv.getClippingRect(mTmpRect);
+                    Rect nextRect = nextTv.getClippingRect(mTmpRect2);
                     RecentsConfiguration config = RecentsConfiguration.getInstance();
                     // The hit rects are relative to the task view, which needs to be offset by the
                     // system bar height
@@ -515,7 +559,14 @@
 
         int smallestDimension = Math.min(width, height);
         int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f);
-        mStackRect.inset(padding, padding);
+        if (Constants.DebugFlags.App.EnableSearchButton) {
+            // Don't need to pad the top since we have some padding on the search bar already
+            mStackRect.left += padding;
+            mStackRect.right -= padding;
+            mStackRect.bottom -= padding;
+        } else {
+            mStackRect.inset(padding, padding);
+        }
         mStackRectSansPeek.set(mStackRect);
         mStackRectSansPeek.top += Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height();
 
@@ -523,9 +574,9 @@
         int minHeight = (int) (mStackRect.height() -
                 (Constants.Values.TaskStackView.StackPeekHeightPct * mStackRect.height()));
         int size = Math.min(minHeight, Math.min(mStackRect.width(), mStackRect.height()));
-        int centerX = mStackRect.centerX();
-        mTaskRect.set(mStackRect.left, mStackRectSansPeek.top,
-                mStackRect.right, mStackRectSansPeek.top + size);
+        int left = mStackRect.left + (mStackRect.width() - size) / 2;
+        mTaskRect.set(left, mStackRectSansPeek.top,
+                left + size, mStackRectSansPeek.top + size);
 
         // Update the scroll bounds
         updateMinMaxScroll(false);
@@ -558,8 +609,9 @@
             requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
 
-            // Animate the icon of the first task view
-            if (Constants.Values.TaskView.AnimateFrontTaskIconOnEnterRecents) {
+            // Animate the task bar of the first task view
+            if (config.launchedWithThumbnailAnimation &&
+                    Constants.Values.TaskView.AnimateFrontTaskBarOnEnterRecents) {
                 TaskView tv = (TaskView) getChildAt(getChildCount() - 1);
                 if (tv != null) {
                     tv.animateOnEnterRecents();
@@ -639,163 +691,21 @@
         requestSynchronizeStackViewsWithModel(Utilities.calculateTranslationAnimationDuration(movement));
     }
 
-    @Override
-    public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curStack,
-                                Task filteredTask) {
-        // NOTE: This code assumes that the current (unfiltered) stack is a superset of the new
-        // (filtered) stack
-        // XXX: Use HW Layers
-
-        // Stash the scroll and filtered task for us to restore to when we unfilter
-        mStashedScroll = getStackScroll();
-
-        // Compute the transforms of the items in the current stack
-        final ArrayList<TaskViewTransform> curTaskTransforms =
-                getStackTransforms(curStack, mStashedScroll, null, true);
-
-        // Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
-        updateMinMaxScroll(false);
-        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
-        setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
-        boundScrollRaw();
-
-        // Compute the transforms of the items in the new stack after setting the new scroll
-        final ArrayList<TaskViewTransform> taskTransforms =
-                getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
-
-        // Animate all of the existing views on screen either out of view (if they are not visible
-        // in the new stack) or to their final positions in the new stack
-        final ArrayList<TaskView> childrenToReturnToPool = new ArrayList<TaskView>();
-        final ArrayList<Task> tasks = mStack.getTasks();
-        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
-        int childCount = getChildCount();
-        int movement = 0;
-        for (int i = 0; i < childCount; i++) {
-            TaskView tv = (TaskView) getChildAt(i);
-            Task task = tv.getTask();
-            TaskViewTransform toTransform;
-            int taskIndex = tasks.indexOf(task);
-
-            boolean willBeInvisible = (taskIndex < 0) || !taskTransforms.get(taskIndex).visible;
-            if (willBeInvisible) {
-                // Compose a new transform that fades and slides the task out of view
-                TaskViewTransform fromTransform = curTaskTransforms.get(curStack.indexOf(task));
-                toTransform = new TaskViewTransform(fromTransform);
-                tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
-                tv.prepareTaskTransformForFilterTaskHidden(toTransform);
-
-                childrenToReturnToPool.add(tv);
-            } else {
-                toTransform = taskTransforms.get(taskIndex);
-
-                // Use the movement of the visible views to calculate the duration of the animation
-                movement = Math.max(movement,
-                        Math.abs(toTransform.translationY - (int) tv.getTranslationY()));
-            }
-            childViewAnims.add(tv.getAnimatorToTaskTransform(toTransform));
-        }
-
-        // Cancel the previous animation
-        if (mFilterChildrenAnimator != null) {
-            mFilterChildrenAnimator.cancel();
-            mFilterChildrenAnimator.removeAllListeners();
-        }
-
-        // Create a new animation for the existing children
-        final RecentsConfiguration config = RecentsConfiguration.getInstance();
-        mFilterChildrenAnimator = new AnimatorSet();
-        mFilterChildrenAnimator.setDuration(
-                Utilities.calculateTranslationAnimationDuration(movement,
-                        config.filteringCurrentViewsMinAnimDuration));
-        mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
-        mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
-            boolean isCancelled;
-
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                isCancelled = true;
-            }
-
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (isCancelled) return;
-
-                // Return all the removed children to the view pool
-                for (TaskView tv : childrenToReturnToPool) {
-                    mViewPool.returnViewToPool(tv);
-                }
-
-                // For views that are not already visible, animate them in
-                ArrayList<Animator> newViewsAnims = new ArrayList<Animator>();
-                int taskCount = tasks.size();
-                int movement = 0;
-                int offset = 0;
-                for (int i = 0; i < taskCount; i++) {
-                    Task task = tasks.get(i);
-                    TaskViewTransform toTransform = taskTransforms.get(i);
-                    if (toTransform.visible) {
-                        TaskViewTransform fromTransform =
-                                curTaskTransforms.get(curStack.indexOf(task));
-                        TaskView tv = getChildViewForTask(task);
-                        if (tv == null) {
-                            tv = mViewPool.pickUpViewFromPool(task, task);
-                            // Compose a new transform that fades and slides the new task in
-                            fromTransform = new TaskViewTransform(toTransform);
-                            tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
-                            tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
-
-                            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
-                            anim.setStartDelay(offset *
-                                    Constants.Values.TaskStackView.FilterStartDelay);
-                            newViewsAnims.add(anim);
-
-                            // Use the movement of the newly visible views to calculate the duration
-                            // of the animation
-                            movement = Math.max(movement, Math.abs(toTransform.translationY -
-                                    fromTransform.translationY));
-                            offset++;
-                        }
-                    }
-
-                    // Animate the new views in
-                    mFilterChildrenAnimator = new AnimatorSet();
-                    mFilterChildrenAnimator.setDuration(
-                            Utilities.calculateTranslationAnimationDuration(movement,
-                                    config.filteringNewViewsMinAnimDuration));
-                    mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
-                    mFilterChildrenAnimator.playTogether(newViewsAnims);
-                    mFilterChildrenAnimator.start();
-                }
-                invalidate();
-            }
-        });
-        mFilterChildrenAnimator.playTogether(childViewAnims);
-        mFilterChildrenAnimator.start();
-    }
-
-    @Override
-    public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curStack) {
-        // Compute the transforms of the items in the current stack
-        final int curScroll = getStackScroll();
-        final ArrayList<TaskViewTransform> curTaskTransforms =
-                getStackTransforms(curStack, curScroll, null, true);
-
-        // Restore the stashed scroll
-        updateMinMaxScroll(false);
-        setStackScrollRaw(mStashedScroll);
-        boundScrollRaw();
-
-        // Compute the transforms of the items in the new stack after restoring the stashed scroll
-        final ArrayList<TaskViewTransform> taskTransforms =
-                getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
-
+    /**
+     * Creates the animations for all the children views that need to be removed or to move views
+     * to their un/filtered position when we are un/filtering a stack, and returns the duration
+     * for these animations.
+     */
+    int getExitTransformsForFilterAnimation(ArrayList<Task> curTasks,
+                        ArrayList<TaskViewTransform> curTaskTransforms,
+                        ArrayList<Task> tasks, ArrayList<TaskViewTransform> taskTransforms,
+                        HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut,
+                        ArrayList<TaskView> childrenToRemoveOut,
+                        RecentsConfiguration config) {
         // Animate all of the existing views out of view (if they are not in the visible range in
         // the new stack) or to their final positions in the new stack
-        final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
-        final ArrayList<Task> tasks = mStack.getTasks();
-        ArrayList<Animator> childViewAnims = new ArrayList<Animator>();
-        int childCount = getChildCount();
         int movement = 0;
+        int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskView tv = (TaskView) getChildAt(i);
             Task task = tv.getTask();
@@ -805,104 +715,172 @@
             // If the view is no longer visible, then we should just animate it out
             boolean willBeInvisible = taskIndex < 0 || !taskTransforms.get(taskIndex).visible;
             if (willBeInvisible) {
-                toTransform = new TaskViewTransform(taskTransforms.get(taskIndex));
+                if (taskIndex < 0) {
+                    toTransform = curTaskTransforms.get(curTasks.indexOf(task));
+                } else {
+                    toTransform = new TaskViewTransform(taskTransforms.get(taskIndex));
+                }
                 tv.prepareTaskTransformForFilterTaskVisible(toTransform);
-                childrenToRemove.add(tv);
+                childrenToRemoveOut.add(tv);
             } else {
                 toTransform = taskTransforms.get(taskIndex);
                 // Use the movement of the visible views to calculate the duration of the animation
                 movement = Math.max(movement, Math.abs(toTransform.translationY -
                         (int) tv.getTranslationY()));
             }
-
-            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
-            childViewAnims.add(anim);
+            childViewTransformsOut.put(tv, new Pair(0, toTransform));
         }
+        return Utilities.calculateTranslationAnimationDuration(movement,
+                config.filteringCurrentViewsMinAnimDuration);
+    }
 
-        // Cancel the previous animation
-        if (mFilterChildrenAnimator != null) {
-            mFilterChildrenAnimator.cancel();
-            mFilterChildrenAnimator.removeAllListeners();
+    /**
+     * Creates the animations for all the children views that need to be animated in when we are
+     * un/filtering a stack, and returns the duration for these animations.
+     */
+    int getEnterTransformsForFilterAnimation(ArrayList<Task> tasks,
+                         ArrayList<TaskViewTransform> taskTransforms,
+                         HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransformsOut,
+                         RecentsConfiguration config) {
+        int offset = 0;
+        int movement = 0;
+        int taskCount = tasks.size();
+        for (int i = taskCount - 1; i >= 0; i--) {
+            Task task = tasks.get(i);
+            TaskViewTransform toTransform = taskTransforms.get(i);
+            if (toTransform.visible) {
+                TaskView tv = getChildViewForTask(task);
+                if (tv == null) {
+                    // For views that are not already visible, animate them in
+                    tv = mViewPool.pickUpViewFromPool(task, task);
+
+                    // Compose a new transform to fade and slide the new task in
+                    TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
+                    tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
+                    tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
+
+                    int startDelay = offset *
+                            Constants.Values.TaskStackView.FilterStartDelay;
+                    childViewTransformsOut.put(tv, new Pair(startDelay, toTransform));
+
+                    // Use the movement of the new views to calculate the duration of the animation
+                    movement = Math.max(movement,
+                            Math.abs(toTransform.translationY - fromTransform.translationY));
+                    offset++;
+                }
+            }
         }
+        return Utilities.calculateTranslationAnimationDuration(movement,
+                config.filteringNewViewsMinAnimDuration);
+    }
 
-        // Create a new animation for the existing children
+    /** Orchestrates the animations of the current child views and any new views. */
+    void doFilteringAnimation(ArrayList<Task> curTasks,
+                              ArrayList<TaskViewTransform> curTaskTransforms,
+                              final ArrayList<Task> tasks,
+                              final ArrayList<TaskViewTransform> taskTransforms) {
         final RecentsConfiguration config = RecentsConfiguration.getInstance();
-        mFilterChildrenAnimator = new AnimatorSet();
-        mFilterChildrenAnimator.setDuration(
-                Utilities.calculateTranslationAnimationDuration(movement,
-                        config.filteringCurrentViewsMinAnimDuration));
-        mFilterChildrenAnimator.setInterpolator(BakedBezierInterpolator.INSTANCE);
-        mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
-            boolean isCancelled;
 
-            @Override
-            public void onAnimationCancel(Animator animation) {
-                isCancelled = true;
-            }
+        // Calculate the transforms to animate out all the existing views if they are not in the
+        // new visible range (or to their final positions in the stack if they are)
+        final ArrayList<TaskView> childrenToRemove = new ArrayList<TaskView>();
+        final HashMap<TaskView, Pair<Integer, TaskViewTransform>> childViewTransforms =
+                new HashMap<TaskView, Pair<Integer, TaskViewTransform>>();
+        int duration = getExitTransformsForFilterAnimation(curTasks, curTaskTransforms, tasks,
+                taskTransforms, childViewTransforms, childrenToRemove, config);
 
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                if (isCancelled) return;
+        // If all the current views are in the visible range of the new stack, then don't wait for
+        // views to animate out and animate all the new views into their place
+        final boolean unifyNewViewAnimation = childrenToRemove.isEmpty();
+        if (unifyNewViewAnimation) {
+            int inDuration = getEnterTransformsForFilterAnimation(tasks, taskTransforms,
+                    childViewTransforms, config);
+            duration = Math.max(duration, inDuration);
+        }
 
-                // Return all the removed children to the view pool
-                for (TaskView tv : childrenToRemove) {
-                    mViewPool.returnViewToPool(tv);
-                }
+        // Animate all the views to their final transforms
+        for (final TaskView tv : childViewTransforms.keySet()) {
+            Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv);
+            tv.animate().cancel();
+            tv.animate()
+                    .setStartDelay(t.first)
+                    .withEndAction(new Runnable() {
+                        @Override
+                        public void run() {
+                            childViewTransforms.remove(tv);
+                            if (childViewTransforms.isEmpty()) {
+                                // Return all the removed children to the view pool
+                                for (TaskView tv : childrenToRemove) {
+                                    mViewPool.returnViewToPool(tv);
+                                }
 
-                // Increment the hw layers ref count
-                addHwLayersRefCount("unfilteredNewViews");
-
-                // For views that are not already visible, animate them in
-                ArrayList<Animator> newViewAnims = new ArrayList<Animator>();
-                int taskCount = tasks.size();
-                int movement = 0;
-                int offset = 0;
-                for (int i = 0; i < taskCount; i++) {
-                    Task task = tasks.get(i);
-                    TaskViewTransform toTransform = taskTransforms.get(i);
-                    if (toTransform.visible) {
-                        TaskView tv = getChildViewForTask(task);
-                        if (tv == null) {
-                            // For views that are not already visible, animate them in
-                            tv = mViewPool.pickUpViewFromPool(task, task);
-
-                            // Compose a new transform to fade and slide the new task in
-                            TaskViewTransform fromTransform = new TaskViewTransform(toTransform);
-                            tv.prepareTaskTransformForFilterTaskHidden(fromTransform);
-                            tv.updateViewPropertiesToTaskTransform(null, fromTransform, 0);
-
-                            Animator anim = tv.getAnimatorToTaskTransform(toTransform);
-                            anim.setStartDelay(offset *
-                                    Constants.Values.TaskStackView.FilterStartDelay);
-                            newViewAnims.add(anim);
-                            // Use the movement of the newly visible views to calculate the duration
-                            // of the animation
-                            movement = Math.max(movement,
-                                    Math.abs(toTransform.translationY - fromTransform.translationY));
-                            offset++;
+                                if (!unifyNewViewAnimation) {
+                                    // For views that are not already visible, animate them in
+                                    childViewTransforms.clear();
+                                    int duration = getEnterTransformsForFilterAnimation(tasks,
+                                            taskTransforms, childViewTransforms, config);
+                                    for (final TaskView tv : childViewTransforms.keySet()) {
+                                        Pair<Integer, TaskViewTransform> t = childViewTransforms.get(tv);
+                                        tv.animate().setStartDelay(t.first);
+                                        tv.updateViewPropertiesToTaskTransform(null, t.second, duration);
+                                    }
+                                }
+                            }
                         }
-                    }
-                }
+                    });
+            tv.updateViewPropertiesToTaskTransform(null, t.second, duration);
+        }
+    }
 
-                // Run the animation
-                mFilterChildrenAnimator = new AnimatorSet();
-                mFilterChildrenAnimator.setDuration(
-                        Utilities.calculateTranslationAnimationDuration(movement,
-                                config.filteringNewViewsMinAnimDuration));
-                mFilterChildrenAnimator.playTogether(newViewAnims);
-                mFilterChildrenAnimator.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        // Decrement the hw layers ref count
-                        decHwLayersRefCount("unfilteredNewViews");
-                    }
-                });
-                mFilterChildrenAnimator.start();
-                invalidate();
-            }
-        });
-        mFilterChildrenAnimator.playTogether(childViewAnims);
-        mFilterChildrenAnimator.start();
+    @Override
+    public void onStackFiltered(TaskStack newStack, final ArrayList<Task> curTasks,
+                                Task filteredTask) {
+        // Close any open info panes
+        closeOpenInfoPanes();
+
+        // Stash the scroll and filtered task for us to restore to when we unfilter
+        mStashedScroll = getStackScroll();
+
+        // Calculate the current task transforms
+        ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curTasks, getStackScroll(), null, true);
+
+        // Scroll the item to the top of the stack (sans-peek) rect so that we can see it better
+        updateMinMaxScroll(false);
+        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+        setStackScrollRaw((int) (newStack.indexOfTask(filteredTask) * overlapHeight));
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack after setting the new scroll
+        final ArrayList<Task> tasks = mStack.getTasks();
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(mStack.getTasks(), getStackScroll(), null, true);
+
+        // Animate
+        doFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
+    }
+
+    @Override
+    public void onStackUnfiltered(TaskStack newStack, final ArrayList<Task> curTasks) {
+        // Close any open info panes
+        closeOpenInfoPanes();
+
+        // Calculate the current task transforms
+        final ArrayList<TaskViewTransform> curTaskTransforms =
+                getStackTransforms(curTasks, getStackScroll(), null, true);
+
+        // Restore the stashed scroll
+        updateMinMaxScroll(false);
+        setStackScrollRaw(mStashedScroll);
+        boundScrollRaw();
+
+        // Compute the transforms of the items in the new stack after restoring the stashed scroll
+        final ArrayList<Task> tasks = mStack.getTasks();
+        final ArrayList<TaskViewTransform> taskTransforms =
+                getStackTransforms(tasks, getStackScroll(), null, true);
+
+        // Animate
+        doFilteringAnimation(curTasks, curTaskTransforms, tasks, taskTransforms);
 
         // Clear the saved vars
         mStashedScroll = 0;
@@ -966,6 +944,9 @@
 
             // Set the callbacks and listeners for this new view
             tv.setOnClickListener(this);
+            if (Constants.DebugFlags.App.EnableInfoPane) {
+                tv.setOnLongClickListener(this);
+            }
             tv.setCallbacks(this);
         } else {
             attachViewToParent(tv, insertIndex, tv.getLayoutParams());
@@ -995,8 +976,24 @@
             } else {
                 mStack.filterTasks(tv.getTask());
             }
-        } else {
-            Console.logError(getContext(), "Task Filtering TBD");
+        }
+    }
+
+    @Override
+    public void onTaskInfoPanelShown(TaskView tv) {
+        // Do nothing
+    }
+
+    @Override
+    public void onTaskInfoPanelHidden(TaskView tv) {
+        // Unset the saved scroll
+        mLastInfoPaneStackScroll = -1;
+    }
+
+    @Override
+    public void onTaskAppInfoClicked(TaskView tv) {
+        if (mCb != null) {
+            mCb.onTaskAppInfoLaunched(tv.getTask());
         }
     }
 
@@ -1009,10 +1006,51 @@
         Console.log(Constants.DebugFlags.UI.ClickEvents, "[TaskStack|Clicked|Thumbnail]",
                 task + " cb: " + mCb);
 
+        // Close any open info panes if the user taps on another task
+        if (closeOpenInfoPanes()) {
+            return;
+        }
+
         if (mCb != null) {
             mCb.onTaskLaunched(this, tv, mStack, task);
         }
     }
+
+    @Override
+    public boolean onLongClick(View v) {
+        if (!Constants.DebugFlags.App.EnableInfoPane) return false;
+
+        TaskView tv = (TaskView) v;
+
+        // Close any other task info panels if we launch another info pane
+        closeOpenInfoPanes();
+
+        // Scroll the task view so that it is maximally visible
+        float overlapHeight = Constants.Values.TaskStackView.StackOverlapPct * mTaskRect.height();
+        int taskIndex = mStack.indexOfTask(tv.getTask());
+        int curScroll = getStackScroll();
+        int newScroll = (int) Math.max(mMinScroll, Math.min(mMaxScroll, taskIndex * overlapHeight));
+        TaskViewTransform transform = getStackTransform(taskIndex, curScroll);
+        Rect nonOverlapRect = new Rect(transform.rect);
+        if (taskIndex < (mStack.getTaskCount() - 1)) {
+            nonOverlapRect.bottom = nonOverlapRect.top + (int) overlapHeight;
+        }
+
+        // XXX: Use HW Layers
+        if (transform.t < 0f) {
+            animateScroll(curScroll, newScroll, null);
+        } else if (nonOverlapRect.bottom > mStackRectSansPeek.bottom) {
+            // Check if we are out of bounds, if so, just scroll it in such that the bottom of the
+            // task view is visible
+            newScroll = curScroll - (mStackRectSansPeek.bottom - nonOverlapRect.bottom);
+            animateScroll(curScroll, newScroll, null);
+        }
+        mLastInfoPaneStackScroll = newScroll;
+
+        // Show the info pane for this task view
+        tv.showInfoPane(new Rect(0, 0, 0, (int) overlapHeight));
+        return true;
+    }
 }
 
 /* Handles touch events */
@@ -1227,9 +1265,10 @@
                 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
                 int x = (int) ev.getX(activePointerIndex);
                 int y = (int) ev.getY(activePointerIndex);
+                int yTotal = Math.abs(y - mInitialMotionY);
                 int deltaY = mLastMotionY - y;
                 if (!mIsScrolling) {
-                    if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
+                    if (yTotal > mScrollTouchSlop) {
                         mIsScrolling = true;
                         // Initialize the velocity tracker
                         initOrResetVelocityTracker();
@@ -1244,7 +1283,12 @@
                     }
                 }
                 if (mIsScrolling) {
-                    mSv.setStackScroll(mSv.getStackScroll() + deltaY);
+                    int curStackScroll = mSv.getStackScroll();
+                    if (mSv.isScrollOutOfBounds(curStackScroll + deltaY)) {
+                        // Scale the touch if we are overscrolling
+                        deltaY /= Constants.Values.TaskStackView.TouchOverscrollScaleFactor;
+                    }
+                    mSv.setStackScroll(curStackScroll + deltaY);
                     if (mSv.isScrollOutOfBounds()) {
                         mVelocityTracker.clear();
                     }
@@ -1351,6 +1395,13 @@
         if (parent != null) {
             parent.requestDisallowInterceptTouchEvent(true);
         }
+        // If the info panel is currently showing on this view, then we need to dismiss it
+        if (Constants.DebugFlags.App.EnableInfoPane) {
+            TaskView tv = (TaskView) v;
+            if (tv.isInfoPaneVisible()) {
+                tv.hideInfoPane();
+            }
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index e99fecb..d3b79d6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -16,18 +16,18 @@
 
 package com.android.systemui.recents.views;
 
-import android.animation.Animator;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
-import android.graphics.Color;
 import android.graphics.Path;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.animation.AccelerateInterpolator;
 import android.widget.FrameLayout;
 import com.android.systemui.R;
 import com.android.systemui.recents.BakedBezierInterpolator;
@@ -36,26 +36,35 @@
 import com.android.systemui.recents.Utilities;
 import com.android.systemui.recents.model.Task;
 
-import java.util.Random;
-
 
 /* A task view */
-public class TaskView extends FrameLayout implements View.OnClickListener, Task.TaskCallbacks {
+public class TaskView extends FrameLayout implements View.OnClickListener,
+        Task.TaskCallbacks {
     /** The TaskView callbacks */
     interface TaskViewCallbacks {
         public void onTaskIconClicked(TaskView tv);
+        public void onTaskInfoPanelShown(TaskView tv);
+        public void onTaskInfoPanelHidden(TaskView tv);
+        public void onTaskAppInfoClicked(TaskView tv);
+
         // public void onTaskViewReboundToTask(TaskView tv, Task t);
     }
 
+    int mDim;
+    int mMaxDim;
+    TimeInterpolator mDimInterpolator = new AccelerateInterpolator();
+
     Task mTask;
     boolean mTaskDataLoaded;
+    boolean mTaskInfoPaneVisible;
+    Point mLastTouchDown = new Point();
+    Path mRoundedRectClipPath = new Path();
 
     TaskThumbnailView mThumbnailView;
     TaskBarView mBarView;
+    TaskInfoView mInfoView;
     TaskViewCallbacks mCb;
 
-    Path mRoundedRectClipPath = new Path();
-
 
     public TaskView(Context context) {
         this(context, null);
@@ -76,10 +85,14 @@
 
     @Override
     protected void onFinishInflate() {
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        mMaxDim = config.taskStackMaxDim;
+
         // Bind the views
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
-        mBarView.mApplicationIcon.setOnClickListener(this);
+        mInfoView = (TaskInfoView) findViewById(R.id.task_view_info_pane);
+
         if (mTaskDataLoaded) {
             onTaskDataLoaded(false);
         }
@@ -91,23 +104,21 @@
 
         // Update the rounded rect clip path
         RecentsConfiguration config = RecentsConfiguration.getInstance();
-        float radius = config.pxFromDp(Constants.Values.TaskView.RoundedCornerRadiusDps);
+        float radius = config.taskViewRoundedCornerRadiusPx;
         mRoundedRectClipPath.reset();
         mRoundedRectClipPath.addRoundRect(new RectF(0, 0, getMeasuredWidth(), getMeasuredHeight()),
                 radius, radius, Path.Direction.CW);
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        int restoreCount = 0;
-        if (Constants.Values.TaskView.UseRoundedCorners) {
-            restoreCount = canvas.save();
-            canvas.clipPath(mRoundedRectClipPath);
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        switch (ev.getAction()) {
+            case MotionEvent.ACTION_DOWN:
+            case MotionEvent.ACTION_MOVE:
+                mLastTouchDown.set((int) ev.getX(), (int) ev.getY());
+                break;
         }
-        super.dispatchDraw(canvas);
-        if (Constants.Values.TaskView.UseRoundedCorners) {
-            canvas.restoreToCount(restoreCount);
-        }
+        return super.onInterceptTouchEvent(ev);
     }
 
     /** Set callback */
@@ -137,6 +148,12 @@
                     .setDuration(duration)
                     .setInterpolator(BakedBezierInterpolator.INSTANCE)
                     .withLayer()
+                    .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                        @Override
+                        public void onAnimationUpdate(ValueAnimator animation) {
+                            updateDimOverlayFromScale();
+                        }
+                    })
                     .start();
         } else {
             setTranslationY(toTransform.translationY);
@@ -144,18 +161,8 @@
             setScaleY(toTransform.scale);
             setAlpha(toTransform.alpha);
         }
-    }
-
-    /** Returns an animator to animate this task to the specified transform */
-    Animator getAnimatorToTaskTransform(TaskViewTransform toTransform) {
-        AnimatorSet anims = new AnimatorSet();
-        anims.playTogether(
-                ObjectAnimator.ofFloat(this, "translationY", toTransform.translationY),
-                ObjectAnimator.ofFloat(this, "scaleX", toTransform.scale),
-                ObjectAnimator.ofFloat(this, "scaleY", toTransform.scale),
-                ObjectAnimator.ofFloat(this, "alpha", toTransform.alpha)
-        );
-        return anims;
+        updateDimOverlayFromScale();
+        invalidate();
     }
 
     /** Resets this view's properties */
@@ -165,14 +172,23 @@
         setScaleX(1f);
         setScaleY(1f);
         setAlpha(1f);
+        invalidate();
     }
 
+    /**
+     * When we are un/filtering, this method will set up the transform that we are animating to,
+     * in order to hide the task.
+     */
     void prepareTaskTransformForFilterTaskHidden(TaskViewTransform toTransform) {
         // Fade the view out and slide it away
         toTransform.alpha = 0f;
         toTransform.translationY += 200;
     }
 
+    /**
+     * When we are un/filtering, this method will setup the transform that we are animating from,
+     * in order to show the task.
+     */
     void prepareTaskTransformForFilterTaskVisible(TaskViewTransform fromTransform) {
         // Fade the view in
         fromTransform.alpha = 0f;
@@ -195,7 +211,7 @@
                 .translationY(0)
                 .setStartDelay(235)
                 .setInterpolator(BakedBezierInterpolator.INSTANCE)
-                .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
+                .setDuration(config.taskBarEnterAnimDuration)
                 .withLayer()
                 .start();
     }
@@ -214,26 +230,81 @@
             .setInterpolator(BakedBezierInterpolator.INSTANCE)
             .setDuration(Utilities.calculateTranslationAnimationDuration(translate))
             .withLayer()
-            .withEndAction(r)
+            .withEndAction(new Runnable() {
+                @Override
+                public void run() {
+                    post(r);
+                }
+            })
             .start();
     }
 
     /** Returns the rect we want to clip (it may not be the full rect) */
-    Rect getClippingRect(Rect outRect, boolean accountForRoundedRects) {
+    Rect getClippingRect(Rect outRect) {
         getHitRect(outRect);
         // XXX: We should get the hit rect of the thumbnail view and intersect, but this is faster
         outRect.right = outRect.left + mThumbnailView.getRight();
         outRect.bottom = outRect.top + mThumbnailView.getBottom();
-        // We need to shrink the next rect by the rounded corners since those are draw on
-        // top of the current view
-        if (accountForRoundedRects) {
-            RecentsConfiguration config = RecentsConfiguration.getInstance();
-            float radius = config.pxFromDp(Constants.Values.TaskView.RoundedCornerRadiusDps);
-            outRect.inset((int) radius, (int) radius);
-        }
         return outRect;
     }
 
+    /** Returns whether this task has an info pane visible */
+    boolean isInfoPaneVisible() {
+        return mTaskInfoPaneVisible;
+    }
+
+    /** Shows the info pane if it is not visible. */
+    void showInfoPane(Rect taskVisibleRect) {
+        if (mTaskInfoPaneVisible) return;
+
+        // Remove the bar view from the visible rect and update the info pane contents
+        taskVisibleRect.top += mBarView.getMeasuredHeight();
+        mInfoView.updateContents(taskVisibleRect);
+
+        // Show the info pane and animate it into view
+        mInfoView.setVisibility(View.VISIBLE);
+        mInfoView.animateCircularClip(mLastTouchDown, 0f, 1f, null, true);
+        mInfoView.setOnClickListener(this);
+        mTaskInfoPaneVisible = true;
+
+        // Notify any callbacks
+        if (mCb != null) {
+            mCb.onTaskInfoPanelShown(this);
+        }
+    }
+
+    /** Hides the info pane if it is visible. */
+    void hideInfoPane() {
+        if (!mTaskInfoPaneVisible) return;
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+
+        // Cancel any circular clip animation
+        mInfoView.cancelCircularClipAnimation();
+
+        // Animate the info pane out
+        mInfoView.animate()
+                .alpha(0f)
+                .setDuration(config.taskViewInfoPaneAnimDuration)
+                .setInterpolator(BakedBezierInterpolator.INSTANCE)
+                .withLayer()
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        mInfoView.setVisibility(View.INVISIBLE);
+                        mInfoView.setOnClickListener(null);
+
+                        mInfoView.setAlpha(1f);
+                    }
+                })
+                .start();
+        mTaskInfoPaneVisible = false;
+
+        // Notify any callbacks
+        if (mCb != null) {
+            mCb.onTaskInfoPanelHidden(this);
+        }
+    }
+
     /** Enable the hw layers on this task view */
     void enableHwLayers() {
         mThumbnailView.setLayerType(View.LAYER_TYPE_HARDWARE, null);
@@ -244,6 +315,29 @@
         mThumbnailView.setLayerType(View.LAYER_TYPE_NONE, null);
     }
 
+    /** Update the dim as a function of the scale of this view. */
+    void updateDimOverlayFromScale() {
+        float minScale = Constants.Values.TaskStackView.StackPeekMinScale;
+        float scaleRange = 1f - minScale;
+        float dim = (1f - getScaleX()) / scaleRange;
+        dim = mDimInterpolator.getInterpolation(Math.min(dim, 1f));
+        mDim = Math.max(0, Math.min(mMaxDim, (int) (dim * 255)));
+        invalidate();
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        // Apply the rounded rect clip path on the whole view
+        canvas.clipPath(mRoundedRectClipPath);
+
+        super.draw(canvas);
+
+        // Apply the dim if necessary
+        if (mDim > 0) {
+            canvas.drawColor(mDim << 24);
+        }
+    }
+
     /**** TaskCallbacks Implementation ****/
 
     /** Binds this task view to the task */
@@ -254,27 +348,39 @@
 
     @Override
     public void onTaskDataLoaded(boolean reloadingTaskData) {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
             // Bind each of the views to the new task data
             mThumbnailView.rebindToTask(mTask, reloadingTaskData);
             mBarView.rebindToTask(mTask, reloadingTaskData);
+            // Rebind any listeners
+            mBarView.mApplicationIcon.setOnClickListener(this);
+            mInfoView.mAppInfoButton.setOnClickListener(this);
         }
         mTaskDataLoaded = true;
     }
 
     @Override
     public void onTaskDataUnloaded() {
-        if (mThumbnailView != null && mBarView != null) {
+        if (mThumbnailView != null && mBarView != null && mInfoView != null) {
             // Unbind each of the views from the task data and remove the task callback
             mTask.setCallbacks(null);
             mThumbnailView.unbindFromTask();
             mBarView.unbindFromTask();
+            // Unbind any listeners
+            mBarView.mApplicationIcon.setOnClickListener(null);
+            mInfoView.mAppInfoButton.setOnClickListener(null);
         }
         mTaskDataLoaded = false;
     }
 
     @Override
     public void onClick(View v) {
-        mCb.onTaskIconClicked(this);
+        if (v == mInfoView) {
+            // Do nothing
+        } else if (v == mBarView.mApplicationIcon) {
+            mCb.onTaskIconClicked(this);
+        } else if (v == mInfoView.mAppInfoButton) {
+            mCb.onTaskAppInfoClicked(this);
+        }
     }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
new file mode 100644
index 0000000..d67e7cb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/settings/UserSwitcherHostView.java
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.settings;
+
+import com.android.systemui.R;
+
+import android.app.ActivityManagerNative;
+import android.content.Context;
+import android.content.pm.UserInfo;
+import android.os.RemoteException;
+import android.os.UserManager;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManagerGlobal;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A quick and dirty view to show a user switcher.
+ */
+public class UserSwitcherHostView extends FrameLayout implements ListView.OnItemClickListener {
+
+    private static final String TAG = "UserSwitcherDialog";
+
+    private ArrayList<UserInfo> mUserInfo = new ArrayList<UserInfo>();
+    private Adapter mAdapter = new Adapter();
+    private UserManager mUserManager;
+    private Runnable mFinishRunnable;
+    private ListView mListView;
+
+    public UserSwitcherHostView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+
+        if (isInEditMode()) {
+            return;
+        }
+        mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+    }
+
+    public UserSwitcherHostView(Context context, AttributeSet attrs) {
+        this(context, attrs, com.android.internal.R.attr.listViewStyle);
+    }
+
+    public UserSwitcherHostView(Context context) {
+        this(context, null);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mListView = (ListView) findViewById(android.R.id.list);
+        mListView.setAdapter(mAdapter);
+        mListView.setOnItemClickListener(this);
+    }
+
+    @Override
+    public void onItemClick(AdapterView<?> l, View v, int position, long id) {
+        int userId = mAdapter.getItem(position).id;
+        try {
+            WindowManagerGlobal.getWindowManagerService().lockNow(null);
+            ActivityManagerNative.getDefault().switchUser(userId);
+            finish();
+        } catch (RemoteException e) {
+            Log.e(TAG, "Couldn't switch user.", e);
+        }
+    }
+
+    private void finish() {
+        if (mFinishRunnable != null) {
+            mFinishRunnable.run();
+        }
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (event.getAction() == MotionEvent.ACTION_UP) {
+            finish();
+        }
+        return true;
+    }
+
+    @Override
+    protected void onVisibilityChanged(View changedView, int visibility) {
+        super.onVisibilityChanged(changedView, visibility);
+        // A gross hack to get rid of the switcher when the shade is collapsed.
+        if (visibility != VISIBLE) {
+            finish();
+        }
+    }
+
+    public void setFinishRunnable(Runnable finishRunnable) {
+        mFinishRunnable = finishRunnable;
+    }
+
+    public void refreshUsers() {
+        mUserInfo.clear();
+        List<UserInfo> users = mUserManager.getUsers(true);
+        for (UserInfo user : users) {
+            if (!user.isManagedProfile()) {
+                mUserInfo.add(user);
+            }
+        }
+        mAdapter.notifyDataSetChanged();
+    }
+
+    private class Adapter extends BaseAdapter {
+
+        @Override
+        public int getCount() {
+            return mUserInfo.size();
+        }
+
+        @Override
+        public UserInfo getItem(int position) {
+            return mUserInfo.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return getItem(position).serialNumber;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null || (!(convertView.getTag() instanceof ViewHolder))) {
+                convertView = createView(parent);
+            }
+            ViewHolder h = (ViewHolder) convertView.getTag();
+            bindView(h, getItem(position));
+            return convertView;
+        }
+
+        private View createView(ViewGroup parent) {
+            View v = LayoutInflater.from(getContext()).inflate(
+                    R.layout.user_switcher_item, parent, false);
+            ViewHolder h = new ViewHolder();
+            h.name = (TextView) v.findViewById(R.id.user_name);
+            h.picture = (ImageView) v.findViewById(R.id.user_picture);
+            v.setTag(h);
+            return v;
+        }
+
+        private void bindView(ViewHolder h, UserInfo item) {
+            h.name.setText(item.name);
+            h.picture.setImageBitmap(mUserManager.getUserIcon(item.id));
+        }
+
+        class ViewHolder {
+            TextView name;
+            ImageView picture;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
new file mode 100644
index 0000000..0f32dc0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ActivatableNotificationView.java
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.widget.FrameLayout;
+
+import com.android.internal.R;
+
+/**
+ * Base class for both {@link ExpandableNotificationRow} and {@link NotificationOverflowContainer}
+ * to implement dimming/activating on Keyguard for the double-tap gesture
+ */
+public abstract class ActivatableNotificationView extends ExpandableOutlineView {
+
+    private static final long DOUBLETAP_TIMEOUT_MS = 1000;
+
+    private boolean mDimmed;
+    private boolean mLocked;
+
+    private int mBgResId = R.drawable.notification_quantum_bg;
+    private int mDimmedBgResId = R.drawable.notification_quantum_bg_dim;
+
+    /**
+     * Flag to indicate that the notification has been touched once and the second touch will
+     * click it.
+     */
+    private boolean mActivated;
+
+    private float mDownX;
+    private float mDownY;
+    private final float mTouchSlop;
+
+    private OnActivatedListener mOnActivatedListener;
+
+    public ActivatableNotificationView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
+        updateBackgroundResource();
+    }
+
+
+    private final Runnable mTapTimeoutRunnable = new Runnable() {
+        @Override
+        public void run() {
+            makeInactive();
+        }
+    };
+
+    @Override
+    public void setOnClickListener(OnClickListener l) {
+        super.setOnClickListener(l);
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mLocked) {
+            return handleTouchEventLocked(event);
+        } else {
+            return super.onTouchEvent(event);
+        }
+    }
+
+    private boolean handleTouchEventLocked(MotionEvent event) {
+        int action = event.getActionMasked();
+        switch (action) {
+            case MotionEvent.ACTION_DOWN:
+                mDownX = event.getX();
+                mDownY = event.getY();
+                if (mDownY > getActualHeight()) {
+                    return false;
+                }
+
+                // Call the listener tentatively directly, even if we don't know whether the user
+                // will stay within the touch slop, as the listener is implemented as a scale
+                // animation, which is cancellable without jarring effects when swiping away
+                // notifications.
+                if (mOnActivatedListener != null) {
+                    mOnActivatedListener.onActivated(this);
+                }
+                break;
+            case MotionEvent.ACTION_MOVE:
+                if (!isWithinTouchSlop(event)) {
+                    makeInactive();
+                    return false;
+                }
+                break;
+            case MotionEvent.ACTION_UP:
+                if (isWithinTouchSlop(event)) {
+                    if (!mActivated) {
+                        makeActive(event.getX(), event.getY());
+                        postDelayed(mTapTimeoutRunnable, DOUBLETAP_TIMEOUT_MS);
+                    } else {
+                        performClick();
+                        makeInactive();
+                    }
+                } else {
+                    makeInactive();
+                }
+                break;
+            case MotionEvent.ACTION_CANCEL:
+                makeInactive();
+                break;
+            default:
+                break;
+        }
+        return true;
+    }
+
+    private void makeActive(float x, float y) {
+        mCustomBackground.setHotspot(0, x, y);
+        mActivated = true;
+    }
+
+    /**
+     * Cancels the hotspot and makes the notification inactive.
+     */
+    private void makeInactive() {
+        if (mActivated) {
+            // Make sure that we clear the hotspot from the center.
+            mCustomBackground.setHotspot(0, getWidth() / 2, getActualHeight() / 2);
+            mCustomBackground.removeHotspot(0);
+            mActivated = false;
+        }
+        if (mOnActivatedListener != null) {
+            mOnActivatedListener.onReset(this);
+        }
+        removeCallbacks(mTapTimeoutRunnable);
+    }
+
+    private boolean isWithinTouchSlop(MotionEvent event) {
+        return Math.abs(event.getX() - mDownX) < mTouchSlop
+                && Math.abs(event.getY() - mDownY) < mTouchSlop;
+    }
+
+    /**
+     * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+     */
+    public void setDimmed(boolean dimmed) {
+        if (mDimmed != dimmed) {
+            mDimmed = dimmed;
+            updateBackgroundResource();
+        }
+    }
+
+    /**
+     * Sets the notification as locked. In the locked state, the first tap will produce a quantum
+     * ripple to make the notification brighter and only the second tap will cause a click.
+     */
+    public void setLocked(boolean locked) {
+        mLocked = locked;
+    }
+
+    /**
+     * Sets the resource id for the background of this notification.
+     *
+     * @param bgResId The background resource to use in normal state.
+     * @param dimmedBgResId The background resource to use in dimmed state.
+     */
+    public void setBackgroundResourceIds(int bgResId, int dimmedBgResId) {
+        mBgResId = bgResId;
+        mDimmedBgResId = dimmedBgResId;
+        updateBackgroundResource();
+    }
+
+    private void updateBackgroundResource() {
+        setCustomBackgroundResource(mDimmed ? mDimmedBgResId : mBgResId);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        setPivotX(getWidth()/2);
+    }
+
+    @Override
+    public void setActualHeight(int actualHeight) {
+        super.setActualHeight(actualHeight);
+        setPivotY(actualHeight/2);
+    }
+
+    public void setOnActivatedListener(OnActivatedListener onActivatedListener) {
+        mOnActivatedListener = onActivatedListener;
+    }
+
+    public interface OnActivatedListener {
+        void onActivated(View view);
+        void onReset(View view);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 844b964..9149e2d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -71,7 +71,6 @@
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
 import com.android.internal.util.LegacyNotificationUtil;
-import com.android.internal.widget.SizeAdaptiveLayout;
 import com.android.systemui.R;
 import com.android.systemui.RecentsComponent;
 import com.android.systemui.SearchPanelView;
@@ -83,7 +82,7 @@
 import java.util.Locale;
 
 public abstract class BaseStatusBar extends SystemUI implements
-        CommandQueue.Callbacks {
+        CommandQueue.Callbacks, ActivatableNotificationView.OnActivatedListener {
     public static final String TAG = "StatusBar";
     public static final boolean DEBUG = false;
     public static final boolean MULTIUSER_DEBUG = false;
@@ -109,9 +108,6 @@
     public static final int EXPANDED_LEAVE_ALONE = -10000;
     public static final int EXPANDED_FULL_OPEN = -10001;
 
-    private static final String EXTRA_INTERCEPT = "android.intercept";
-    private static final float INTERCEPTED_ALPHA = .2f;
-
     protected CommandQueue mCommandQueue;
     protected IStatusBarService mBarService;
     protected H mHandler = createHandler();
@@ -141,7 +137,8 @@
 
     protected IDreamManager mDreamManager;
     PowerManager mPowerManager;
-    protected int mRowHeight;
+    protected int mRowMinHeight;
+    protected int mRowMaxHeight;
 
     // public mode, private notifications, etc
     private boolean mLockscreenPublicMode = false;
@@ -170,9 +167,8 @@
 
     protected int mZenMode;
 
-    public IStatusBarService getStatusBarService() {
-        return mBarService;
-    }
+    protected boolean mOnKeyguard;
+    protected NotificationOverflowContainer mKeyguardIconOverflowContainer;
 
     public boolean isDeviceProvisioned() {
         return mDeviceProvisioned;
@@ -425,9 +421,9 @@
     }
 
 
-    protected void applyLegacyRowBackground(StatusBarNotification sbn, View content) {
-        if (sbn.getNotification().contentView.getLayoutId() !=
-                com.android.internal.R.layout.notification_template_base) {
+    protected void applyLegacyRowBackground(StatusBarNotification sbn,
+            NotificationData.Entry entry) {
+        if (entry.expanded.getId() != com.android.internal.R.id.status_bar_latest_event_content) {
             int version = 0;
             try {
                 ApplicationInfo info = mContext.getPackageManager().getApplicationInfo(sbn.getPackageName(), 0);
@@ -436,9 +432,11 @@
                 Log.e(TAG, "Failed looking up ApplicationInfo for " + sbn.getPackageName(), ex);
             }
             if (version > 0 && version < Build.VERSION_CODES.GINGERBREAD) {
-                content.setBackgroundResource(R.drawable.notification_row_legacy_bg);
-            } else {
-                content.setBackgroundResource(com.android.internal.R.drawable.notification_bg);
+                entry.row.setBackgroundResource(R.drawable.notification_row_legacy_bg);
+            } else if (version < Build.VERSION_CODES.L) {
+                entry.row.setBackgroundResourceIds(
+                        com.android.internal.R.drawable.notification_bg,
+                        com.android.internal.R.drawable.notification_bg_dim);
             }
         }
     }
@@ -738,8 +736,9 @@
             return false;
         }
 
-        Log.v(TAG, "publicNotification: "
-                + sbn.getNotification().publicVersion);
+        if (DEBUG) {
+            Log.v(TAG, "publicNotification: " + sbn.getNotification().publicVersion);
+        }
 
         Notification publicNotification = sbn.getNotification().publicVersion;
 
@@ -760,20 +759,20 @@
         // NB: the large icon is now handled entirely by the template
 
         // bind the click event to the content area
-        ViewGroup content = (ViewGroup)row.findViewById(R.id.container);
-        SizeAdaptiveLayout expanded = (SizeAdaptiveLayout)row.findViewById(R.id.expanded);
-        SizeAdaptiveLayout expandedPublic
-                = (SizeAdaptiveLayout)row.findViewById(R.id.expandedPublic);
+        NotificationContentView expanded =
+                (NotificationContentView) row.findViewById(R.id.expanded);
+        NotificationContentView expandedPublic =
+                (NotificationContentView) row.findViewById(R.id.expandedPublic);
 
-        content.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+        row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
 
         PendingIntent contentIntent = sbn.getNotification().contentIntent;
         if (contentIntent != null) {
             final View.OnClickListener listener = makeClicker(contentIntent,
                     sbn.getPackageName(), sbn.getTag(), sbn.getId(), isHeadsUp, sbn.getUserId());
-            content.setOnClickListener(listener);
+            row.setOnClickListener(listener);
         } else {
-            content.setOnClickListener(null);
+            row.setOnClickListener(null);
         }
 
         // set up the adaptive layout
@@ -795,19 +794,11 @@
 
         if (contentViewLocal != null) {
             contentViewLocal.setIsRootNamespace(true);
-            SizeAdaptiveLayout.LayoutParams params =
-                    new SizeAdaptiveLayout.LayoutParams(contentViewLocal.getLayoutParams());
-            params.minHeight = minHeight;
-            params.maxHeight = minHeight;
-            expanded.addView(contentViewLocal, params);
+            expanded.setContractedChild(contentViewLocal);
         }
         if (bigContentViewLocal != null) {
             bigContentViewLocal.setIsRootNamespace(true);
-            SizeAdaptiveLayout.LayoutParams params =
-                    new SizeAdaptiveLayout.LayoutParams(bigContentViewLocal.getLayoutParams());
-            params.minHeight = minHeight+1;
-            params.maxHeight = maxHeight;
-            expanded.addView(bigContentViewLocal, params);
+            expanded.setExpandedChild(bigContentViewLocal);
         }
 
         PackageManager pm = mContext.getPackageManager();
@@ -821,11 +812,7 @@
 
                 if (publicViewLocal != null) {
                     publicViewLocal.setIsRootNamespace(true);
-                    SizeAdaptiveLayout.LayoutParams params =
-                            new SizeAdaptiveLayout.LayoutParams(publicViewLocal.getLayoutParams());
-                    params.minHeight = minHeight;
-                    params.maxHeight = minHeight;
-                    expandedPublic.addView(publicViewLocal, params);
+                    expandedPublic.setContractedChild(publicViewLocal);
                 }
             }
             catch (RuntimeException e) {
@@ -873,8 +860,6 @@
 
         row.setDrawingCacheEnabled(true);
 
-        applyLegacyRowBackground(sbn, content);
-
         if (MULTIUSER_DEBUG) {
             TextView debug = (TextView) row.findViewById(R.id.debug_info);
             if (debug != null) {
@@ -883,12 +868,14 @@
             }
         }
         entry.row = row;
-        entry.row.setRowHeight(mRowHeight);
-        entry.content = content;
+        entry.row.setHeightRange(mRowMinHeight, mRowMaxHeight);
+        entry.row.setOnActivatedListener(this);
         entry.expanded = contentViewLocal;
         entry.expandedPublic = publicViewLocal;
         entry.setBigContentView(bigContentViewLocal);
 
+        applyLegacyRowBackground(sbn, entry);
+
         return true;
     }
 
@@ -1006,7 +993,7 @@
         // Remove the expanded view.
         ViewGroup rowParent = (ViewGroup)entry.row.getParent();
         if (rowParent != null) rowParent.removeView(entry.row);
-        updateExpansionStates();
+        updateRowStates();
         updateNotificationIcons();
 
         return entry.notification;
@@ -1049,8 +1036,7 @@
         if (DEBUG) {
             Log.d(TAG, "addNotificationViews: added at " + pos);
         }
-        updateInterceptedState(entry);
-        updateExpansionStates();
+        updateRowStates();
         updateNotificationIcons();
     }
 
@@ -1058,56 +1044,102 @@
         addNotificationViews(createNotificationViews(key, notification));
     }
 
-    protected void updateExpansionStates() {
-        int N = mNotificationData.size();
-        for (int i = 0; i < N; i++) {
+    /**
+     * @return The number of notifications we show on Keyguard.
+     */
+    protected abstract int getMaxKeyguardNotifications();
+
+    /**
+     * Updates expanded, dimmed and locked states of notification rows.
+     */
+    protected void updateRowStates() {
+        int maxKeyguardNotifications = getMaxKeyguardNotifications();
+        mKeyguardIconOverflowContainer.getIconsView().removeAllViews();
+        int n = mNotificationData.size();
+        int visibleNotifications = 0;
+        for (int i = n-1; i >= 0; i--) {
             NotificationData.Entry entry = mNotificationData.get(i);
-            if (!entry.row.isUserLocked()) {
-                if (i == (N-1)) {
-                    if (DEBUG) Log.d(TAG, "expanding top notification at " + i);
-                    entry.row.setExpanded(true);
-                } else {
-                    if (!entry.row.isUserExpanded()) {
-                        if (DEBUG) Log.d(TAG, "collapsing notification at " + i);
-                        entry.row.setExpanded(false);
-                    } else {
-                        if (DEBUG) Log.d(TAG, "ignoring user-modified notification at " + i);
-                    }
+            if (mOnKeyguard) {
+                entry.row.setExpansionDisabled(true);
+            } else {
+                entry.row.setExpansionDisabled(false);
+                if (!entry.row.isUserLocked()) {
+                    boolean top = (i == n-1);
+                    entry.row.setSystemExpanded(top);
+                }
+            }
+            entry.row.setDimmed(mOnKeyguard);
+            entry.row.setLocked(mOnKeyguard);
+            boolean showOnKeyguard = shouldShowOnKeyguard(entry.notification);
+            if (mOnKeyguard && (visibleNotifications >= maxKeyguardNotifications
+                    || !showOnKeyguard)) {
+                entry.row.setVisibility(View.GONE);
+                if (showOnKeyguard) {
+                    mKeyguardIconOverflowContainer.getIconsView().addNotification(entry);
                 }
             } else {
-                if (DEBUG) Log.d(TAG, "ignoring notification being held by user at " + i);
+                if (entry.row.getVisibility() == View.GONE) {
+                    // notify the scroller of a child addition
+                    mStackScroller.generateAddAnimation(entry.row);
+                }
+                entry.row.setVisibility(View.VISIBLE);
+                visibleNotifications++;
             }
         }
+
+        if (mOnKeyguard && mKeyguardIconOverflowContainer.getIconsView().getChildCount() > 0) {
+            mKeyguardIconOverflowContainer.setVisibility(View.VISIBLE);
+        } else {
+            mKeyguardIconOverflowContainer.setVisibility(View.GONE);
+        }
+    }
+
+    @Override
+    public void onActivated(View view) {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                if (view == entry.row) {
+                    entry.row.getActivator().activate();
+                } else {
+                    entry.row.getActivator().activateInverse();
+                }
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            if (view == mKeyguardIconOverflowContainer) {
+                mKeyguardIconOverflowContainer.getActivator().activate();
+            } else {
+                mKeyguardIconOverflowContainer.getActivator().activateInverse();
+            }
+        }
+    }
+
+    @Override
+    public void onReset(View view) {
+        int n = mNotificationData.size();
+        for (int i = 0; i < n; i++) {
+            NotificationData.Entry entry = mNotificationData.get(i);
+            if (entry.row.getVisibility() != View.GONE) {
+                entry.row.getActivator().reset();
+            }
+        }
+        if (mKeyguardIconOverflowContainer.getVisibility() != View.GONE) {
+            mKeyguardIconOverflowContainer.getActivator().reset();
+        }
+    }
+
+    private boolean shouldShowOnKeyguard(StatusBarNotification sbn) {
+        return sbn.getNotification().priority >= Notification.PRIORITY_LOW;
     }
 
     protected void setZenMode(int mode) {
         if (!isDeviceProvisioned()) return;
-        final boolean change = mZenMode != mode;
         mZenMode = mode;
-        final int N = mNotificationData.size();
-        for (int i = 0; i < N; i++) {
-            final NotificationData.Entry entry = mNotificationData.get(i);
-            if (change && !shouldIntercept()) {
-                entry.notification.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
-            }
-            updateInterceptedState(entry);
-        }
         updateNotificationIcons();
     }
 
-    private boolean shouldIntercept() {
-        return mZenMode != Settings.Global.ZEN_MODE_OFF;
-    }
-
-    protected boolean shouldIntercept(Notification n) {
-        return shouldIntercept() && n.extras.getBoolean(EXTRA_INTERCEPT);
-    }
-
-    private void updateInterceptedState(NotificationData.Entry entry) {
-        final boolean intercepted = shouldIntercept(entry.notification.getNotification());
-        entry.row.findViewById(R.id.container).setAlpha(intercepted ? INTERCEPTED_ALPHA : 1);
-    }
-
     protected abstract void haltTicker();
     protected abstract void setAreThereNotifications();
     protected abstract void updateNotificationIcons();
@@ -1231,7 +1263,7 @@
                     handleNotificationError(key, notification, "Couldn't update icon: " + ic);
                     return;
                 }
-                updateExpansionStates();
+                updateRowStates();
             }
             catch (RuntimeException e) {
                 // It failed to add cleanly.  Log, and remove the view from the panel.
@@ -1244,13 +1276,14 @@
             if (DEBUG) Log.d(TAG, "contents was " + (contentsUnchanged ? "unchanged" : "changed"));
             if (DEBUG) Log.d(TAG, "order was " + (orderUnchanged ? "unchanged" : "changed"));
             if (DEBUG) Log.d(TAG, "notification is " + (isTopAnyway ? "top" : "not top"));
-            final boolean wasExpanded = oldEntry.row.isUserExpanded();
             removeNotificationViews(key);
             addNotificationViews(key, notification);  // will also replace the heads up
-            if (wasExpanded) {
-                final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
-                newEntry.row.setExpanded(true);
-                newEntry.row.setUserExpanded(true);
+            final NotificationData.Entry newEntry = mNotificationData.findByKey(key);
+            final boolean userChangedExpansion = oldEntry.row.hasUserChangedExpansion();
+            if (userChangedExpansion) {
+                boolean userExpanded = oldEntry.row.isUserExpanded();
+                newEntry.row.setUserExpanded(userExpanded);
+                newEntry.row.applyExpansionToLayout();
             }
         }
 
@@ -1308,11 +1341,11 @@
             final View.OnClickListener listener = makeClicker(contentIntent,
                     notification.getPackageName(), notification.getTag(), notification.getId(),
                     isHeadsUp, notification.getUserId());
-            entry.content.setOnClickListener(listener);
+            entry.row.setOnClickListener(listener);
         } else {
-            entry.content.setOnClickListener(null);
+            entry.row.setOnClickListener(null);
         }
-        updateInterceptedState(entry);
+        entry.row.notifyContentUpdated();
     }
 
     protected void notifyHeadsUpScreenOn(boolean screenOn) {
@@ -1338,7 +1371,7 @@
         boolean interrupt = (isFullscreen || (isHighPriority && (isNoisy || hasTicker)))
                 && isAllowed
                 && mPowerManager.isScreenOn()
-                && !keyguard.isShowingAndNotHidden()
+                && !keyguard.isShowingAndNotOccluded()
                 && !keyguard.isInputRestricted();
         try {
             interrupt = interrupt && !mDreamManager.isDreaming();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 39333d7..bbbe8fa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -21,6 +21,7 @@
 import android.os.Message;
 import android.service.notification.StatusBarNotification;
 
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.statusbar.IStatusBar;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.internal.statusbar.StatusBarIconList;
@@ -98,6 +99,7 @@
         public void hideSearchPanel();
         public void cancelPreloadRecentApps();
         public void setWindowState(int window, int state);
+
     }
 
     public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -232,6 +234,7 @@
         }
     }
 
+
     private final class H extends Handler {
         public void handleMessage(Message msg) {
             final int what = msg.what & MSG_MASK;
@@ -295,7 +298,7 @@
                     mCallbacks.topAppWindowChanged(msg.arg1 != 0);
                     break;
                 case MSG_SHOW_IME_BUTTON:
-                    mCallbacks.setImeWindowStatus((IBinder)msg.obj, msg.arg1, msg.arg2);
+                    mCallbacks.setImeWindowStatus((IBinder) msg.obj, msg.arg1, msg.arg2);
                     break;
                 case MSG_SET_HARD_KEYBOARD_STATUS:
                     mCallbacks.setHardKeyboardStatus(msg.arg1 != 0, msg.arg2 != 0);
@@ -312,6 +315,7 @@
                 case MSG_SET_WINDOW_STATE:
                     mCallbacks.setWindowState(msg.arg1, msg.arg2);
                     break;
+
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index b3d8688..61aad6f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -19,33 +19,71 @@
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
+import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.R;
 
-public class ExpandableNotificationRow extends FrameLayout {
-    private int mRowHeight;
+public class ExpandableNotificationRow extends ActivatableNotificationView {
+    private int mRowMinHeight;
+    private int mRowMaxHeight;
 
-    /** does this row contain layouts that can adapt to row expansion */
+    /** Does this row contain layouts that can adapt to row expansion */
     private boolean mExpandable;
-    /** has the user manually expanded this row */
+    /** Has the user actively changed the expansion state of this row */
+    private boolean mHasUserChangedExpansion;
+    /** If {@link #mHasUserChangedExpansion}, has the user expanded this row */
     private boolean mUserExpanded;
-    /** is the user touching this row */
+    /** Is the user touching this row */
     private boolean mUserLocked;
-    /** are we showing the "public" version */
+    /** Are we showing the "public" version */
     private boolean mShowingPublic;
 
+    /**
+     * Is this notification expanded by the system. The expansion state can be overridden by the
+     * user expansion.
+     */
+    private boolean mIsSystemExpanded;
+
+    /**
+     * Whether the notification expansion is disabled. This is the case on Keyguard.
+     */
+    private boolean mExpansionDisabled;
+
+    private NotificationContentView mPublicLayout;
+    private NotificationContentView mPrivateLayout;
+    private int mMaxExpandHeight;
+    private NotificationActivator mActivator;
+
     public ExpandableNotificationRow(Context context, AttributeSet attrs) {
         super(context, attrs);
     }
 
-    public int getRowHeight() {
-        return mRowHeight;
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mPublicLayout = (NotificationContentView) findViewById(R.id.expandedPublic);
+        mPrivateLayout = (NotificationContentView) findViewById(R.id.expanded);
+
+        mActivator = new NotificationActivator(this);
     }
 
-    public void setRowHeight(int rowHeight) {
-        this.mRowHeight = rowHeight;
+    @Override
+    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
+        if (super.onRequestSendAccessibilityEvent(child, event)) {
+            // Add a record for the entire layout since its content is somehow small.
+            // The event comes from a leaf view that is interacted with.
+            AccessibilityEvent record = AccessibilityEvent.obtain();
+            onInitializeAccessibilityEvent(record);
+            dispatchPopulateAccessibilityEvent(record);
+            event.appendRecord(record);
+            return true;
+        }
+        return false;
+    }
+
+    public void setHeightRange(int rowMinHeight, int rowMaxHeight) {
+        mRowMinHeight = rowMinHeight;
+        mRowMaxHeight = rowMaxHeight;
     }
 
     public boolean isExpandable() {
@@ -56,11 +94,24 @@
         mExpandable = expandable;
     }
 
+    /**
+     * @return whether the user has changed the expansion state
+     */
+    public boolean hasUserChangedExpansion() {
+        return mHasUserChangedExpansion;
+    }
+
     public boolean isUserExpanded() {
         return mUserExpanded;
     }
 
+    /**
+     * Set this notification to be expanded by the user
+     *
+     * @param userExpanded whether the user wants this notification to be expanded
+     */
     public void setUserExpanded(boolean userExpanded) {
+        mHasUserChangedExpansion = true;
         mUserExpanded = userExpanded;
     }
 
@@ -72,25 +123,138 @@
         mUserLocked = userLocked;
     }
 
-    public void setExpanded(boolean expand) {
-        ViewGroup.LayoutParams lp = getLayoutParams();
+    /**
+     * @return has the system set this notification to be expanded
+     */
+    public boolean isSystemExpanded() {
+        return mIsSystemExpanded;
+    }
+
+    /**
+     * Set this notification to be expanded by the system.
+     *
+     * @param expand whether the system wants this notification to be expanded.
+     */
+    public void setSystemExpanded(boolean expand) {
+        mIsSystemExpanded = expand;
+        applyExpansionToLayout();
+    }
+
+    /**
+     * @param expansionDisabled whether to prevent notification expansion
+     */
+    public void setExpansionDisabled(boolean expansionDisabled) {
+        mExpansionDisabled = expansionDisabled;
+        applyExpansionToLayout();
+    }
+
+    /**
+     * Apply an expansion state to the layout.
+     */
+    public void applyExpansionToLayout() {
+        boolean expand = isExpanded();
         if (expand && mExpandable) {
-            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
+            setActualHeight(mMaxExpandHeight);
         } else {
-            lp.height = mRowHeight;
+            setActualHeight(mRowMinHeight);
         }
-        setLayoutParams(lp);
+    }
+
+    /**
+     * If {@link #isExpanded()} then this is the greatest possible height this view can
+     * get and otherwise it is {@link #mRowMinHeight}.
+     *
+     * @return the maximum allowed expansion height of this view.
+     */
+    public int getMaximumAllowedExpandHeight() {
+        if (isUserLocked()) {
+            return getActualHeight();
+        }
+        boolean inExpansionState = isExpanded();
+        if (!inExpansionState) {
+            // not expanded, so we return the collapsed size
+            return mRowMinHeight;
+        }
+
+        return mShowingPublic ? mRowMinHeight : getMaxExpandHeight();
+    }
+
+    /**
+     * Check whether the view state is currently expanded. This is given by the system in {@link
+     * #setSystemExpanded(boolean)} and can be overridden by user expansion or
+     * collapsing in {@link #setUserExpanded(boolean)}. Note that the visual appearance of this
+     * view can differ from this state, if layout params are modified from outside.
+     *
+     * @return whether the view state is currently expanded.
+     */
+    private boolean isExpanded() {
+        return !mExpansionDisabled
+                && (!hasUserChangedExpansion() && isSystemExpanded() || isUserExpanded());
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        boolean updateExpandHeight = mMaxExpandHeight == 0;
+        mMaxExpandHeight = mPrivateLayout.getMaxHeight();
+        if (updateExpandHeight) {
+            applyExpansionToLayout();
+        }
     }
 
     public void setShowingPublic(boolean show) {
         mShowingPublic = show;
-        final ViewGroup publicLayout = (ViewGroup) findViewById(R.id.expandedPublic);
 
         // bail out if no public version
-        if (publicLayout.getChildCount() == 0) return;
+        if (mPublicLayout.getChildCount() == 0) return;
 
         // TODO: animation?
-        publicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
-        findViewById(R.id.expanded).setVisibility(show ? View.GONE : View.VISIBLE);
+        mPublicLayout.setVisibility(show ? View.VISIBLE : View.GONE);
+        mPrivateLayout.setVisibility(show ? View.GONE : View.VISIBLE);
+    }
+
+    /**
+     * Sets the notification as dimmed, meaning that it will appear in a more gray variant.
+     */
+    public void setDimmed(boolean dimmed) {
+        super.setDimmed(dimmed);
+        mActivator.setDimmed(dimmed);
+    }
+
+    public int getMaxExpandHeight() {
+        return mMaxExpandHeight;
+    }
+
+    public NotificationActivator getActivator() {
+        return mActivator;
+    }
+
+    /**
+     * @return the potential height this view could expand in addition.
+     */
+    public int getExpandPotential() {
+        return getMaximumAllowedExpandHeight() - getActualHeight();
+    }
+
+    @Override
+    public void setActualHeight(int height) {
+        mPrivateLayout.setActualHeight(height);
+        invalidate();
+        super.setActualHeight(height);
+    }
+
+    @Override
+    public int getMaxHeight() {
+        return mPrivateLayout.getMaxHeight();
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        mPrivateLayout.setClipTopAmount(clipTopAmount);
+    }
+
+    public void notifyContentUpdated() {
+        mPrivateLayout.notifyContentUpdated();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
new file mode 100644
index 0000000..43eb5b5
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableOutlineView.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.Outline;
+import android.util.AttributeSet;
+import android.widget.FrameLayout;
+
+/**
+ * Like {@link ExpandableView}, but setting an outline for the height and clipping.
+ */
+public abstract class ExpandableOutlineView extends ExpandableView {
+
+    private final Outline mOutline = new Outline();
+
+    public ExpandableOutlineView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setActualHeight(int actualHeight) {
+        super.setActualHeight(actualHeight);
+        updateOutline();
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        updateOutline();
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        updateOutline();
+    }
+
+    private void updateOutline() {
+        mOutline.setRect(0,
+                mClipTopAmount,
+                getWidth(),
+                Math.max(mActualHeight, mClipTopAmount));
+        setOutline(mOutline);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
new file mode 100644
index 0000000..35913fa
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Outline;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.InsetDrawable;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.FrameLayout;
+
+/**
+ * An abstract view for expandable views.
+ */
+public abstract class ExpandableView extends FrameLayout {
+
+    private OnHeightChangedListener mOnHeightChangedListener;
+    protected int mActualHeight;
+    protected int mClipTopAmount;
+    protected Drawable mCustomBackground;
+    private boolean mActualHeightInitialized;
+
+    public ExpandableView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        if (mCustomBackground != null) {
+            mCustomBackground.setBounds(0, mClipTopAmount, getWidth(), mActualHeight);
+            mCustomBackground.draw(canvas);
+        }
+    }
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || who == mCustomBackground;
+    }
+
+    @Override
+    protected void drawableStateChanged() {
+        final Drawable d = mCustomBackground;
+        if (d != null && d.isStateful()) {
+            d.setState(getDrawableState());
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (!mActualHeightInitialized && mActualHeight == 0) {
+            mActualHeight = getHeight();
+        }
+        mActualHeightInitialized = true;
+    }
+
+    /**
+     * Sets the actual height of this notification. This is different than the laid out
+     * {@link View#getHeight()}, as we want to avoid layouting during scrolling and expanding.
+     */
+    public void setActualHeight(int actualHeight) {
+        mActualHeight = actualHeight;
+        invalidate();
+        if (mOnHeightChangedListener != null) {
+            mOnHeightChangedListener.onHeightChanged(this);
+        }
+    }
+
+    /**
+     * See {@link #setActualHeight}.
+     *
+     * @return The actual height of this notification.
+     */
+    public int getActualHeight() {
+        return mActualHeight;
+    }
+
+    /**
+     * @return The maximum height of this notification.
+     */
+    public abstract int getMaxHeight();
+
+    /**
+     * Sets the amount this view should be clipped from the top. This is used when an expanded
+     * notification is scrolling in the top or bottom stack.
+     *
+     * @param clipTopAmount The amount of pixels this view should be clipped from top.
+     */
+    public void setClipTopAmount(int clipTopAmount) {
+        mClipTopAmount = clipTopAmount;
+        invalidate();
+    }
+
+    public void setOnHeightChangedListener(OnHeightChangedListener listener) {
+        mOnHeightChangedListener = listener;
+    }
+
+    /**
+     * Sets a custom background drawable. As we need to change our bounds independently of layout,
+     * we need the notition of a custom background.
+     */
+    public void setCustomBackground(Drawable customBackground) {
+        if (mCustomBackground != null) {
+            mCustomBackground.setCallback(null);
+            unscheduleDrawable(mCustomBackground);
+        }
+        mCustomBackground = customBackground;
+        mCustomBackground.setCallback(this);
+        setWillNotDraw(customBackground == null);
+        invalidate();
+    }
+
+    public void setCustomBackgroundResource(int drawableResId) {
+        setCustomBackground(getResources().getDrawable(drawableResId));
+    }
+
+    /**
+     * A listener notifying when {@link #getActualHeight} changes.
+     */
+    public interface OnHeightChangedListener {
+        void onHeightChanged(ExpandableView view);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
new file mode 100644
index 0000000..6401695
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/InterceptedNotifications.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar;
+
+import android.app.Notification;
+import android.content.Context;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.Process;
+import android.service.notification.StatusBarNotification;
+import android.util.ArrayMap;
+import android.view.View;
+
+import com.android.systemui.R;
+import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.phone.PhoneStatusBar;
+
+public class InterceptedNotifications {
+    private static final String TAG = "InterceptedNotifications";
+    private static final String EXTRA_INTERCEPT = "android.intercept";
+
+    private final Context mContext;
+    private final PhoneStatusBar mBar;
+    private final ArrayMap<IBinder, StatusBarNotification> mIntercepted
+            = new ArrayMap<IBinder, StatusBarNotification>();
+
+    private Binder mSynKey;
+
+    public InterceptedNotifications(Context context, PhoneStatusBar bar) {
+        mContext = context;
+        mBar = bar;
+    }
+
+    public void releaseIntercepted() {
+        final int n = mIntercepted.size();
+        for (int i = 0; i < n; i++) {
+            final IBinder key = mIntercepted.keyAt(i);
+            final StatusBarNotification sbn = mIntercepted.valueAt(i);
+            sbn.getNotification().extras.putBoolean(EXTRA_INTERCEPT, false);
+            mBar.addNotification(key, sbn);
+        }
+        mIntercepted.clear();
+        updateSyntheticNotification();
+    }
+
+    public boolean tryIntercept(IBinder key, StatusBarNotification notification) {
+        if (!notification.getNotification().extras.getBoolean(EXTRA_INTERCEPT)) return false;
+        mIntercepted.put(key, notification);
+        updateSyntheticNotification();
+        return true;
+    }
+
+    public void remove(IBinder key) {
+        if (mIntercepted.remove(key) != null) {
+            updateSyntheticNotification();
+        }
+    }
+
+    public boolean isSyntheticEntry(Entry ent) {
+        return mSynKey != null && ent.key.equals(mSynKey);
+    }
+
+    public void update(IBinder key, StatusBarNotification notification) {
+        if (mIntercepted.containsKey(key)) {
+            mIntercepted.put(key, notification);
+        }
+    }
+
+    private void updateSyntheticNotification() {
+        if (mIntercepted.isEmpty()) {
+            if (mSynKey != null) {
+                mBar.removeNotification(mSynKey);
+                mSynKey = null;
+            }
+            return;
+        }
+        final Notification n = new Notification.Builder(mContext)
+                .setSmallIcon(R.drawable.stat_sys_zen_limited)
+                .setContentTitle(mContext.getResources().getQuantityString(
+                        R.plurals.zen_mode_notification_title,
+                        mIntercepted.size(), mIntercepted.size()))
+                .setContentText(mContext.getString(R.string.zen_mode_notification_text))
+                .setOngoing(true)
+                .build();
+        final StatusBarNotification sbn = new StatusBarNotification(mContext.getPackageName(),
+                mContext.getBasePackageName(),
+                TAG.hashCode(), TAG, Process.myUid(), Process.myPid(), 0, n,
+                mBar.getCurrentUserHandle());
+        if (mSynKey == null) {
+            mSynKey = new Binder();
+            mBar.addNotification(mSynKey, sbn);
+        } else {
+           mBar.updateNotification(mSynKey, sbn);
+        }
+        final NotificationData.Entry entry = mBar.mNotificationData.findByKey(mSynKey);
+        entry.row.setOnClickListener(mSynClickListener);
+    }
+
+    private final View.OnClickListener mSynClickListener = new View.OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            releaseIntercepted();
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java b/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
deleted file mode 100644
index 6419777..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/LatestItemView.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.
- */
-
-package com.android.systemui.statusbar;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-import android.widget.FrameLayout;
-
-public class LatestItemView extends FrameLayout {
-    public LatestItemView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    public void setOnClickListener(OnClickListener l) {
-        super.setOnClickListener(l);
-    }
-
-    @Override
-    public boolean onRequestSendAccessibilityEvent(View child, AccessibilityEvent event) {
-        if (super.onRequestSendAccessibilityEvent(child, event)) {
-            // Add a record for the entire layout since its content is somehow small.
-            // The event comes from a leaf view that is interacted with.
-            AccessibilityEvent record = AccessibilityEvent.obtain();
-            onInitializeAccessibilityEvent(record);
-            dispatchPopulateAccessibilityEvent(record);
-            event.appendRecord(record);
-            return true;
-        }
-        return false;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
new file mode 100644
index 0000000..620e457
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationActivator.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+
+import com.android.systemui.R;
+
+/**
+ * A helper class used by both {@link com.android.systemui.statusbar.ExpandableNotificationRow} and
+ * {@link com.android.systemui.statusbar.NotificationOverflowIconsView} to make a notification look
+ * active after tapping it once on the Keyguard.
+ */
+public class NotificationActivator {
+
+    private static final int ANIMATION_LENGTH_MS = 220;
+    private static final float INVERSE_ALPHA = 0.9f;
+    private static final float DIMMED_SCALE = 0.95f;
+
+    private final View mTargetView;
+
+    private final Interpolator mFastOutSlowInInterpolator;
+    private final Interpolator mLinearOutSlowInInterpolator;
+    private final int mTranslationZ;
+
+    public NotificationActivator(View targetView) {
+        mTargetView = targetView;
+        Context ctx = targetView.getContext();
+        mFastOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(ctx, android.R.interpolator.fast_out_slow_in);
+        mLinearOutSlowInInterpolator =
+                AnimationUtils.loadInterpolator(ctx, android.R.interpolator.linear_out_slow_in);
+        mTranslationZ =
+                ctx.getResources().getDimensionPixelSize(R.dimen.z_distance_between_notifications);
+        mTargetView.animate().setDuration(ANIMATION_LENGTH_MS);
+    }
+
+    public void activateInverse() {
+        mTargetView.animate().withLayer().alpha(INVERSE_ALPHA);
+    }
+
+    public void activate() {
+        mTargetView.animate()
+                .setInterpolator(mLinearOutSlowInInterpolator)
+                .scaleX(1)
+                .scaleY(1)
+                .translationZBy(mTranslationZ);
+    }
+
+    public void reset() {
+        mTargetView.animate()
+                .setInterpolator(mFastOutSlowInInterpolator)
+                .scaleX(DIMMED_SCALE)
+                .scaleY(DIMMED_SCALE)
+                .translationZBy(-mTranslationZ);
+        if (mTargetView.getAlpha() != 1.0f) {
+            mTargetView.animate().withLayer().alpha(1);
+        }
+    }
+
+    public void setDimmed(boolean dimmed) {
+        if (dimmed) {
+            mTargetView.setScaleX(DIMMED_SCALE);
+            mTargetView.setScaleY(DIMMED_SCALE);
+        } else {
+            mTargetView.setScaleX(1);
+            mTargetView.setScaleY(1);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
new file mode 100644
index 0000000..fd0cb08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.view.Gravity;
+import android.view.View;
+
+import com.android.systemui.R;
+
+/**
+ * A frame layout containing the actual payload of the notification, including the contracted and
+ * expanded layout. This class is responsible for clipping the content and and switching between the
+ * expanded and contracted view depending on its clipped size.
+ */
+public class NotificationContentView extends ExpandableView {
+
+    private final Rect mClipBounds = new Rect();
+
+    private View mContractedChild;
+    private View mExpandedChild;
+
+    private int mSmallHeight;
+
+    public NotificationContentView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+        mSmallHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+        mActualHeight = mSmallHeight;
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        updateClipping();
+    }
+
+    public void setContractedChild(View child) {
+        if (mContractedChild != null) {
+            removeView(mContractedChild);
+        }
+        sanitizeContractedLayoutParams(child);
+        addView(child);
+        mContractedChild = child;
+        selectLayout();
+    }
+
+    public void setExpandedChild(View child) {
+        if (mExpandedChild != null) {
+            removeView(mExpandedChild);
+        }
+        addView(child);
+        mExpandedChild = child;
+        selectLayout();
+    }
+
+    @Override
+    public void setActualHeight(int actualHeight) {
+        super.setActualHeight(actualHeight);
+        selectLayout();
+        updateClipping();
+    }
+
+    @Override
+    public int getMaxHeight() {
+
+        // The maximum height is just the laid out height.
+        return getHeight();
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        super.setClipTopAmount(clipTopAmount);
+        updateClipping();
+    }
+
+    public int getClipTopAmount() {
+        return mClipTopAmount;
+    }
+
+    private void updateClipping() {
+        mClipBounds.set(0, mClipTopAmount, getWidth(), mActualHeight);
+        setClipBounds(mClipBounds);
+    }
+
+    private void sanitizeContractedLayoutParams(View contractedChild) {
+        LayoutParams lp = (LayoutParams) contractedChild.getLayoutParams();
+        lp.height = mSmallHeight;
+        contractedChild.setLayoutParams(lp);
+    }
+
+    private void selectLayout() {
+        if (mActualHeight <= mSmallHeight || mExpandedChild == null) {
+            if (mContractedChild.getVisibility() != View.VISIBLE) {
+                mContractedChild.setVisibility(View.VISIBLE);
+            }
+            if (mExpandedChild != null && mExpandedChild.getVisibility() != View.INVISIBLE) {
+                mExpandedChild.setVisibility(View.INVISIBLE);
+            }
+        } else {
+            if (mExpandedChild.getVisibility() != View.VISIBLE) {
+                mExpandedChild.setVisibility(View.VISIBLE);
+            }
+            if (mContractedChild.getVisibility() != View.INVISIBLE) {
+                mContractedChild.setVisibility(View.INVISIBLE);
+            }
+        }
+    }
+
+    public void notifyContentUpdated() {
+        selectLayout();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
index b9a59dd..6b6f55a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationData.java
@@ -33,7 +33,6 @@
         public StatusBarNotification notification;
         public StatusBarIconView icon;
         public ExpandableNotificationRow row; // the outer expanded view
-        public View content; // takes the click events and sends the PendingIntent
         public View expanded; // the inflated RemoteViews
         public View expandedPublic; // for insecure lockscreens
         public ImageView largeIcon;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
new file mode 100644
index 0000000..8ebd50d
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowContainer.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+import com.android.systemui.R;
+
+/**
+ * Container view for overflowing notification icons on Keyguard.
+ */
+public class NotificationOverflowContainer extends ActivatableNotificationView {
+
+    private NotificationOverflowIconsView mIconsView;
+    private NotificationActivator mActivator;
+
+    public NotificationOverflowContainer(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    public void setActualHeight(int currentHeight) {
+        // noop
+    }
+
+    @Override
+    public int getActualHeight() {
+        return getHeight();
+    }
+
+    @Override
+    public int getMaxHeight() {
+        return getHeight();
+    }
+
+    @Override
+    public void setClipTopAmount(int clipTopAmount) {
+        // noop
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mIconsView = (NotificationOverflowIconsView) findViewById(R.id.overflow_icons_view);
+        mIconsView.setMoreText((TextView) findViewById(R.id.more_text));
+
+        mActivator = new NotificationActivator(this);
+        mActivator.setDimmed(true);
+        setLocked(true);
+        setDimmed(true);
+    }
+
+    public NotificationOverflowIconsView getIconsView() {
+        return mIconsView;
+    }
+
+    public NotificationActivator getActivator() {
+        return mActivator;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
new file mode 100644
index 0000000..ce31894
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationOverflowIconsView.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar;
+
+import android.app.Notification;
+import android.content.Context;
+import android.graphics.Color;
+import android.graphics.PorterDuff;
+import android.util.AttributeSet;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import com.android.internal.statusbar.StatusBarIcon;
+import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.IconMerger;
+
+/**
+ * A view to display all the overflowing icons on Keyguard.
+ */
+public class NotificationOverflowIconsView extends IconMerger {
+
+    private TextView mMoreText;
+    private int mTintColor;
+
+    public NotificationOverflowIconsView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mTintColor = getResources().getColor(R.color.keyguard_overflow_content_color);
+    }
+
+    public void setMoreText(TextView moreText) {
+        mMoreText = moreText;
+    }
+
+    public void addNotification(NotificationData.Entry notification) {
+        StatusBarIconView v = new StatusBarIconView(getContext(), "",
+                notification.notification.getNotification());
+        v.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
+        v.setColorFilter(mTintColor, PorterDuff.Mode.MULTIPLY);
+        addView(v);
+        v.set(notification.icon.getStatusBarIcon());
+        updateMoreText();
+    }
+
+    private void updateMoreText() {
+        mMoreText.setText(getResources().getQuantityString(
+                R.plurals.keyguard_more_overflow_text, getChildCount(), getChildCount()));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
new file mode 100644
index 0000000..3cc22ef
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActivityManagerNative;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.provider.MediaStore;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewConfiguration;
+import android.view.accessibility.AccessibilityManager;
+import android.view.animation.AccelerateInterpolator;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.FrameLayout;
+
+import com.android.systemui.R;
+
+/**
+ * Implementation for the bottom area of the Keyguard, including camera/phone affordance and status
+ * text.
+ */
+public class KeyguardBottomAreaView extends FrameLayout {
+
+    final static String TAG = "PhoneStatusBar/KeyguardBottomAreaView";
+
+    private View mCameraButton;
+    private float mCameraDragDistance;
+    private PowerManager mPowerManager;
+    private int mScaledTouchSlop;
+
+    public KeyguardBottomAreaView(Context context) {
+        super(context);
+    }
+
+    public KeyguardBottomAreaView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public KeyguardBottomAreaView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    @Override
+    protected void onFinishInflate() {
+        super.onFinishInflate();
+        mCameraButton = findViewById(R.id.camera_button);
+        watchForDevicePolicyChanges();
+        watchForAccessibilityChanges();
+        updateCameraVisibility();
+        mCameraDragDistance = getResources().getDimension(R.dimen.camera_drag_distance);
+        mScaledTouchSlop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+    }
+
+    private void updateCameraVisibility() {
+        boolean visible = !isCameraDisabledByDpm();
+        mCameraButton.setVisibility(visible ? View.VISIBLE : View.GONE);
+    }
+
+    private boolean isCameraDisabledByDpm() {
+        final DevicePolicyManager dpm =
+                (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
+        if (dpm != null) {
+            try {
+                final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
+                final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
+                final  boolean disabledBecauseKeyguardSecure =
+                        (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
+                                && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
+                return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Can't get userId", e);
+            }
+        }
+        return false;
+    }
+
+    private void watchForDevicePolicyChanges() {
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
+        getContext().registerReceiver(new BroadcastReceiver() {
+            public void onReceive(Context context, Intent intent) {
+                post(new Runnable() {
+                    @Override
+                    public void run() {
+                        updateCameraVisibility();
+                    }
+                });
+            }
+        }, filter);
+    }
+
+    private void watchForAccessibilityChanges() {
+        final AccessibilityManager am =
+                (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+        // Set the initial state
+        enableAccessibility(am.isTouchExplorationEnabled());
+
+        // Watch for changes
+        am.addTouchExplorationStateChangeListener(
+                new AccessibilityManager.TouchExplorationStateChangeListener() {
+            @Override
+            public void onTouchExplorationStateChanged(boolean enabled) {
+                enableAccessibility(enabled);
+            }
+        });
+    }
+
+    private void enableAccessibility(boolean touchExplorationEnabled) {
+
+        // Add a touch handler or accessibility click listener for camera button.
+        if (touchExplorationEnabled) {
+            mCameraButton.setOnTouchListener(null);
+            mCameraButton.setOnClickListener(mCameraClickListener);
+        } else {
+            mCameraButton.setOnTouchListener(mCameraTouchListener);
+            mCameraButton.setOnClickListener(null);
+        }
+    }
+
+    private void launchCamera() {
+        mContext.startActivityAsUser(
+                new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA_SECURE),
+                UserHandle.CURRENT);
+    }
+
+    private final OnClickListener mCameraClickListener = new OnClickListener() {
+        @Override
+        public void onClick(View v) {
+            launchCamera();
+        }
+    };
+
+    private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
+        private float mStartX;
+        private boolean mTouchSlopReached;
+        private boolean mSkipCancelAnimation;
+
+        @Override
+        public boolean onTouch(final View cameraButtonView, MotionEvent event) {
+            float realX = event.getRawX();
+            switch (event.getAction()) {
+                case MotionEvent.ACTION_DOWN:
+                    mStartX = realX;
+                    mTouchSlopReached = false;
+                    mSkipCancelAnimation = false;
+                    break;
+                case MotionEvent.ACTION_MOVE:
+                    if (realX > mStartX) {
+                        realX = mStartX;
+                    }
+                    if (realX < mStartX - mCameraDragDistance) {
+                        cameraButtonView.setPressed(true);
+                        mPowerManager.userActivity(event.getEventTime(), false);
+                    } else {
+                        cameraButtonView.setPressed(false);
+                    }
+                    if (realX < mStartX - mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    cameraButtonView.setTranslationX(Math.max(realX - mStartX,
+                            -mCameraDragDistance));
+                    break;
+                case MotionEvent.ACTION_UP:
+                    if (realX < mStartX - mCameraDragDistance) {
+                        launchCamera();
+                        cameraButtonView.animate().x(-cameraButtonView.getWidth())
+                                .setInterpolator(new AccelerateInterpolator(2f)).withEndAction(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        cameraButtonView.setTranslationX(0);
+                                    }
+                                });
+                        mSkipCancelAnimation = true;
+                    }
+                    if (realX < mStartX - mScaledTouchSlop) {
+                        mTouchSlopReached = true;
+                    }
+                    if (!mTouchSlopReached) {
+                        mSkipCancelAnimation = true;
+                        cameraButtonView.animate().translationX(-mCameraDragDistance / 2).
+                                setInterpolator(new DecelerateInterpolator()).withEndAction(
+                                new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        cameraButtonView.animate().translationX(0).
+                                                setInterpolator(new AccelerateInterpolator());
+                                    }
+                                });
+                    }
+                case MotionEvent.ACTION_CANCEL:
+                    cameraButtonView.setPressed(false);
+                    if (!mSkipCancelAnimation) {
+                        cameraButtonView.animate().translationX(0)
+                                .setInterpolator(new AccelerateInterpolator(2f));
+                    }
+                    break;
+            }
+            return true;
+        }
+    };
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
new file mode 100644
index 0000000..1ffb4ee
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardViewBase;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+import static com.android.keyguard.KeyguardSecurityModel.*;
+
+/**
+ * A class which manages the bouncer on the lockscreen.
+ */
+public class KeyguardBouncer {
+
+    private Context mContext;
+    private ViewMediatorCallback mCallback;
+    private LockPatternUtils mLockPatternUtils;
+    private ViewGroup mContainer;
+    private StatusBarWindowManager mWindowManager;
+    private KeyguardViewBase mKeyguardView;
+    private ViewGroup mRoot;
+
+    public KeyguardBouncer(Context context, ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils, StatusBarWindowManager windowManager,
+            ViewGroup container) {
+        mContext = context;
+        mCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+        mContainer = container;
+        mWindowManager = windowManager;
+    }
+
+    public void prepare() {
+        ensureView();
+    }
+
+    public void show() {
+        ensureView();
+
+        // Try to dismiss the Keyguard. If no security pattern is set, this will dismiss the whole
+        // Keyguard. If we need to authenticate, show the bouncer.
+        if (!mKeyguardView.dismiss()) {
+            mRoot.setVisibility(View.VISIBLE);
+            mKeyguardView.requestFocus();
+            mKeyguardView.onResume();
+        }
+    }
+
+    public void hide() {
+        if (mKeyguardView != null) {
+            mKeyguardView.cleanUp();
+        }
+        removeView();
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public void reset() {
+        inflateView();
+    }
+
+    public void onScreenTurnedOff() {
+        if (mKeyguardView != null && mRoot != null && mRoot.getVisibility() == View.VISIBLE) {
+            mKeyguardView.onPause();
+        }
+    }
+
+    public long getUserActivityTimeout() {
+        if (mKeyguardView != null) {
+            long timeout = mKeyguardView.getUserActivityTimeout();
+            if (timeout >= 0) {
+                return timeout;
+            }
+        }
+        return KeyguardViewMediator.AWAKE_INTERVAL_DEFAULT_MS;
+    }
+
+    public boolean isShowing() {
+        return mRoot != null && mRoot.getVisibility() == View.VISIBLE;
+    }
+
+    private void ensureView() {
+        if (mRoot == null) {
+            inflateView();
+        }
+    }
+
+    private void inflateView() {
+        removeView();
+        mRoot = (ViewGroup) LayoutInflater.from(mContext).inflate(R.layout.keyguard_bouncer, null);
+        mKeyguardView = (KeyguardViewBase) mRoot.findViewById(R.id.keyguard_host_view);
+        mKeyguardView.setLockPatternUtils(mLockPatternUtils);
+        mKeyguardView.setViewMediatorCallback(mCallback);
+        mContainer.addView(mRoot, mContainer.getChildCount());
+        mRoot.setVisibility(View.INVISIBLE);
+        mRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
+    }
+
+    private void removeView() {
+        if (mRoot != null && mRoot.getParent() == mContainer) {
+            mContainer.removeView(mRoot);
+            mRoot = null;
+        }
+    }
+
+    public boolean onBackPressed() {
+        return mKeyguardView != null && mKeyguardView.handleBackKey();
+    }
+
+    /**
+     * @return True if and only if the current security method should be shown before showing
+     *         the notifications on Keyguard, like SIM PIN/PUK.
+     */
+    public boolean needsFullscreenBouncer() {
+        if (mKeyguardView != null) {
+            SecurityMode mode = mKeyguardView.getSecurityMode();
+            return mode == SecurityMode.SimPin
+                    || mode == SecurityMode.SimPuk;
+        }
+        return false;
+    }
+
+    public boolean isSecure() {
+        return mKeyguardView == null || mKeyguardView.getSecurityMode() != SecurityMode.None;
+    }
+
+    public boolean onMenuPressed() {
+        ensureView();
+        if (mKeyguardView.handleMenuKey()) {
+
+            // We need to show it in case it is secure. If not, it will get dismissed in any case.
+            mRoot.setVisibility(View.VISIBLE);
+            mKeyguardView.requestFocus();
+            mKeyguardView.onResume();
+            return true;
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
new file mode 100644
index 0000000..769b1b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardIndicationTextView.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.util.AttributeSet;
+import android.widget.TextView;
+
+/**
+ * A view to show hints on Keyguard ("Swipe up to unlock", "Tap again to open").
+ */
+public class KeyguardIndicationTextView extends TextView {
+
+    public KeyguardIndicationTextView(Context context) {
+        super(context);
+    }
+
+    public KeyguardIndicationTextView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+    }
+
+    public KeyguardIndicationTextView(Context context, AttributeSet attrs, int defStyleAttr) {
+        super(context, attrs, defStyleAttr);
+    }
+
+    public KeyguardIndicationTextView(Context context, AttributeSet attrs, int defStyleAttr,
+            int defStyleRes) {
+        super(context, attrs, defStyleAttr, defStyleRes);
+    }
+
+    /**
+     * Changes the text with an animation and makes sure a single indication is shown long enough.
+     *
+     * @param text The text to show.
+     */
+    public void switchIndication(CharSequence text) {
+
+        // TODO: Animation, make sure that we will show one indication long enough.
+        setText(text);
+    }
+
+    /**
+     * See {@link #switchIndication}.
+     */
+    public void switchIndication(int textResId) {
+        switchIndication(getResources().getText(textResId));
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
index 1ea920d..754075a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardTouchDelegate.java
@@ -39,8 +39,8 @@
  */
 public class KeyguardTouchDelegate {
     // TODO: propagate changes to these to {@link KeyguardServiceDelegate}
-    static final String KEYGUARD_PACKAGE = "com.android.keyguard";
-    static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+    static final String KEYGUARD_PACKAGE = "com.android.systemui";
+    static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
 
     private static KeyguardTouchDelegate sInstance;
     private static final List<OnKeyguardConnectionListener> sConnectionListeners =
@@ -140,16 +140,16 @@
         return false;
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         final IKeyguardService service = mService;
         if (service != null) {
             try {
-                return service.isShowingAndNotHidden();
+                return service.isShowingAndNotOccluded();
             } catch (RemoteException e) {
                 Slog.w(TAG , "Remote Exception", e);
             }
         } else {
-            Slog.w(TAG, "isShowingAndNotHidden(): NO SERVICE!");
+            Slog.w(TAG, "isShowingAndNotOccluded(): NO SERVICE!");
         }
         return false;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
index a74230b..a0582ee 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarTransitions.java
@@ -82,7 +82,6 @@
         setKeyButtonViewQuiescentAlpha(mView.getMenuButton(), alpha, animate);
 
         setKeyButtonViewQuiescentAlpha(mView.getSearchLight(), KEYGUARD_QUIESCENT_ALPHA, animate);
-        setKeyButtonViewQuiescentAlpha(mView.getCameraButton(), KEYGUARD_QUIESCENT_ALPHA, animate);
 
         applyBackButtonQuiescentAlpha(mode, animate);
 
@@ -98,7 +97,6 @@
     public void applyBackButtonQuiescentAlpha(int mode, boolean animate) {
         float backAlpha = 0;
         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getSearchLight());
-        backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getCameraButton());
         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getHomeButton());
         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getRecentsButton());
         backAlpha = maxVisibleQuiescentAlpha(backAlpha, mView.getMenuButton());
@@ -117,7 +115,7 @@
     @Override
     public void setContentVisible(boolean visible) {
         final float alpha = visible ? 1 : 0;
-        fadeContent(mView.getCameraButton(), alpha);
+        fadeContent(mView.getBackButton(), alpha);
         fadeContent(mView.getSearchLight(), alpha);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index d9e0903..3fae3f0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,20 +21,14 @@
 import android.animation.ObjectAnimator;
 import android.animation.TimeInterpolator;
 import android.animation.ValueAnimator;
-import android.app.ActivityManagerNative;
 import android.app.StatusBarManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Message;
-import android.os.RemoteException;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.view.Display;
@@ -57,8 +51,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
-import static com.android.systemui.statusbar.phone.KeyguardTouchDelegate.OnKeyguardConnectionListener;
-
 public class NavigationBarView extends LinearLayout {
     final static boolean DEBUG = false;
     final static String TAG = "PhoneStatusBar/NavigationBarView";
@@ -92,9 +84,6 @@
     final static boolean WORKAROUND_INVALID_LAYOUT = true;
     final static int MSG_CHECK_INVALID_LAYOUT = 8686;
 
-    // used to disable the camera icon in navbar when disabled by DPM
-    private boolean mCameraDisabledByDpm;
-
     // performs manual animation in sync with layout transitions
     private final NavTransitionListener mTransitionListener = new NavTransitionListener();
 
@@ -147,52 +136,12 @@
     private final OnClickListener mAccessibilityClickListener = new OnClickListener() {
         @Override
         public void onClick(View v) {
-            if (v.getId() == R.id.camera_button) {
-                KeyguardTouchDelegate.getInstance(getContext()).launchCamera();
-            } else if (v.getId() == R.id.search_light) {
+            if (v.getId() == R.id.search_light) {
                 KeyguardTouchDelegate.getInstance(getContext()).showAssistant();
             }
         }
     };
 
-    private final OnTouchListener mCameraTouchListener = new OnTouchListener() {
-        @Override
-        public boolean onTouch(View cameraButtonView, MotionEvent event) {
-            switch (event.getAction()) {
-                case MotionEvent.ACTION_DOWN:
-                    // disable search gesture while interacting with camera
-                    mDelegateHelper.setDisabled(true);
-                    mBarTransitions.setContentVisible(false);
-                    break;
-                case MotionEvent.ACTION_UP:
-                case MotionEvent.ACTION_CANCEL:
-                    mDelegateHelper.setDisabled(false);
-                    mBarTransitions.setContentVisible(true);
-                    break;
-            }
-            return KeyguardTouchDelegate.getInstance(getContext()).dispatch(event);
-        }
-    };
-
-    private final OnKeyguardConnectionListener mKeyguardConnectionListener =
-            new OnKeyguardConnectionListener() {
-                @Override
-                public void onKeyguardServiceConnected(
-                        KeyguardTouchDelegate keyguardTouchDelegate) {
-                    post(new Runnable() {
-                        @Override
-                        public void run() {
-                            mCameraDisabledByDpm = isCameraDisabledByDpm();
-                        }
-                    });
-                }
-
-                @Override
-                public void onKeyguardServiceDisconnected(
-                        KeyguardTouchDelegate keyguardTouchDelegate) {
-                }
-            };
-
     private class H extends Handler {
         public void handleMessage(Message m) {
             switch (m.what) {
@@ -231,25 +180,6 @@
         getIcons(res);
 
         mBarTransitions = new NavigationBarTransitions(this);
-
-        KeyguardTouchDelegate.addListener(mKeyguardConnectionListener);
-        mCameraDisabledByDpm = isCameraDisabledByDpm();
-        watchForDevicePolicyChanges();
-    }
-
-    private void watchForDevicePolicyChanges() {
-        final IntentFilter filter = new IntentFilter();
-        filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
-        getContext().registerReceiver(new BroadcastReceiver() {
-            public void onReceive(Context context, Intent intent) {
-                post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mCameraDisabledByDpm = isCameraDisabledByDpm();
-                    }
-                });
-            }
-        }, filter);
     }
 
     public BarTransitions getBarTransitions() {
@@ -308,11 +238,6 @@
         return mCurrentView.findViewById(R.id.search_light);
     }
 
-    // shown when keyguard is visible and camera is available
-    public View getCameraButton() {
-        return mCurrentView.findViewById(R.id.camera_button);
-    }
-
     private void getIcons(Resources res) {
         mBackIcon = res.getDrawable(R.drawable.ic_sysbar_back);
         mBackLandIcon = res.getDrawable(R.drawable.ic_sysbar_back_land);
@@ -402,9 +327,7 @@
         getRecentsButton().setVisibility(disableRecent     ? View.INVISIBLE : View.VISIBLE);
 
         final boolean showSearch = disableHome && !disableSearch;
-        final boolean showCamera = showSearch && !mCameraDisabledByDpm;
         setVisibleOrGone(getSearchLight(), showSearch);
-        setVisibleOrGone(getCameraButton(), showCamera);
 
         mBarTransitions.applyBackButtonQuiescentAlpha(mBarTransitions.getMode(), true /*animate*/);
     }
@@ -415,24 +338,6 @@
         }
     }
 
-    private boolean isCameraDisabledByDpm() {
-        final DevicePolicyManager dpm =
-                (DevicePolicyManager) getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
-        if (dpm != null) {
-            try {
-                final int userId = ActivityManagerNative.getDefault().getCurrentUser().id;
-                final int disabledFlags = dpm.getKeyguardDisabledFeatures(null, userId);
-                final  boolean disabledBecauseKeyguardSecure =
-                        (disabledFlags & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) != 0
-                        && KeyguardTouchDelegate.getInstance(getContext()).isSecure();
-                return dpm.getCameraDisabled(null) || disabledBecauseKeyguardSecure;
-            } catch (RemoteException e) {
-                Log.e(TAG, "Can't get userId", e);
-            }
-        }
-        return false;
-    }
-
     public void setSlippery(boolean newSlippery) {
         WindowManager.LayoutParams lp = (WindowManager.LayoutParams) getLayoutParams();
         if (lp != null) {
@@ -499,25 +404,12 @@
         // Add a touch handler or accessibility click listener for camera and search buttons
         // for all view orientations.
         final OnClickListener onClickListener = touchEnabled ? mAccessibilityClickListener : null;
-        final OnTouchListener onTouchListener = touchEnabled ? null : mCameraTouchListener;
-        boolean hasCamera = false;
         for (int i = 0; i < mRotatedViews.length; i++) {
-            final View cameraButton = mRotatedViews[i].findViewById(R.id.camera_button);
             final View searchLight = mRotatedViews[i].findViewById(R.id.search_light);
-            if (cameraButton != null) {
-                hasCamera = true;
-                cameraButton.setOnTouchListener(onTouchListener);
-                cameraButton.setOnClickListener(onClickListener);
-            }
             if (searchLight != null) {
                 searchLight.setOnClickListener(onClickListener);
             }
         }
-        if (hasCamera) {
-            // Warm up KeyguardTouchDelegate so it's ready by the time the camera button is touched.
-            // This will connect to KeyguardService so that touch events are processed.
-            KeyguardTouchDelegate.getInstance(getContext());
-        }
     }
 
     public boolean isVertical() {
@@ -654,7 +546,6 @@
         dumpButton(pw, "rcnt", getRecentsButton());
         dumpButton(pw, "menu", getMenuButton());
         dumpButton(pw, "srch", getSearchLight());
-        dumpButton(pw, "cmra", getCameraButton());
 
         pw.println("    }");
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 2d2f2f1..712eec8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -23,18 +23,21 @@
 import android.view.accessibility.AccessibilityEvent;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.GestureRecorder;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
-public class NotificationPanelView extends PanelView {
+public class NotificationPanelView extends PanelView implements
+        ExpandableView.OnHeightChangedListener {
     public static final boolean DEBUG_GESTURES = true;
 
     PhoneStatusBar mStatusBar;
-    private NotificationStackScrollLayout mNotificationStackScroller;
-    private int[] mTempLocation = new int[2];
-    private int[] mTempChildLocation = new int[2];
-    private View mNotificationParent;
+    private View mHeader;
+    private View mKeyguardStatusView;
 
+    private NotificationStackScrollLayout mNotificationStackScroller;
+    private boolean mTrackingSettings;
+    private int mNotificationTopPadding;
 
     public NotificationPanelView(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -59,9 +62,23 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
 
+        mHeader = findViewById(R.id.header);
+        mKeyguardStatusView = findViewById(R.id.keyguard_status_view);
         mNotificationStackScroller = (NotificationStackScrollLayout)
                 findViewById(R.id.notification_stack_scroller);
-        mNotificationParent = findViewById(R.id.notification_container_parent);
+        mNotificationStackScroller.setOnHeightChangedListener(this);
+        mNotificationTopPadding = getResources().getDimensionPixelSize(
+                R.dimen.notifications_top_padding);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        int keyguardBottomMargin =
+                ((MarginLayoutParams) mKeyguardStatusView.getLayoutParams()).bottomMargin;
+        mNotificationStackScroller.setTopPadding(mStatusBar.isOnKeyguard()
+                ? mKeyguardStatusView.getBottom() + keyguardBottomMargin
+                : mHeader.getBottom() + mNotificationTopPadding);
     }
 
     @Override
@@ -86,22 +103,39 @@
         return super.dispatchPopulateAccessibilityEvent(event);
     }
 
-    /**
-     * Gets the relative position of a view on the screen in regard to this view.
-     *
-     * @param requestedView the view we want to find the relative position for
-     * @return
-     */
-    private int getRelativeTop(View requestedView) {
-        getLocationOnScreen(mTempLocation);
-        requestedView.getLocationOnScreen(mTempChildLocation);
-        return mTempChildLocation[1] - mTempLocation[1];
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent event) {
+        // intercept for quick settings
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            final View target = mStatusBar.isOnKeyguard() ?  mKeyguardStatusView : mHeader;
+            final boolean inTarget = PhoneStatusBar.inBounds(target, event, true);
+            if (inTarget && !isInSettings()) {
+                mTrackingSettings = true;
+                return true;
+            }
+            if (!inTarget && isInSettings()) {
+                mTrackingSettings = true;
+                return true;
+            }
+        }
+        return super.onInterceptTouchEvent(event);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
         // TODO: Handle doublefinger swipe to notifications again. Look at history for a reference
         // implementation.
+        if (mTrackingSettings) {
+            mStatusBar.onSettingsEvent(event);
+            if (event.getAction() == MotionEvent.ACTION_UP
+                    || event.getAction() == MotionEvent.ACTION_CANCEL) {
+                mTrackingSettings = false;
+            }
+            return true;
+        }
+        if (isInSettings()) {
+            return true;
+        }
         return super.onTouchEvent(event);
     }
 
@@ -129,43 +163,28 @@
 
     @Override
     protected void onHeightUpdated(float expandedHeight) {
-        updateNotificationStackHeight(expandedHeight);
-    }
-
-    /**
-     * Update the height of the {@link #mNotificationStackScroller} to the new expanded height.
-     * This is much more efficient than doing it over the layout pass.
-     *
-     * @param expandedHeight the new expanded height
-     */
-    private void updateNotificationStackHeight(float expandedHeight) {
-        float childOffset = getRelativeTop(mNotificationStackScroller)
-                - mNotificationParent.getTranslationY();
-        int newStackHeight = (int) (expandedHeight - childOffset);
-        int itemHeight = mNotificationStackScroller.getItemHeight();
-        int bottomStackPeekSize = mNotificationStackScroller.getBottomStackPeekSize();
-        int minStackHeight = itemHeight + bottomStackPeekSize;
-        if (newStackHeight >= minStackHeight) {
-            mNotificationParent.setTranslationY(0);
-            mNotificationStackScroller.setCurrentStackHeight(newStackHeight);
-        } else {
-
-            // We did not reach the position yet where we actually start growing,
-            // so we translate the stack upwards.
-            int translationY = (newStackHeight - minStackHeight);
-            // A slight parallax effect is introduced in order for the stack to catch up with
-            // the top card.
-            float partiallyThere = (float) newStackHeight / minStackHeight;
-            partiallyThere = Math.max(0, partiallyThere);
-            translationY += (1 - partiallyThere) * bottomStackPeekSize;
-            mNotificationParent.setTranslationY(translationY);
-            mNotificationStackScroller.setCurrentStackHeight(
-                    (int) (expandedHeight - (childOffset + translationY)));
-        }
+        mNotificationStackScroller.setStackHeight(expandedHeight);
     }
 
     @Override
     protected int getDesiredMeasureHeight() {
         return mMaxPanelHeight;
     }
+
+    @Override
+    protected void onExpandingStarted() {
+        super.onExpandingStarted();
+        mNotificationStackScroller.onExpansionStarted();
+    }
+
+    @Override
+    protected void onExpandingFinished() {
+        super.onExpandingFinished();
+        mNotificationStackScroller.onExpansionStopped();
+    }
+
+    @Override
+    public void onHeightChanged(ExpandableView view) {
+        requestPanelHeightUpdate();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
index a3e35d1..324d6f3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelBar.java
@@ -151,7 +151,8 @@
         if (DEBUG) LOG("panelExpansionChanged: start state=%d panel=%s", mState, panel.getName());
         mPanelExpandedFractionSum = 0f;
         for (PanelView pv : mPanels) {
-            final boolean visible = pv.getVisibility() == View.VISIBLE;
+            boolean visible = pv.getExpandedHeight() > 0;
+            pv.setVisibility(visible ? View.VISIBLE : View.GONE);
             // adjust any other panels that may be partially visible
             if (pv.getExpandedHeight() > 0f) {
                 if (mState == STATE_CLOSED) {
@@ -166,11 +167,6 @@
                     if (thisFrac == 1f) fullyOpenedPanel = panel;
                 }
             }
-            if (pv.getExpandedHeight() > 0f) {
-                if (!visible) pv.setVisibility(View.VISIBLE);
-            } else {
-                if (visible) pv.setVisibility(View.GONE);
-            }
         }
         mPanelExpandedFractionSum /= mPanels.size();
         if (fullyOpenedPanel != null && !mTracking) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 20fb225..328a172 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -46,7 +46,6 @@
     }
 
     public static final boolean BRAKES = false;
-    private boolean mRubberbandingEnabled = true;
 
     private float mSelfExpandVelocityPx; // classic value: 2000px/s
     private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -68,14 +67,12 @@
     private float mExpandBrakingDistancePx = 150; // XXX Resource
     private float mBrakingSpeedPx = 150; // XXX Resource
 
-    private View mHandleView;
     private float mPeekHeight;
     private float mInitialOffsetOnTouch;
     private float mExpandedFraction = 0;
     private float mExpandedHeight = 0;
     private boolean mJustPeeked;
     private boolean mClosing;
-    private boolean mRubberbanding;
     private boolean mTracking;
     private int mTrackingPointer;
     private int mTouchSlop;
@@ -214,8 +211,8 @@
         public void run() {
             if (mTimeAnimator != null && mTimeAnimator.isStarted()) {
                 mTimeAnimator.end();
-                mRubberbanding = false;
                 mClosing = false;
+                onExpandingFinished();
             }
         }
     };
@@ -224,10 +221,13 @@
     protected int mMaxPanelHeight = 0;
     private String mViewName;
     protected float mInitialTouchY;
+    protected float mInitialTouchX;
     protected float mFinalTouchY;
 
-    public void setRubberbandingEnabled(boolean enable) {
-        mRubberbandingEnabled = enable;
+    protected void onExpandingFinished() {
+    }
+
+    protected void onExpandingStarted() {
     }
 
     private void runPeekAnimation() {
@@ -253,12 +253,7 @@
 
             mTimeAnimator.start();
 
-            mRubberbanding = mRubberbandingEnabled // is it enabled at all?
-                    && mExpandedHeight > getMaxPanelHeight() // are we past the end?
-                    && mVel >= -mFlingGestureMinDistPx; // was this not possibly a "close" gesture?
-            if (mRubberbanding) {
-                mClosing = true;
-            } else if (mVel == 0) {
+            if (mVel == 0) {
                 // if the panel is less than halfway open, close it
                 mClosing = (mFinalTouchY / getMaxPanelHeight()) < 0.5f;
             } else {
@@ -301,10 +296,6 @@
 
             float h = mExpandedHeight + mVel * dt;
 
-            if (mRubberbanding && h < fh) {
-                h = fh;
-            }
-
             if (DEBUG) logf("tick: new h=%d closing=%s", (int) h, mClosing?"true":"false");
 
             setExpandedHeightInternal(h);
@@ -313,7 +304,7 @@
 
             if (mVel == 0
                     || (mClosing && mExpandedHeight == 0)
-                    || ((mRubberbanding || !mClosing) && mExpandedHeight == fh)) {
+                    || (!mClosing && mExpandedHeight == fh)) {
                 post(mStopAnimator);
             }
         } else {
@@ -327,6 +318,7 @@
 
         mTimeAnimator = new TimeAnimator();
         mTimeAnimator.setTimeListener(mAnimationCallback);
+        setOnHierarchyChangeListener(mHierarchyListener);
     }
 
     private void loadDimens() {
@@ -350,8 +342,7 @@
         mFlingGestureMaxOutputVelocityPx = res.getDimension(R.dimen.fling_gesture_max_output_velocity);
 
         mPeekHeight = res.getDimension(R.dimen.peek_height)
-            + getPaddingBottom() // our window might have a dropshadow
-            - (mHandleView == null ? 0 : mHandleView.getPaddingTop()); // the handle might have a topshadow
+            + getPaddingBottom(); // our window might have a dropshadow
 
         final ViewConfiguration configuration = ViewConfiguration.get(getContext());
         mTouchSlop = configuration.getScaledTouchSlop();
@@ -385,20 +376,18 @@
             mTrackingPointer = event.getPointerId(pointerIndex);
         }
         final float y = event.getY(pointerIndex);
+        final float x = event.getX(pointerIndex);
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
                 mTracking = true;
-                if (mHandleView != null) {
-                    mHandleView.setPressed(true);
-                    postInvalidate(); // catch the press state change
-                }
 
                 mInitialTouchY = y;
+                mInitialTouchX = x;
                 initVelocityTracker();
                 trackMovement(event);
                 mTimeAnimator.cancel(); // end any outstanding animations
-                mBar.onTrackingStarted(PanelView.this);
+                onTrackingStarted();
                 mInitialOffsetOnTouch = mExpandedHeight;
                 if (mExpandedHeight == 0) {
                     mJustPeeked = true;
@@ -412,9 +401,11 @@
                     // gesture is ongoing, find a new pointer to track
                     final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
                     final float newY = event.getY(newIndex);
+                    final float newX = event.getX(newIndex);
                     mTrackingPointer = event.getPointerId(newIndex);
                     mInitialOffsetOnTouch = mExpandedHeight;
                     mInitialTouchY = newY;
+                    mInitialTouchX = newX;
                 }
                 break;
 
@@ -439,11 +430,7 @@
                 mFinalTouchY = y;
                 mTracking = false;
                 mTrackingPointer = -1;
-                if (mHandleView != null) {
-                    mHandleView.setPressed(false);
-                    postInvalidate(); // catch the press state change
-                }
-                mBar.onTrackingStopped(PanelView.this);
+                onTrackingStopped();
                 trackMovement(event);
 
                 float vel = getCurrentVelocity();
@@ -458,6 +445,15 @@
         return true;
     }
 
+    protected void onTrackingStopped() {
+        mBar.onTrackingStopped(PanelView.this);
+    }
+
+    protected void onTrackingStarted() {
+        mBar.onTrackingStarted(PanelView.this);
+        onExpandingStarted();
+    }
+
     private float getCurrentVelocity() {
         float vel = 0;
         float yVel = 0, xVel = 0;
@@ -524,23 +520,17 @@
             pointerIndex = 0;
             mTrackingPointer = event.getPointerId(pointerIndex);
         }
+        final float x = event.getX(pointerIndex);
         final float y = event.getY(pointerIndex);
         boolean scrolledToBottom = isScrolledToBottom();
 
         switch (event.getActionMasked()) {
             case MotionEvent.ACTION_DOWN:
-                if (mHandleView != null) {
-                    mHandleView.setPressed(true);
-                    // catch the press state change
-                    postInvalidate();
-                }
                 mInitialTouchY = y;
+                mInitialTouchX = x;
                 initVelocityTracker();
                 trackMovement(event);
                 mTimeAnimator.cancel(); // end any outstanding animations
-                if (mExpandedHeight == 0 || y > getContentHeight()) {
-                    return true;
-                }
                 break;
             case MotionEvent.ACTION_POINTER_UP:
                 final int upPointer = event.getPointerId(event.getActionIndex());
@@ -548,8 +538,8 @@
                     // gesture is ongoing, find a new pointer to track
                     final int newIndex = event.getPointerId(0) != upPointer ? 0 : 1;
                     mTrackingPointer = event.getPointerId(newIndex);
-                    final float newY = event.getY(newIndex);
-                    mInitialTouchY = newY;
+                    mInitialTouchX = event.getX(newIndex);
+                    mInitialTouchY = event.getY(newIndex);
                 }
                 break;
 
@@ -557,10 +547,12 @@
                 final float h = y - mInitialTouchY;
                 trackMovement(event);
                 if (scrolledToBottom) {
-                    if (h < -mTouchSlop) {
+                    if (h < -mTouchSlop && h < -Math.abs(x - mInitialTouchX)) {
                         mInitialOffsetOnTouch = mExpandedHeight;
                         mInitialTouchY = y;
+                        mInitialTouchX = x;
                         mTracking = true;
+                        onTrackingStarted();
                         return true;
                     }
                 }
@@ -587,7 +579,6 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-        mHandleView = findViewById(R.id.handle);
 
         loadDimens();
     }
@@ -598,6 +589,8 @@
 
         if (always||mVel != 0) {
             animationTick(0); // begin the animation
+        } else {
+            onExpandingFinished();
         }
     }
 
@@ -611,15 +604,6 @@
         return mViewName;
     }
 
-    @Override
-    protected void onViewAdded(View child) {
-        if (DEBUG) logf("onViewAdded: " + child);
-    }
-
-    public View getHandle() {
-        return mHandleView;
-    }
-
     // Rubberbands the panel to hold its contents.
     @Override
     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
@@ -632,9 +616,15 @@
         int newHeight = getMeasuredHeight();
         if (newHeight != mMaxPanelHeight) {
             mMaxPanelHeight = newHeight;
+            // If the user isn't actively poking us, let's rubberband to the content
+            if (!mTracking && !mTimeAnimator.isStarted()
+                    && mExpandedHeight > 0 && mExpandedHeight != mMaxPanelHeight
+                    && mMaxPanelHeight > 0) {
+                mExpandedHeight = mMaxPanelHeight;
+            }
         }
         heightMeasureSpec = MeasureSpec.makeMeasureSpec(
-                    getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
+                getDesiredMeasureHeight(), MeasureSpec.AT_MOST);
         setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
     }
 
@@ -645,7 +635,6 @@
 
     public void setExpandedHeight(float height) {
         if (DEBUG) logf("setExpandedHeight(%.1f)", height);
-        mRubberbanding = false;
         if (mTimeAnimator.isStarted()) {
             post(mStopAnimator);
         }
@@ -665,7 +654,7 @@
         float currentMaxPanelHeight = getMaxPanelHeight();
 
         // If the user isn't actively poking us, let's update the height
-        if (!mTracking && !mRubberbanding && !mTimeAnimator.isStarted()
+        if (!mTracking && !mTimeAnimator.isStarted()
                 && mExpandedHeight > 0 && currentMaxPanelHeight != mExpandedHeight) {
             setExpandedHeightInternal(currentMaxPanelHeight);
         }
@@ -687,13 +676,13 @@
         }
 
         if (h < 0) h = 0;
-        if (!(mRubberbandingEnabled && (mTracking || mRubberbanding)) && h > fh) h = fh;
+        if (h > fh) h = fh;
 
         mExpandedHeight = h;
 
         if (DEBUG) {
-            logf("setExpansion: height=%.1f fh=%.1f tracking=%s rubber=%s", h, fh,
-                    mTracking ? "T" : "f", mRubberbanding ? "T" : "f");
+            logf("setExpansion: height=%.1f fh=%.1f tracking=%s", h, fh,
+                    mTracking ? "T" : "f");
         }
 
         onHeightUpdated(mExpandedHeight);
@@ -770,8 +759,8 @@
         if (!isFullyCollapsed()) {
             mTimeAnimator.cancel();
             mClosing = true;
+            onExpandingStarted();
             // collapse() should never be a rubberband, even if an animation is already running
-            mRubberbanding = false;
             fling(-mSelfCollapseVelocityPx, /*always=*/ true);
         }
     }
@@ -780,6 +769,7 @@
         if (DEBUG) logf("expand: " + this);
         if (isFullyCollapsed()) {
             mBar.startOpeningPanel(this);
+            onExpandingStarted();
             fling(mSelfExpandVelocityPx, /*always=*/ true);
         } else if (DEBUG) {
             if (DEBUG) logf("skipping expansion: is expanded");
@@ -794,17 +784,27 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println(String.format("[PanelView(%s): expandedHeight=%f maxPanelHeight=%d closing=%s"
-                + " tracking=%s rubberbanding=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
+                + " tracking=%s justPeeked=%s peekAnim=%s%s timeAnim=%s%s"
                 + "]",
                 this.getClass().getSimpleName(),
                 getExpandedHeight(),
                 getMaxPanelHeight(),
                 mClosing?"T":"f",
                 mTracking?"T":"f",
-                mRubberbanding?"T":"f",
                 mJustPeeked?"T":"f",
                 mPeekAnimator, ((mPeekAnimator!=null && mPeekAnimator.isStarted())?" (started)":""),
                 mTimeAnimator, ((mTimeAnimator!=null && mTimeAnimator.isStarted())?" (started)":"")
         ));
     }
+
+    private final OnHierarchyChangeListener mHierarchyListener = new OnHierarchyChangeListener() {
+        @Override
+        public void onChildViewAdded(View parent, View child) {
+            if (DEBUG) logf("onViewAdded: " + child);
+        }
+
+        @Override
+        public void onChildViewRemoved(View parent, View child) {
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 4730f2f..545352c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -16,14 +16,15 @@
 
 package com.android.systemui.statusbar.phone;
 
+
 import static android.app.StatusBarManager.NAVIGATION_HINT_BACK_ALT;
 import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
 import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
 import static android.app.StatusBarManager.windowStateToString;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_SEMI_TRANSPARENT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_TRANSLUCENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -59,19 +60,23 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.provider.Settings;
+import android.provider.Settings.Global;
 import android.service.notification.StatusBarNotification;
+import android.util.ArraySet;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Display;
 import android.view.Gravity;
+import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.ViewPropertyAnimator;
-import android.view.ViewStub;
+import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.animation.AccelerateInterpolator;
 import android.view.animation.Animation;
@@ -83,17 +88,20 @@
 import android.widget.TextView;
 
 import com.android.internal.statusbar.StatusBarIcon;
+import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DemoMode;
 import com.android.systemui.EventLogTags;
 import com.android.systemui.R;
+import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.statusbar.BaseStatusBar;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.InterceptedNotifications;
 import com.android.systemui.statusbar.NotificationData;
 import com.android.systemui.statusbar.NotificationData.Entry;
+import com.android.systemui.statusbar.NotificationOverflowContainer;
 import com.android.systemui.statusbar.SignalClusterView;
 import com.android.systemui.statusbar.StatusBarIconView;
-
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.BluetoothController;
 import com.android.systemui.statusbar.policy.DateView;
@@ -101,12 +109,15 @@
 import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.statusbar.policy.NetworkController;
 import com.android.systemui.statusbar.policy.RotationLockController;
-
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.stack.NotificationStackScrollLayout.OnChildLocationsChangedListener;
+import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
 
 public class PhoneStatusBar extends BaseStatusBar implements DemoMode {
     static final String TAG = "PhoneStatusBar";
@@ -135,10 +146,18 @@
     private static final int NOTIFICATION_PRIORITY_MULTIPLIER = 10; // see NotificationManagerService
     private static final int HIDE_ICONS_BELOW_SCORE = Notification.PRIORITY_LOW * NOTIFICATION_PRIORITY_MULTIPLIER;
 
+    /**
+     * Default value of {@link android.provider.Settings.Global#LOCK_SCREEN_SHOW_NOTIFICATIONS}.
+     */
+    private static final boolean ALLOW_NOTIFICATIONS_DEFAULT = false;
+
     private static final int STATUS_OR_NAV_TRANSIENT =
             View.STATUS_BAR_TRANSIENT | View.NAVIGATION_BAR_TRANSIENT;
     private static final long AUTOHIDE_TIMEOUT_MS = 3000;
 
+    /** The minimum delay in ms between reports of notification visibility. */
+    private static final int VISIBILITY_REPORT_MIN_DELAY_MS = 500;
+
     // fling gesture tuning parameters, scaled to display density
     private float mSelfExpandVelocityPx; // classic value: 2000px/s
     private float mSelfCollapseVelocityPx; // classic value: 2000px/s (will be negated to collapse "up")
@@ -174,6 +193,7 @@
     StatusBarWindowView mStatusBarWindow;
     PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+    private StatusBarWindowManager mStatusBarWindowManager;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -204,17 +224,22 @@
 
     // settings
     QuickSettings mQS;
-    boolean mHasSettingsPanel, mHasFlipSettings;
-    SettingsPanelView mSettingsPanel;
+    boolean mHasQuickSettings;
     View mFlipSettingsView;
     QuickSettingsContainerView mSettingsContainer;
-    int mSettingsPanelGravity;
 
     // top bar
     View mNotificationPanelHeader;
+    View mKeyguardStatusView;
+    View mKeyguardBottomArea;
+    KeyguardIndicationTextView mKeyguardIndicationTextView;
+
+    // TODO: Fetch phrase from search/hotword provider.
+    String mKeyguardHotwordPhrase = "";
+    int mKeyguardMaxNotificationCount;
     View mDateTimeView;
     View mClearButton;
-    ImageView mSettingsButton, mNotificationButton;
+    FlipperButton mHeaderFlipper, mKeyguardFlipper;
 
     // carrier/wifi label
     private TextView mCarrierLabel;
@@ -222,6 +247,7 @@
     private int mCarrierLabelHeight;
     private TextView mEmergencyCallLabel;
     private int mNotificationHeaderHeight;
+    private View mKeyguardCarrierLabel;
 
     private boolean mShowCarrierInPanel = false;
 
@@ -294,12 +320,9 @@
             if (MULTIUSER_DEBUG) Log.d(TAG, String.format("User setup changed: " +
                     "selfChange=%s userSetup=%s mUserSetup=%s",
                     selfChange, userSetup, mUserSetup));
-            if (mSettingsButton != null && mHasFlipSettings) {
-                mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
-            }
-            if (mSettingsPanel != null) {
-                mSettingsPanel.setEnabled(userSetup);
-            }
+            mHeaderFlipper.userSetup(userSetup);
+            mKeyguardFlipper.userSetup(userSetup);
+
             if (userSetup != mUserSetup) {
                 mUserSetup = userSetup;
                 if (!mUserSetup && mStatusBarView != null)
@@ -337,6 +360,9 @@
     private int mNavigationBarMode;
     private Boolean mScreenOn;
 
+    private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private ViewMediatorCallback mKeyguardViewMediatorCallback;
+
     private final Runnable mAutohide = new Runnable() {
         @Override
         public void run() {
@@ -347,17 +373,112 @@
         }};
 
     private Runnable mOnFlipRunnable;
+    private InterceptedNotifications mIntercepted;
+    private VelocityTracker mSettingsTracker;
+    private float mSettingsDownY;
+    private boolean mSettingsStarted;
+    private boolean mSettingsCancelled;
+    private boolean mSettingsClosing;
+    private int mNotificationPadding;
+
+    private final OnChildLocationsChangedListener mOnChildLocationsChangedListener =
+            new OnChildLocationsChangedListener() {
+        @Override
+        public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout) {
+            userActivity();
+        }
+    };
 
     public void setOnFlipRunnable(Runnable onFlipRunnable) {
         mOnFlipRunnable = onFlipRunnable;
     }
 
+    /** Keys of notifications currently visible to the user. */
+    private final ArraySet<String> mCurrentlyVisibleNotifications = new ArraySet<String>();
+    private long mLastVisibilityReportUptimeMs;
+
+    private static final int VISIBLE_LOCATIONS = ViewState.LOCATION_FIRST_CARD
+            | ViewState.LOCATION_TOP_STACK_PEEKING
+            | ViewState.LOCATION_MAIN_AREA
+            | ViewState.LOCATION_BOTTOM_STACK_PEEKING;
+
+    private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
+            new OnChildLocationsChangedListener() {
+                @Override
+                public void onChildLocationsChanged(
+                        NotificationStackScrollLayout stackScrollLayout) {
+                    if (mHandler.hasCallbacks(mVisibilityReporter)) {
+                        // Visibilities will be reported when the existing
+                        // callback is executed.
+                        return;
+                    }
+                    // Calculate when we're allowed to run the visibility
+                    // reporter. Note that this timestamp might already have
+                    // passed. That's OK, the callback will just be executed
+                    // ASAP.
+                    long nextReportUptimeMs =
+                            mLastVisibilityReportUptimeMs + VISIBILITY_REPORT_MIN_DELAY_MS;
+                    mHandler.postAtTime(mVisibilityReporter, nextReportUptimeMs);
+                }
+            };
+
+    // Tracks notifications currently visible in mNotificationStackScroller and
+    // emits visibility events via NoMan on changes.
+    private final Runnable mVisibilityReporter = new Runnable() {
+        private final ArrayList<String> mTmpNewlyVisibleNotifications = new ArrayList<String>();
+        private final ArrayList<String> mTmpCurrentlyVisibleNotifications = new ArrayList<String>();
+
+        @Override
+        public void run() {
+            mLastVisibilityReportUptimeMs = SystemClock.uptimeMillis();
+
+            // 1. Loop over mNotificationData entries:
+            //   A. Keep list of visible notifications.
+            //   B. Keep list of previously hidden, now visible notifications.
+            // 2. Compute no-longer visible notifications by removing currently
+            //    visible notifications from the set of previously visible
+            //    notifications.
+            // 3. Report newly visible and no-longer visible notifications.
+            // 4. Keep currently visible notifications for next report.
+            int N = mNotificationData.size();
+            for (int i = 0; i < N; i++) {
+                Entry entry = mNotificationData.get(i);
+                String key = entry.notification.getKey();
+                boolean previouslyVisible = mCurrentlyVisibleNotifications.contains(key);
+                boolean currentlyVisible =
+                        (mStackScroller.getChildLocation(entry.row) & VISIBLE_LOCATIONS) != 0;
+                if (currentlyVisible) {
+                    // Build new set of visible notifications.
+                    mTmpCurrentlyVisibleNotifications.add(key);
+                }
+                if (!previouslyVisible && currentlyVisible) {
+                    mTmpNewlyVisibleNotifications.add(key);
+                }
+            }
+            ArraySet<String> noLongerVisibleNotifications = mCurrentlyVisibleNotifications;
+            noLongerVisibleNotifications.removeAll(mTmpCurrentlyVisibleNotifications);
+
+            logNotificationVisibilityChanges(
+                    mTmpNewlyVisibleNotifications, noLongerVisibleNotifications);
+
+            mCurrentlyVisibleNotifications.clear();
+            mCurrentlyVisibleNotifications.addAll(mTmpCurrentlyVisibleNotifications);
+
+            mTmpNewlyVisibleNotifications.clear();
+            mTmpCurrentlyVisibleNotifications.clear();
+        }
+    };
+
     @Override
     public void setZenMode(int mode) {
         super.setZenMode(mode);
         if (mModeIcon == null) return;
         if (!isDeviceProvisioned()) return;
-        mModeIcon.setVisibility(mode != Settings.Global.ZEN_MODE_OFF ? View.VISIBLE : View.GONE);
+        final boolean zen = mode != Settings.Global.ZEN_MODE_OFF;
+        mModeIcon.setVisibility(zen ? View.VISIBLE : View.GONE);
+        if (!zen) {
+            mIntercepted.releaseIntercepted();
+        }
     }
 
     @Override
@@ -365,7 +486,7 @@
         mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
                 .getDefaultDisplay();
         updateDisplaySize();
-
+        mIntercepted = new InterceptedNotifications(mContext, this);
         super.start(); // calls createAndAddWindows()
 
         addNavigationBar();
@@ -383,6 +504,7 @@
                     Settings.Global.getUriFor(SETTING_HEADS_UP_TICKER), true,
                     mHeadsUpObserver);
         }
+        startKeyguard();
     }
 
     // ================================================================================
@@ -489,11 +611,22 @@
         mStackScroller = (NotificationStackScrollLayout) mStatusBarWindow.findViewById(
                 R.id.notification_stack_scroller);
         mStackScroller.setLongPressListener(getNotificationLongClicker());
+        mStackScroller.setChildLocationsChangedListener(mOnChildLocationsChangedListener);
+
+        mKeyguardIconOverflowContainer =
+                (NotificationOverflowContainer) LayoutInflater.from(mContext).inflate(
+                        R.layout.status_bar_notification_keyguard_overflow, mStackScroller, false);
+        mKeyguardIconOverflowContainer.setOnActivatedListener(this);
+        mKeyguardCarrierLabel = mStatusBarWindow.findViewById(R.id.keyguard_carrier_text);
+        mStackScroller.addView(mKeyguardIconOverflowContainer);
 
         mExpandedContents = mStackScroller;
 
         mNotificationPanelHeader = mStatusBarWindow.findViewById(R.id.header);
-
+        mKeyguardStatusView = mStatusBarWindow.findViewById(R.id.keyguard_status_view);
+        mKeyguardBottomArea = mStatusBarWindow.findViewById(R.id.keyguard_bottom_area);
+        mKeyguardIndicationTextView = (KeyguardIndicationTextView) mStatusBarWindow.findViewById(
+                R.id.keyguard_indication_text);
         mClearButton = mStatusBarWindow.findViewById(R.id.clear_all_button);
         mClearButton.setOnClickListener(mClearButtonListener);
         mClearButton.setAlpha(0f);
@@ -501,8 +634,7 @@
         mClearButton.setEnabled(false);
         mDateView = (DateView)mStatusBarWindow.findViewById(R.id.date);
 
-        mHasSettingsPanel = res.getBoolean(R.bool.config_hasSettingsPanel);
-        mHasFlipSettings = res.getBoolean(R.bool.config_hasFlipSettingsPanel);
+        mHasQuickSettings = res.getBoolean(R.bool.config_hasQuickSettings);
 
         mDateTimeView = mNotificationPanelHeader.findViewById(R.id.datetime);
         if (mDateTimeView != null) {
@@ -510,35 +642,8 @@
             mDateTimeView.setEnabled(true);
         }
 
-        mSettingsButton = (ImageView) mStatusBarWindow.findViewById(R.id.settings_button);
-        if (mSettingsButton != null) {
-            mSettingsButton.setOnClickListener(mSettingsButtonListener);
-            if (mHasSettingsPanel) {
-                if (mStatusBarView.hasFullWidthNotifications()) {
-                    // the settings panel is hiding behind this button
-                    mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
-                    mSettingsButton.setVisibility(View.VISIBLE);
-                } else {
-                    // there is a settings panel, but it's on the other side of the (large) screen
-                    final View buttonHolder = mStatusBarWindow.findViewById(
-                            R.id.settings_button_holder);
-                    if (buttonHolder != null) {
-                        buttonHolder.setVisibility(View.GONE);
-                    }
-                }
-            } else {
-                // no settings panel, go straight to settings
-                mSettingsButton.setVisibility(View.VISIBLE);
-                mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
-            }
-        }
-        if (mHasFlipSettings) {
-            mNotificationButton = (ImageView) mStatusBarWindow.findViewById(
-                    R.id.notification_button);
-            if (mNotificationButton != null) {
-                mNotificationButton.setOnClickListener(mNotificationButtonListener);
-            }
-        }
+        mHeaderFlipper = new FlipperButton(mStatusBarWindow.findViewById(R.id.header_flipper));
+        mKeyguardFlipper =new FlipperButton(mStatusBarWindow.findViewById(R.id.keyguard_flipper));
 
         if (!mNotificationPanelIsFullScreenWidth) {
             mNotificationPanel.setSystemUiVisibility(
@@ -614,37 +719,13 @@
         }
 
         // Quick Settings (where available, some restrictions apply)
-        if (mHasSettingsPanel) {
-            // first, figure out where quick settings should be inflated
-            final View settings_stub;
-            if (mHasFlipSettings) {
-                // a version of quick settings that flips around behind the notifications
-                settings_stub = mStatusBarWindow.findViewById(R.id.flip_settings_stub);
-                if (settings_stub != null) {
-                    mFlipSettingsView = ((ViewStub)settings_stub).inflate();
-                    mFlipSettingsView.setVisibility(View.GONE);
-                    mFlipSettingsView.setVerticalScrollBarEnabled(false);
-                }
-            } else {
-                // full quick settings panel
-                settings_stub = mStatusBarWindow.findViewById(R.id.quick_settings_stub);
-                if (settings_stub != null) {
-                    mSettingsPanel = (SettingsPanelView) ((ViewStub)settings_stub).inflate();
-                } else {
-                    mSettingsPanel = (SettingsPanelView) mStatusBarWindow.findViewById(R.id.settings_panel);
-                }
-
-                if (mSettingsPanel != null) {
-                    if (!ActivityManager.isHighEndGfx()) {
-                        mSettingsPanel.setBackground(new FastColorDrawable(context.getResources().getColor(
-                                R.color.notification_panel_solid_background)));
-                    }
-                }
-            }
-
-            // wherever you find it, Quick Settings needs a container to survive
+        mNotificationPadding = mContext.getResources()
+                .getDimensionPixelSize(R.dimen.notification_side_padding);
+        if (mHasQuickSettings) {
+            // Quick Settings needs a container to survive
             mSettingsContainer = (QuickSettingsContainerView)
                     mStatusBarWindow.findViewById(R.id.quick_settings_container);
+            mFlipSettingsView = mSettingsContainer;
             if (mSettingsContainer != null) {
                 mQS = new QuickSettings(mContext, mSettingsContainer);
                 if (!mNotificationPanelIsFullScreenWidth) {
@@ -652,9 +733,6 @@
                             View.STATUS_BAR_DISABLE_NOTIFICATION_ICONS
                             | View.STATUS_BAR_DISABLE_SYSTEM_INFO);
                 }
-                if (mSettingsPanel != null) {
-                    mSettingsPanel.setQuickSettings(mQS);
-                }
                 mQS.setService(this);
                 mQS.setBar(mStatusBarView);
                 mQS.setup(mNetworkController, mBluetoothController, mBatteryController,
@@ -682,6 +760,106 @@
         return mStatusBarView;
     }
 
+    public boolean onSettingsEvent(MotionEvent event) {
+        userActivity();
+        if (mSettingsClosing
+                && mFlipSettingsViewAnim != null && mFlipSettingsViewAnim.isRunning()) {
+            return true;
+        }
+        if (mSettingsTracker != null) {
+            mSettingsTracker.addMovement(event);
+        }
+        final int slop = ViewConfiguration.get(mContext).getScaledTouchSlop();
+        if (event.getAction() == MotionEvent.ACTION_DOWN) {
+            mSettingsTracker = VelocityTracker.obtain();
+            mSettingsDownY = event.getY();
+            mSettingsCancelled = false;
+            mSettingsStarted = false;
+            mSettingsClosing = mFlipSettingsView.getVisibility() == View.VISIBLE;
+            if (mSettingsClosing) {
+                mStackScroller.setVisibility(View.VISIBLE);
+            } else {
+                mFlipSettingsView.setTranslationY(-mNotificationPanel.getMeasuredHeight());
+            }
+            dispatchSettingsEvent(event);
+        } else if (mSettingsTracker != null && (event.getAction() == MotionEvent.ACTION_UP
+                || event.getAction() == MotionEvent.ACTION_CANCEL)) {
+            final float dy = event.getY() - mSettingsDownY;
+            final FlipperButton flipper = mOnKeyguard ? mKeyguardFlipper : mHeaderFlipper;
+            final boolean inButton = flipper.inHolderBounds(event);
+            final boolean qsTap = mSettingsClosing && Math.abs(dy) < slop;
+            if (!qsTap && !inButton) {
+                mSettingsTracker.computeCurrentVelocity(1000);
+                final float vy = mSettingsTracker.getYVelocity();
+                final boolean animate = true;
+                if (dy <= slop || vy <= 0) {
+                    flipToNotifications(animate);
+                } else {
+                    flipToSettings(animate);
+                }
+            }
+            mSettingsTracker.recycle();
+            mSettingsTracker = null;
+            dispatchSettingsEvent(event);
+        } else if (mSettingsTracker != null && event.getAction() == MotionEvent.ACTION_MOVE) {
+            final float dy = event.getY() - mSettingsDownY;
+            if (mSettingsClosing) {
+                positionSettings(dy);
+                final boolean qsTap = Math.abs(dy) < slop;
+                if (!mSettingsCancelled && !qsTap) {
+                    MotionEvent cancelEvent = MotionEvent.obtainNoHistory(event);
+                    cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
+                    dispatchSettingsEvent(cancelEvent);
+                    mSettingsCancelled = true;
+                }
+            } else {
+                if (!mSettingsStarted && dy > slop) {
+                    mSettingsStarted = true;
+                    mFlipSettingsView.setVisibility(View.VISIBLE);
+                    mStackScroller.setVisibility(View.VISIBLE);
+                }
+                if (mSettingsStarted) {
+                    positionSettings(dy);
+                }
+                dispatchSettingsEvent(event);
+            }
+        }
+        return true;
+    }
+
+    private void dispatchSettingsEvent(MotionEvent event) {
+        final View target = mSettingsClosing ? mFlipSettingsView : mNotificationPanelHeader;
+        final int[] targetLoc = new int[2];
+        target.getLocationInWindow(targetLoc);
+        final int[] panelLoc = new int[2];
+        mNotificationPanel.getLocationInWindow(panelLoc);
+        final int dx = targetLoc[0] - panelLoc[0];
+        final int dy = targetLoc[1] - panelLoc[1];
+        event.offsetLocation(-dx, -dy);
+        target.dispatchTouchEvent(event);
+    }
+
+    private void positionSettings(float dy) {
+        if (mSettingsClosing) {
+            final int ph = mNotificationPanel.getMeasuredHeight();
+            dy = Math.min(Math.max(-ph, dy), 0);
+            mFlipSettingsView.setTranslationY(dy);
+            mStackScroller.setTranslationY(ph + dy);
+        } else {
+            final int h = mFlipSettingsView.getBottom();
+            dy = Math.min(Math.max(0, dy), h);
+            mFlipSettingsView.setTranslationY(-h + dy);
+            mStackScroller.setTranslationY(dy);
+        }
+    }
+
+    private void startKeyguard() {
+        KeyguardViewMediator keyguardViewMediator = getComponent(KeyguardViewMediator.class);
+        mStatusBarKeyguardViewManager = keyguardViewMediator.registerStatusBar(this,
+                mStatusBarWindow, mStatusBarWindowManager);
+        mKeyguardViewMediatorCallback = keyguardViewMediator.getViewMediatorCallback();
+    }
+
     @Override
     protected void onShowSearchPanel() {
         if (mNavigationBarView != null) {
@@ -759,10 +937,6 @@
         }
     }
 
-    protected int getStatusBarGravity() {
-        return Gravity.TOP | Gravity.FILL_HORIZONTAL;
-    }
-
     public int getStatusBarHeight() {
         if (mNaturalBarHeight < 0) {
             final Resources res = mContext.getResources();
@@ -931,49 +1105,54 @@
         mStatusIcons.removeViewAt(viewIndex);
     }
 
+    public UserHandle getCurrentUserHandle() {
+        return new UserHandle(mCurrentUserId);
+    }
+
     public void addNotification(IBinder key, StatusBarNotification notification) {
         if (DEBUG) Log.d(TAG, "addNotification score=" + notification.getScore());
         Entry shadeEntry = createNotificationViews(key, notification);
         if (shadeEntry == null) {
             return;
         }
-        if (!shouldIntercept(notification.getNotification())) {
-            if (mUseHeadsUp && shouldInterrupt(notification)) {
-                if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
-                Entry interruptionCandidate = new Entry(key, notification, null);
-                ViewGroup holder = mHeadsUpNotificationView.getHolder();
-                if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
-                    mInterruptingNotificationTime = System.currentTimeMillis();
-                    mInterruptingNotificationEntry = interruptionCandidate;
-                    shadeEntry.setInterruption();
+        if (mZenMode != Global.ZEN_MODE_OFF && mIntercepted.tryIntercept(key, notification)) {
+            return;
+        }
+        if (mUseHeadsUp && shouldInterrupt(notification)) {
+            if (DEBUG) Log.d(TAG, "launching notification in heads up mode");
+            Entry interruptionCandidate = new Entry(key, notification, null);
+            ViewGroup holder = mHeadsUpNotificationView.getHolder();
+            if (inflateViewsForHeadsUp(interruptionCandidate, holder)) {
+                mInterruptingNotificationTime = System.currentTimeMillis();
+                mInterruptingNotificationEntry = interruptionCandidate;
+                shadeEntry.setInterruption();
 
-                    // 1. Populate mHeadsUpNotificationView
-                    mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
+                // 1. Populate mHeadsUpNotificationView
+                mHeadsUpNotificationView.setNotification(mInterruptingNotificationEntry);
 
-                    // 2. Animate mHeadsUpNotificationView in
-                    mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
+                // 2. Animate mHeadsUpNotificationView in
+                mHandler.sendEmptyMessage(MSG_SHOW_HEADS_UP);
 
-                    // 3. Set alarm to age the notification off
-                    resetHeadsUpDecayTimer();
-                }
-            } else if (notification.getNotification().fullScreenIntent != null) {
-                // Stop screensaver if the notification has a full-screen intent.
-                // (like an incoming phone call)
-                awakenDreams();
+                // 3. Set alarm to age the notification off
+                resetHeadsUpDecayTimer();
+            }
+        } else if (notification.getNotification().fullScreenIntent != null) {
+            // Stop screensaver if the notification has a full-screen intent.
+            // (like an incoming phone call)
+            awakenDreams();
 
-                // not immersive & a full-screen alert should be shown
-                if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
-                try {
-                    notification.getNotification().fullScreenIntent.send();
-                } catch (PendingIntent.CanceledException e) {
-                }
-            } else {
-                // usual case: status bar visible & not immersive
+            // not immersive & a full-screen alert should be shown
+            if (DEBUG) Log.d(TAG, "Notification has fullScreenIntent; sending fullScreenIntent");
+            try {
+                notification.getNotification().fullScreenIntent.send();
+            } catch (PendingIntent.CanceledException e) {
+            }
+        } else {
+            // usual case: status bar visible & not immersive
 
-                // show the ticker if there isn't already a heads up
-                if (mInterruptingNotificationEntry == null) {
-                    tick(null, notification, true);
-                }
+            // show the ticker if there isn't already a heads up
+            if (mInterruptingNotificationEntry == null) {
+                tick(null, notification, true);
             }
         }
         addNotificationViews(shadeEntry);
@@ -991,6 +1170,12 @@
         }
     }
 
+    @Override
+    public void updateNotification(IBinder key, StatusBarNotification notification) {
+        super.updateNotification(key, notification);
+        mIntercepted.update(key, notification);
+    }
+
     public void removeNotification(IBinder key) {
         StatusBarNotification old = removeNotificationViews(key);
         if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
@@ -1008,11 +1193,11 @@
             }
 
             if (CLOSE_PANEL_WHEN_EMPTIED && mNotificationData.size() == 0
-                    && !mNotificationPanel.isTracking()) {
+                    && !mNotificationPanel.isTracking() && !mOnKeyguard) {
                 animateCollapsePanels();
             }
         }
-
+        mIntercepted.remove(key);
         setAreThereNotifications();
     }
 
@@ -1028,17 +1213,8 @@
             ((ImageView)mClearButton).setImageResource(R.drawable.ic_notify_clear);
         }
 
-        if (mSettingsButton != null) {
-            // Force asset reloading
-            mSettingsButton.setImageDrawable(null);
-            mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
-        }
-
-        if (mNotificationButton != null) {
-            // Force asset reloading
-            mNotificationButton.setImageDrawable(null);
-            mNotificationButton.setImageResource(R.drawable.ic_notifications);
-        }
+        mHeaderFlipper.refreshLayout();
+        mKeyguardFlipper.refreshLayout();
 
         refreshAllStatusBarIcons();
     }
@@ -1077,7 +1253,7 @@
         ArrayList<View> toRemove = new ArrayList<View>();
         for (int i=0; i< mStackScroller.getChildCount(); i++) {
             View child = mStackScroller.getChildAt(i);
-            if (!toShow.contains(child)) {
+            if (!toShow.contains(child) && child != mKeyguardIconOverflowContainer) {
                 toRemove.add(child);
             }
         }
@@ -1093,9 +1269,8 @@
             }
         }
 
-        if (mSettingsButton != null) {
-            mSettingsButton.setEnabled(isDeviceProvisioned());
-        }
+        mHeaderFlipper.provisionCheck(provisioned);
+        mKeyguardFlipper.provisionCheck(provisioned);
     }
 
     @Override
@@ -1129,7 +1304,7 @@
                 // in "public" mode (atop a secure keyguard), secret notifs are totally hidden
                 continue;
             }
-            if (shouldIntercept(ent.notification.getNotification())) {
+            if (mIntercepted.isSyntheticEntry(ent)) {
                 continue;
             }
             toShow.add(ent.icon);
@@ -1171,7 +1346,8 @@
             !(emergencyCallsShownElsewhere && mNetworkController.isEmergencyOnly())
             && mStackScroller.getHeight() < (mNotificationPanel.getHeight()
                     - mCarrierLabelHeight - mNotificationHeaderHeight)
-            && mStackScroller.getVisibility() == View.VISIBLE;
+            && mStackScroller.getVisibility() == View.VISIBLE
+            && !mOnKeyguard;
 
         if (force || mCarrierLabelVisible != makeVisible) {
             mCarrierLabelVisible = makeVisible;
@@ -1211,8 +1387,7 @@
                     + " any=" + any + " clearable=" + clearable);
         }
 
-        if (mHasFlipSettings
-                && mFlipSettingsView != null
+        if (mFlipSettingsView != null
                 && mFlipSettingsView.getVisibility() == View.VISIBLE
                 && mStackScroller.getVisibility() != View.VISIBLE) {
             // the flip settings panel is unequivocally showing; we should not be shown
@@ -1296,8 +1471,6 @@
         flagdbg.append(((diff  & StatusBarManager.DISABLE_NOTIFICATION_ICONS) != 0) ? "* " : " ");
         flagdbg.append(((state & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "ALERTS" : "alerts");
         flagdbg.append(((diff  & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0) ? "* " : " ");
-        flagdbg.append(((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "PRIVATE" : "private");
-        flagdbg.append(((diff  & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) ? "* " : " ");
         flagdbg.append(((state & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "SYSTEM_INFO" : "system_info");
         flagdbg.append(((diff  & StatusBarManager.DISABLE_SYSTEM_INFO) != 0) ? "* " : " ");
         flagdbg.append(((state & StatusBarManager.DISABLE_BACK) != 0) ? "BACK" : "back");
@@ -1382,15 +1555,6 @@
                     .setDuration(175)
                     .start();
             }
-        } else if ((diff & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) {
-            if ((state & StatusBarManager.DISABLE_PRIVATE_NOTIFICATIONS) != 0) {
-                // we are outside a secure keyguard, so we need to switch to "public" mode
-                setLockscreenPublicMode(true);
-            } else {
-                // user has authenticated the device; full notifications may be shown
-                setLockscreenPublicMode(false);
-            }
-            updateNotificationIcons();
         }
     }
 
@@ -1461,9 +1625,9 @@
         return (mDisabled & StatusBarManager.DISABLE_EXPAND) == 0;
     }
 
-    void makeExpandedVisible() {
+    void makeExpandedVisible(boolean force) {
         if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
-        if (mExpandedVisible || !panelsEnabled()) {
+        if (!force && (mExpandedVisible || !panelsEnabled())) {
             return;
         }
 
@@ -1477,26 +1641,13 @@
 
         // Expand the window to encompass the full screen in anticipation of the drag.
         // This is only possible to do atomically because the status bar is at the top of the screen!
-        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+        mStatusBarWindowManager.setStatusBarExpanded(true);
 
         visibilityChanged(true);
 
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
     }
 
-    private void releaseFocus() {
-        if (mStatusBarWindow == null) return;
-        WindowManager.LayoutParams lp =
-                (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
-    }
-
     public void animateCollapsePanels() {
         animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE);
     }
@@ -1508,9 +1659,6 @@
                     + " flags=" + flags);
         }
 
-        // release focus immediately to kick off focus change transition
-        releaseFocus();
-
         if ((flags & CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL) == 0) {
             mHandler.removeMessages(MSG_CLOSE_RECENTS_PANEL);
             mHandler.sendEmptyMessage(MSG_CLOSE_RECENTS_PANEL);
@@ -1522,8 +1670,15 @@
         }
 
         if (mStatusBarWindow != null) {
+
+            // release focus immediately to kick off focus change transition
+            mStatusBarWindowManager.setStatusBarFocusable(false);
+
             mStatusBarWindow.cancelExpandHelper();
             mStatusBarView.collapseAllPanels(true);
+            if (isFlippedToSettings()) {
+                flipToNotifications(true /*animate*/);
+            }
         }
     }
 
@@ -1571,8 +1726,7 @@
     final int FLIP_DURATION_IN = 225;
     final int FLIP_DURATION = (FLIP_DURATION_IN + FLIP_DURATION_OUT);
 
-    Animator mScrollViewAnim, mFlipSettingsViewAnim, mNotificationButtonAnim,
-        mSettingsButtonAnim, mClearButtonAnim;
+    Animator mScrollViewAnim, mFlipSettingsViewAnim, mClearButtonAnim;
 
     @Override
     public void animateExpandNotificationsPanel() {
@@ -1582,43 +1736,50 @@
         }
 
         mNotificationPanel.expand();
-        if (mHasFlipSettings && mStackScroller.getVisibility() != View.VISIBLE) {
-            flipToNotifications();
+        if (mStackScroller.getVisibility() != View.VISIBLE) {
+            flipToNotifications(true /*animate*/);
         }
 
         if (false) postStartTracing();
     }
 
-    public void flipToNotifications() {
-        if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
-        if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
-        if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+    private static void cancelAnim(Animator anim) {
+        if (anim != null) {
+            anim.cancel();
+        }
+    }
 
+    public void flipToNotifications(boolean animate) {
+        cancelAnim(mFlipSettingsViewAnim);
+        cancelAnim(mScrollViewAnim);
+        cancelAnim(mClearButtonAnim);
+        mHeaderFlipper.cancel();
+        mKeyguardFlipper.cancel();
         mStackScroller.setVisibility(View.VISIBLE);
-        mScrollViewAnim = start(
-            startDelay(FLIP_DURATION_OUT,
-                interpolator(mDecelerateInterpolator,
-                    ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 0f, 1f)
-                        .setDuration(FLIP_DURATION_IN)
-                    )));
-        mFlipSettingsViewAnim = start(
-            setVisibilityWhenDone(
-                interpolator(mAccelerateInterpolator,
-                        ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 1f, 0f)
-                        )
-                    .setDuration(FLIP_DURATION_OUT),
-                mFlipSettingsView, View.INVISIBLE));
-        mNotificationButtonAnim = start(
-            setVisibilityWhenDone(
-                ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
-                    .setDuration(FLIP_DURATION),
-                mNotificationButton, View.INVISIBLE));
-        mSettingsButton.setVisibility(View.VISIBLE);
-        mSettingsButtonAnim = start(
-            ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
-                .setDuration(FLIP_DURATION));
+        final int h = mNotificationPanel.getMeasuredHeight();
+        if (animate) {
+            final float settingsY =
+                    mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : 0;
+            final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : h;
+            mScrollViewAnim = start(
+                    interpolator(mDecelerateInterpolator,
+                        ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, 0)
+                            .setDuration(FLIP_DURATION)
+                        ));
+            mFlipSettingsViewAnim = start(
+                setVisibilityWhenDone(
+                    interpolator(mDecelerateInterpolator,
+                            ObjectAnimator.ofFloat(
+                                    mFlipSettingsView, View.TRANSLATION_Y, settingsY, -h))
+                        .setDuration(FLIP_DURATION),
+                    mFlipSettingsView, View.INVISIBLE));
+        } else {
+            mStackScroller.setTranslationY(0);
+            mFlipSettingsView.setTranslationY(-h);
+            mFlipSettingsView.setVisibility(View.INVISIBLE);
+        }
+        mHeaderFlipper.flipToNotifications(animate);
+        mKeyguardFlipper.flipToNotifications(animate);
         mClearButton.setVisibility(View.VISIBLE);
         mClearButton.setAlpha(0f);
         setAreThereNotifications(); // this will show/hide the button as necessary
@@ -1626,7 +1787,7 @@
             public void run() {
                 updateCarrierLabelVisibility(false);
             }
-        }, FLIP_DURATION - 150);
+        }, animate ? FLIP_DURATION - 150 : 0);
         if (mOnFlipRunnable != null) {
             mOnFlipRunnable.run();
         }
@@ -1642,35 +1803,15 @@
         // Settings are not available in setup
         if (!mUserSetup) return;
 
-        if (mHasFlipSettings) {
-            mNotificationPanel.expand();
-            if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
-                flipToSettings();
-            }
-        } else if (mSettingsPanel != null) {
-            mSettingsPanel.expand();
+        mNotificationPanel.expand();
+        if (mFlipSettingsView.getVisibility() != View.VISIBLE
+                || mFlipSettingsView.getTranslationY() < 0) {
+            flipToSettings(true /*animate*/);
         }
 
         if (false) postStartTracing();
     }
 
-    public void switchToSettings() {
-        // Settings are not available in setup
-        if (!mUserSetup) return;
-
-        mFlipSettingsView.setScaleX(1f);
-        mFlipSettingsView.setVisibility(View.VISIBLE);
-        mSettingsButton.setVisibility(View.GONE);
-        mStackScroller.setVisibility(View.GONE);
-        mStackScroller.setScaleX(0f);
-        mNotificationButton.setVisibility(View.VISIBLE);
-        mNotificationButton.setAlpha(1f);
-        mClearButton.setVisibility(View.GONE);
-        if (mOnFlipRunnable != null) {
-            mOnFlipRunnable.run();
-        }
-    }
-
     public boolean isFlippedToSettings() {
         if (mFlipSettingsView != null) {
             return mFlipSettingsView.getVisibility() == View.VISIBLE;
@@ -1678,65 +1819,63 @@
         return false;
     }
 
-    public void flipToSettings() {
+    public void flipToSettings(boolean animate) {
         // Settings are not available in setup
         if (!mUserSetup) return;
 
-        if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
-        if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-        if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-        if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
-        if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+        cancelAnim(mFlipSettingsViewAnim);
+        cancelAnim(mScrollViewAnim);
+        mHeaderFlipper.cancel();
+        mKeyguardFlipper.cancel();
+        cancelAnim(mClearButtonAnim);
 
         mFlipSettingsView.setVisibility(View.VISIBLE);
-        mFlipSettingsView.setScaleX(0f);
-        mFlipSettingsViewAnim = start(
-            startDelay(FLIP_DURATION_OUT,
-                interpolator(mDecelerateInterpolator,
-                    ObjectAnimator.ofFloat(mFlipSettingsView, View.SCALE_X, 0f, 1f)
-                        .setDuration(FLIP_DURATION_IN)
-                    )));
-        mScrollViewAnim = start(
-            setVisibilityWhenDone(
-                interpolator(mAccelerateInterpolator,
-                        ObjectAnimator.ofFloat(mStackScroller, View.SCALE_X, 1f, 0f)
-                        )
-                    .setDuration(FLIP_DURATION_OUT),
-                    mStackScroller, View.INVISIBLE));
-        mSettingsButtonAnim = start(
-            setVisibilityWhenDone(
-                ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+        final int h = mNotificationPanel.getMeasuredHeight();
+        if (animate) {
+            final float settingsY
+                    = mSettingsTracker != null ? mFlipSettingsView.getTranslationY() : -h;
+            final float scrollerY = mSettingsTracker != null ? mStackScroller.getTranslationY() : 0;
+            mFlipSettingsViewAnim = start(
+                    startDelay(0,
+                        interpolator(mDecelerateInterpolator,
+                            ObjectAnimator.ofFloat(mFlipSettingsView, View.TRANSLATION_Y,
+                                    settingsY, 0f)
+                                .setDuration(FLIP_DURATION)
+                            )));
+            mScrollViewAnim = start(
+                setVisibilityWhenDone(
+                    interpolator(mDecelerateInterpolator,
+                            ObjectAnimator.ofFloat(mStackScroller, View.TRANSLATION_Y, scrollerY, h)
+                            )
+                        .setDuration(FLIP_DURATION),
+                        mStackScroller, View.INVISIBLE));
+        } else {
+            mFlipSettingsView.setTranslationY(0);
+            mStackScroller.setTranslationY(h);
+            mStackScroller.setVisibility(View.INVISIBLE);
+        }
+        mHeaderFlipper.flipToSettings(animate);
+        mKeyguardFlipper.flipToSettings(animate);
+        if (animate) {
+            mClearButtonAnim = start(
+                setVisibilityWhenDone(
+                    ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
                     .setDuration(FLIP_DURATION),
-                    mStackScroller, View.INVISIBLE));
-        mNotificationButton.setVisibility(View.VISIBLE);
-        mNotificationButtonAnim = start(
-            ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
-                .setDuration(FLIP_DURATION));
-        mClearButtonAnim = start(
-            setVisibilityWhenDone(
-                ObjectAnimator.ofFloat(mClearButton, View.ALPHA, 0f)
-                .setDuration(FLIP_DURATION),
-                mClearButton, View.INVISIBLE));
+                    mClearButton, View.INVISIBLE));
+        } else {
+            mClearButton.setAlpha(0);
+            mClearButton.setVisibility(View.INVISIBLE);
+        }
         mNotificationPanel.postDelayed(new Runnable() {
             public void run() {
                 updateCarrierLabelVisibility(false);
             }
-        }, FLIP_DURATION - 150);
+        }, animate ? FLIP_DURATION - 150 : 0);
         if (mOnFlipRunnable != null) {
             mOnFlipRunnable.run();
         }
     }
 
-    public void flipPanels() {
-        if (mHasFlipSettings) {
-            if (mFlipSettingsView.getVisibility() != View.VISIBLE) {
-                flipToSettings();
-            } else {
-                flipToNotifications();
-            }
-        }
-    }
-
     public void animateCollapseQuickSettings() {
         mStatusBarView.collapseAllPanels(true);
     }
@@ -1756,23 +1895,19 @@
         // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
         mStatusBarView.collapseAllPanels(/*animate=*/ false);
 
-        if (mHasFlipSettings) {
-            // reset things to their proper state
-            if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
-            if (mScrollViewAnim != null) mScrollViewAnim.cancel();
-            if (mSettingsButtonAnim != null) mSettingsButtonAnim.cancel();
-            if (mNotificationButtonAnim != null) mNotificationButtonAnim.cancel();
-            if (mClearButtonAnim != null) mClearButtonAnim.cancel();
+        // reset things to their proper state
+        if (mFlipSettingsViewAnim != null) mFlipSettingsViewAnim.cancel();
+        if (mScrollViewAnim != null) mScrollViewAnim.cancel();
+        if (mClearButtonAnim != null) mClearButtonAnim.cancel();
 
-            mStackScroller.setScaleX(1f);
-            mStackScroller.setVisibility(View.VISIBLE);
-            mSettingsButton.setAlpha(1f);
-            mSettingsButton.setVisibility(View.VISIBLE);
-            mNotificationPanel.setVisibility(View.GONE);
-            mFlipSettingsView.setVisibility(View.GONE);
-            mNotificationButton.setVisibility(View.GONE);
-            setAreThereNotifications(); // show the clear button
-        }
+        mStackScroller.setVisibility(View.VISIBLE);
+        mNotificationPanel.setVisibility(View.GONE);
+        mFlipSettingsView.setVisibility(View.GONE);
+
+        setAreThereNotifications(); // show the clear button
+
+        mHeaderFlipper.reset();
+        mKeyguardFlipper.reset();
 
         mExpandedVisible = false;
         if (mNavigationBarView != null)
@@ -1780,11 +1915,7 @@
         visibilityChanged(false);
 
         // Shrink the window to the size of the status bar only
-        WindowManager.LayoutParams lp = (WindowManager.LayoutParams) mStatusBarWindow.getLayoutParams();
-        lp.height = getStatusBarHeight();
-        lp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-        lp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
-        mWindowManager.updateViewLayout(mStatusBarWindow, lp);
+        mStatusBarWindowManager.setStatusBarExpanded(false);
 
         if ((mDisabled & StatusBarManager.DISABLE_NOTIFICATION_ICONS) == 0) {
             setNotificationIconVisibility(true, com.android.internal.R.anim.fade_in);
@@ -1799,6 +1930,8 @@
         }
 
         setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+
+        showBouncer();
     }
 
     public boolean interceptTouchEvent(MotionEvent event) {
@@ -1964,7 +2097,8 @@
     private void checkBarModes() {
         if (mDemoMode) return;
         int sbMode = mStatusBarMode;
-        if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0) {
+        if (panelsEnabled() && (mInteractingWindows & StatusBarManager.WINDOW_STATUS_BAR) != 0
+                && !mOnKeyguard) {
             // if panels are expandable, force the status bar opaque on any interaction
             sbMode = MODE_OPAQUE;
         }
@@ -2219,12 +2353,6 @@
             pw.print  ("      ");
             mNotificationPanel.dump(fd, pw, args);
         }
-        if (mSettingsPanel != null) {
-            pw.println("    mSettingsPanel=" +
-                mSettingsPanel + " params=" + mSettingsPanel.getLayoutParams().debug(""));
-            pw.print  ("      ");
-            mSettingsPanel.dump(fd, pw, args);
-        }
 
         if (DUMPTRUCK) {
             synchronized (mNotificationData) {
@@ -2287,30 +2415,9 @@
     }
 
     private void addStatusBarWindow() {
-        // Put up the view
-        final int height = getStatusBarHeight();
-
-        // Now that the status bar window encompasses the sliding panel and its
-        // translucent backdrop, the entire thing is made TRANSLUCENT and is
-        // hardware-accelerated.
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                ViewGroup.LayoutParams.MATCH_PARENT,
-                height,
-                WindowManager.LayoutParams.TYPE_STATUS_BAR,
-                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
-                    | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
-                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH,
-                PixelFormat.TRANSLUCENT);
-
-        lp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
-
-        lp.gravity = getStatusBarGravity();
-        lp.setTitle("StatusBar");
-        lp.packageName = mContext.getPackageName();
-
         makeStatusBarView();
-        mWindowManager.addView(mStatusBarWindow, lp);
+        mStatusBarWindowManager = new StatusBarWindowManager(mContext);
+        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
     }
 
     void setNotificationIconVisibility(boolean visible, int anim) {
@@ -2348,13 +2455,6 @@
         lp.setMarginStart(mNotificationPanelMarginPx);
         mNotificationPanel.setLayoutParams(lp);
 
-        if (mSettingsPanel != null) {
-            lp = (FrameLayout.LayoutParams) mSettingsPanel.getLayoutParams();
-            lp.gravity = mSettingsPanelGravity;
-            lp.setMarginEnd(mNotificationPanelMarginPx);
-            mSettingsPanel.setLayoutParams(lp);
-        }
-
         if (ENABLE_HEADS_UP && mHeadsUpNotificationView != null) {
             mHeadsUpNotificationView.setMargin(mNotificationPanelMarginPx);
             mStackScroller.getLocationOnScreen(mStackScrollerPosition);
@@ -2410,7 +2510,7 @@
 
     private View.OnClickListener mSettingsButtonListener = new View.OnClickListener() {
         public void onClick(View v) {
-            if (mHasSettingsPanel) {
+            if (mHasQuickSettings) {
                 animateExpandSettingsPanel();
             } else {
                 startActivityDismissingKeyguard(
@@ -2448,8 +2548,6 @@
             }
             else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
                 mScreenOn = false;
-                // no waiting!
-                makeExpandedInvisible();
                 notifyNavigationBarScreenOn(false);
                 notifyHeadsUpScreenOn(false);
                 finishBarAnimations();
@@ -2610,11 +2708,6 @@
         if (mNotificationPanelGravity <= 0) {
             mNotificationPanelGravity = Gravity.START | Gravity.TOP;
         }
-        mSettingsPanelGravity = res.getInteger(R.integer.settings_panel_layout_gravity);
-        Log.d(TAG, "mSettingsPanelGravity = " + mSettingsPanelGravity);
-        if (mSettingsPanelGravity <= 0) {
-            mSettingsPanelGravity = Gravity.END | Gravity.TOP;
-        }
 
         mCarrierLabelHeight = res.getDimensionPixelSize(R.dimen.carrier_label_height);
         mNotificationHeaderHeight = res.getDimensionPixelSize(R.dimen.notification_panel_header_height);
@@ -2625,11 +2718,49 @@
         }
 
         mHeadsUpNotificationDecay = res.getInteger(R.integer.heads_up_notification_decay);
-        mRowHeight =  res.getDimensionPixelSize(R.dimen.notification_row_min_height);
+        mRowMinHeight =  res.getDimensionPixelSize(R.dimen.notification_min_height);
+        mRowMaxHeight =  res.getDimensionPixelSize(R.dimen.notification_max_height);
+
+        mKeyguardMaxNotificationCount = res.getInteger(R.integer.keyguard_max_notification_count);
 
         if (false) Log.v(TAG, "updateResources");
     }
 
+    // Visibility reporting
+
+    @Override
+    protected void visibilityChanged(boolean visible) {
+        if (visible) {
+            mStackScroller.setChildLocationsChangedListener(mNotificationLocationsChangedListener);
+        } else {
+            // Report all notifications as invisible and turn down the
+            // reporter.
+            if (!mCurrentlyVisibleNotifications.isEmpty()) {
+                logNotificationVisibilityChanges(
+                        Collections.<String>emptyList(), mCurrentlyVisibleNotifications);
+                mCurrentlyVisibleNotifications.clear();
+            }
+            mHandler.removeCallbacks(mVisibilityReporter);
+            mStackScroller.setChildLocationsChangedListener(null);
+        }
+        super.visibilityChanged(visible);
+    }
+
+    private void logNotificationVisibilityChanges(
+            Collection<String> newlyVisible, Collection<String> noLongerVisible) {
+        if (newlyVisible.isEmpty() && noLongerVisible.isEmpty()) {
+            return;
+        }
+
+        String[] newlyVisibleAr = newlyVisible.toArray(new String[newlyVisible.size()]);
+        String[] noLongerVisibleAr = noLongerVisible.toArray(new String[noLongerVisible.size()]);
+        try {
+            mBarService.onNotificationVisibilityChanged(newlyVisibleAr, noLongerVisibleAr);
+        } catch (RemoteException e) {
+            // Ignore.
+        }
+    }
+
     //
     // tracing
     //
@@ -2798,4 +2929,271 @@
             ((DemoMode)v).dispatchDemoCommand(command, args);
         }
     }
+
+    public boolean isOnKeyguard() {
+        return mOnKeyguard;
+    }
+
+    public void showKeyguard() {
+        mOnKeyguard = true;
+        updateKeyguardState();
+        instantExpandNotificationsPanel();
+    }
+
+    public void hideKeyguard() {
+        mOnKeyguard = false;
+        updateKeyguardState();
+        instantCollapseNotificationPanel();
+    }
+
+    private void updatePublicMode() {
+        setLockscreenPublicMode(mOnKeyguard && mStatusBarKeyguardViewManager.isSecure());
+    }
+
+    private void updateKeyguardState() {
+        if (mOnKeyguard) {
+            if (isFlippedToSettings()) {
+                flipToNotifications(false /*animate*/);
+            }
+            mKeyguardStatusView.setVisibility(View.VISIBLE);
+            mKeyguardBottomArea.setVisibility(View.VISIBLE);
+            mKeyguardIndicationTextView.setVisibility(View.VISIBLE);
+            mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+            mKeyguardCarrierLabel.setVisibility(View.VISIBLE);
+            mNotificationPanelHeader.setVisibility(View.GONE);
+
+            mKeyguardFlipper.setVisibility(View.VISIBLE);
+            mSettingsContainer.setKeyguardShowing(true);
+        } else {
+            mKeyguardStatusView.setVisibility(View.GONE);
+            mKeyguardBottomArea.setVisibility(View.GONE);
+            mKeyguardIndicationTextView.setVisibility(View.GONE);
+            mKeyguardCarrierLabel.setVisibility(View.GONE);
+            mNotificationPanelHeader.setVisibility(View.VISIBLE);
+
+            mKeyguardFlipper.setVisibility(View.GONE);
+            mSettingsContainer.setKeyguardShowing(false);
+        }
+
+        updatePublicMode();
+        updateRowStates();
+        checkBarModes();
+        updateNotificationIcons();
+        updateCarrierLabelVisibility(false);
+    }
+
+    public void userActivity() {
+        if (mOnKeyguard) {
+            mKeyguardViewMediatorCallback.userActivity();
+        }
+    }
+
+    public boolean onMenuPressed() {
+        return mOnKeyguard && mStatusBarKeyguardViewManager.onMenuPressed();
+    }
+
+    public boolean onBackPressed() {
+        if (mOnKeyguard) {
+            return mStatusBarKeyguardViewManager.onBackPressed();
+        } else {
+            animateCollapsePanels();
+            return true;
+        }
+    }
+
+    private void showBouncer() {
+        if (mOnKeyguard) {
+            mStatusBarKeyguardViewManager.dismiss();
+        }
+    }
+
+    private void instantExpandNotificationsPanel() {
+
+        // Make our window larger and the panel visible.
+        makeExpandedVisible(true);
+        mNotificationPanel.setVisibility(View.VISIBLE);
+
+        // Wait for window manager to pickup the change, so we know the maximum height of the panel
+        // then.
+        mNotificationPanel.getViewTreeObserver().addOnGlobalLayoutListener(
+                new ViewTreeObserver.OnGlobalLayoutListener() {
+            @Override
+            public void onGlobalLayout() {
+                if (mStatusBarWindow.getHeight() != getStatusBarHeight()) {
+                    mNotificationPanel.getViewTreeObserver().removeOnGlobalLayoutListener(this);
+                    mNotificationPanel.setExpandedFraction(1);
+                }
+            }
+        });
+    }
+
+    private void instantCollapseNotificationPanel() {
+        mNotificationPanel.setExpandedFraction(0);
+    }
+
+    @Override
+    public void onActivated(View view) {
+        userActivity();
+        mKeyguardIndicationTextView.switchIndication(R.string.notification_tap_again);
+        super.onActivated(view);
+    }
+
+    @Override
+    public void onReset(View view) {
+        super.onReset(view);
+        mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+    }
+
+    public void onTrackingStarted() {
+        if (mOnKeyguard) {
+            mKeyguardIndicationTextView.switchIndication(R.string.keyguard_unlock);
+        }
+    }
+
+    public void onTrackingStopped() {
+        if (mOnKeyguard) {
+            mKeyguardIndicationTextView.switchIndication(mKeyguardHotwordPhrase);
+        }
+    }
+
+    @Override
+    protected int getMaxKeyguardNotifications() {
+        return mKeyguardMaxNotificationCount;
+    }
+
+    public NavigationBarView getNavigationBarView() {
+        return mNavigationBarView;
+    }
+
+    /**
+     * @return a ViewGroup that spans the entire panel which contains the quick settings
+     */
+    public ViewGroup getQuickSettingsOverlayParent() {
+        if (mHasQuickSettings) {
+            return mNotificationPanel;
+        } else {
+            return null;
+        }
+    }
+
+    public static boolean inBounds(View view, MotionEvent event, boolean orAbove) {
+        final int[] location = new int[2];
+        view.getLocationInWindow(location);
+        final int rx = (int) event.getRawX();
+        final int ry = (int) event.getRawY();
+        return rx >= location[0] && rx <= location[0] + view.getMeasuredWidth()
+                && (orAbove || ry >= location[1]) && ry <= location[1] + view.getMeasuredHeight();
+    }
+
+    private final class FlipperButton {
+        private final View mHolder;
+
+        private ImageView mSettingsButton, mNotificationButton;
+        private Animator mSettingsButtonAnim, mNotificationButtonAnim;
+
+        public FlipperButton(View holder) {
+            mHolder = holder;
+            mSettingsButton = (ImageView) holder.findViewById(R.id.settings_button);
+            if (mSettingsButton != null) {
+                mSettingsButton.setOnClickListener(mSettingsButtonListener);
+                if (mHasQuickSettings) {
+                    // the settings panel is hiding behind this button
+                    mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+                    mSettingsButton.setVisibility(View.VISIBLE);
+                } else {
+                    // no settings panel, go straight to settings
+                    mSettingsButton.setVisibility(View.VISIBLE);
+                    mSettingsButton.setImageResource(R.drawable.ic_notify_settings);
+                }
+            }
+            mNotificationButton = (ImageView) holder.findViewById(R.id.notification_button);
+            if (mNotificationButton != null) {
+                mNotificationButton.setOnClickListener(mNotificationButtonListener);
+            }
+        }
+
+        public boolean inHolderBounds(MotionEvent event) {
+            return inBounds(mHolder, event, false);
+        }
+
+        public void provisionCheck(boolean provisioned) {
+            if (mSettingsButton != null) {
+                mSettingsButton.setEnabled(provisioned);
+            }
+        }
+
+        public void userSetup(boolean userSetup) {
+            if (mSettingsButton != null) {
+                mSettingsButton.setVisibility(userSetup ? View.VISIBLE : View.INVISIBLE);
+            }
+        }
+
+        public void reset() {
+            cancel();
+            mSettingsButton.setVisibility(View.VISIBLE);
+            mNotificationButton.setVisibility(View.GONE);
+        }
+
+        public void refreshLayout() {
+            if (mSettingsButton != null) {
+                // Force asset reloading
+                mSettingsButton.setImageDrawable(null);
+                mSettingsButton.setImageResource(R.drawable.ic_notify_quicksettings);
+            }
+
+            if (mNotificationButton != null) {
+                // Force asset reloading
+                mNotificationButton.setImageDrawable(null);
+                mNotificationButton.setImageResource(R.drawable.ic_notifications);
+            }
+        }
+
+        public void flipToSettings(boolean animate) {
+            mNotificationButton.setVisibility(View.VISIBLE);
+            if (animate) {
+                mSettingsButtonAnim = start(
+                    setVisibilityWhenDone(
+                        ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 0f)
+                            .setDuration(FLIP_DURATION_OUT),
+                        mStackScroller, View.INVISIBLE));
+                mNotificationButtonAnim = start(
+                    startDelay(FLIP_DURATION_OUT,
+                        ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 1f)
+                            .setDuration(FLIP_DURATION_IN)));
+            } else {
+                mSettingsButton.setAlpha(0f);
+                mSettingsButton.setVisibility(View.INVISIBLE);
+                mNotificationButton.setAlpha(1f);
+            }
+        }
+
+        public void flipToNotifications(boolean animate) {
+            mSettingsButton.setVisibility(View.VISIBLE);
+            if (animate) {
+                mNotificationButtonAnim = start(
+                    setVisibilityWhenDone(
+                        ObjectAnimator.ofFloat(mNotificationButton, View.ALPHA, 0f)
+                            .setDuration(FLIP_DURATION_OUT),
+                        mNotificationButton, View.INVISIBLE));
+
+                mSettingsButtonAnim = start(
+                    startDelay(FLIP_DURATION_OUT,
+                        ObjectAnimator.ofFloat(mSettingsButton, View.ALPHA, 1f)
+                            .setDuration(FLIP_DURATION_IN)));
+            } else {
+                mNotificationButton.setVisibility(View.INVISIBLE);
+                mNotificationButton.setAlpha(0f);
+                mSettingsButton.setAlpha(1f);
+            }
+        }
+
+        public void cancel() {
+            cancelAnim(mSettingsButtonAnim);
+            cancelAnim(mNotificationButtonAnim);
+        }
+
+        public void setVisibility(int vis) {
+            mHolder.setVisibility(vis);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 8957a77..194774d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -168,6 +168,9 @@
         if (IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(stateExtra)) {
             mSimState = IccCardConstants.State.ABSENT;
         }
+        else if (IccCardConstants.INTENT_VALUE_ICC_CARD_IO_ERROR.equals(stateExtra)) {
+            mSimState = IccCardConstants.State.CARD_IO_ERROR;
+        }
         else if (IccCardConstants.INTENT_VALUE_ICC_READY.equals(stateExtra)) {
             mSimState = IccCardConstants.State.READY;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index d9e3fdf..79c63f7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -37,13 +37,11 @@
 
     PhoneStatusBar mBar;
     int mScrimColor;
-    float mSettingsPanelDragzoneFrac;
-    float mSettingsPanelDragzoneMin;
+    int mScrimColorKeyguard;
 
-    boolean mFullWidthNotifications;
     PanelView mFadingPanel = null;
     PanelView mLastFullyOpenedPanel = null;
-    PanelView mNotificationPanel, mSettingsPanel;
+    PanelView mNotificationPanel;
     private boolean mShouldFade;
     private final PhoneStatusBarTransitions mBarTransitions;
 
@@ -52,13 +50,7 @@
 
         Resources res = getContext().getResources();
         mScrimColor = res.getColor(R.color.notification_panel_scrim_color);
-        mSettingsPanelDragzoneMin = res.getDimension(R.dimen.settings_panel_dragzone_min);
-        try {
-            mSettingsPanelDragzoneFrac = res.getFraction(R.dimen.settings_panel_dragzone_fraction, 1, 1);
-        } catch (NotFoundException ex) {
-            mSettingsPanelDragzoneFrac = 0f;
-        }
-        mFullWidthNotifications = mSettingsPanelDragzoneFrac <= 0f;
+        mScrimColorKeyguard = res.getColor(R.color.notification_panel_scrim_color_keyguard);
         mBarTransitions = new PhoneStatusBarTransitions(this);
     }
 
@@ -70,15 +62,8 @@
         mBar = bar;
     }
 
-    public boolean hasFullWidthNotifications() {
-        return mFullWidthNotifications;
-    }
-
     @Override
     public void onAttachedToWindow() {
-        for (PanelView pv : mPanels) {
-            pv.setRubberbandingEnabled(!mFullWidthNotifications);
-        }
         mBarTransitions.init();
     }
 
@@ -87,10 +72,7 @@
         super.addPanel(pv);
         if (pv.getId() == R.id.notification_panel) {
             mNotificationPanel = pv;
-        } else if (pv.getId() == R.id.settings_panel){
-            mSettingsPanel = pv;
         }
-        pv.setRubberbandingEnabled(!mFullWidthNotifications);
     }
 
     @Override
@@ -115,40 +97,16 @@
 
     @Override
     public PanelView selectPanelForTouch(MotionEvent touch) {
-        final float x = touch.getX();
-        final boolean isLayoutRtl = isLayoutRtl();
-
-        if (mFullWidthNotifications) {
-            // No double swiping. If either panel is open, nothing else can be pulled down.
-            return ((mSettingsPanel == null ? 0 : mSettingsPanel.getExpandedHeight())
-                        + mNotificationPanel.getExpandedHeight() > 0)
-                    ? null
-                    : mNotificationPanel;
-        }
-
-        // We split the status bar into thirds: the left 2/3 are for notifications, and the
-        // right 1/3 for quick settings. If you pull the status bar down a second time you'll
-        // toggle panels no matter where you pull it down.
-
-        final float w = getMeasuredWidth();
-        float region = (w * mSettingsPanelDragzoneFrac);
-
-        if (DEBUG) {
-            Log.v(TAG, String.format(
-                "w=%.1f frac=%.3f region=%.1f min=%.1f x=%.1f w-x=%.1f",
-                w, mSettingsPanelDragzoneFrac, region, mSettingsPanelDragzoneMin, x, (w-x)));
-        }
-
-        if (region < mSettingsPanelDragzoneMin) region = mSettingsPanelDragzoneMin;
-
-        final boolean showSettings = isLayoutRtl ? (x < region) : (w - region < x);
-        return showSettings ? mSettingsPanel : mNotificationPanel;
+        // No double swiping. If either panel is open, nothing else can be pulled down.
+        return mNotificationPanel.getExpandedHeight() > 0
+                ? null
+                : mNotificationPanel;
     }
 
     @Override
     public void onPanelPeeked() {
         super.onPanelPeeked();
-        mBar.makeExpandedVisible();
+        mBar.makeExpandedVisible(false);
     }
 
     @Override
@@ -202,6 +160,18 @@
     }
 
     @Override
+    public void onTrackingStarted(PanelView panel) {
+        super.onTrackingStarted(panel);
+        mBar.onTrackingStarted();
+    }
+
+    @Override
+    public void onTrackingStopped(PanelView panel) {
+        super.onTrackingStopped(panel);
+        mBar.onTrackingStopped();
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent event) {
         return mBar.interceptTouchEvent(event) || super.onInterceptTouchEvent(event);
     }
@@ -217,6 +187,7 @@
         if (panel == mFadingPanel && mScrimColor != 0 && ActivityManager.isHighEndGfx()
                 && mBar.mStatusBarWindow != null) {
             if (mShouldFade) {
+                int scrimColor = mBar.isOnKeyguard() ? mScrimColorKeyguard : mScrimColor;
                 frac = mPanelExpandedFractionSum; // don't judge me
                 // let's start this 20% of the way down the screen
                 frac = frac * 1.2f - 0.2f;
@@ -226,7 +197,7 @@
                     // woo, special effects
                     final float k = (float)(1f-0.5f*(1f-Math.cos(3.14159f * Math.pow(1f-frac, 2f))));
                     // attenuate background color alpha by k
-                    final int color = (int) ((mScrimColor >>> 24) * k) << 24 | (mScrimColor & 0xFFFFFF);
+                    final int color = (int) ((scrimColor >>> 24) * k) << 24 | (scrimColor & 0xFFFFFF);
                     mBar.mStatusBarWindow.setBackgroundColor(color);
                 }
             }
@@ -249,5 +220,6 @@
         mBar.animateHeadsUp(mNotificationPanel == panel, mPanelExpandedFractionSum);
 
         mBar.updateCarrierLabelVisibility(false);
+        mBar.userActivity();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
index d67f7cd..f3ebf1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettings.java
@@ -71,6 +71,7 @@
 
 import com.android.internal.app.MediaRouteDialogPresenter;
 import com.android.systemui.R;
+import com.android.systemui.settings.UserSwitcherHostView;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.ActivityState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.BluetoothState;
 import com.android.systemui.statusbar.phone.QuickSettingsModel.RSSIState;
@@ -279,6 +280,7 @@
         addUserTiles(mContainerView, inflater);
         addSystemTiles(mContainerView, inflater);
         addTemporaryTiles(mContainerView, inflater);
+        addAccessibilityTiles(mContainerView);
 
         queryForUserInformation();
         queryForSslCaCerts();
@@ -310,30 +312,56 @@
         collapsePanels();
     }
 
-    private void addUserTiles(ViewGroup parent, LayoutInflater inflater) {
+    private void addAccessibilityTiles(ViewGroup parent) {
+        if (!DEBUG_GONE_TILES && !SHOW_ACCESSIBILITY_TILES) return;
+
+        // Color inversion tile
+        final SystemSettingTile inversionTile = new SystemSettingTile(mContext);
+        inversionTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
+                SystemSettingTile.TYPE_SECURE);
+        inversionTile.setFragment("Settings$AccessibilityInversionSettingsActivity");
+        mModel.addInversionTile(inversionTile, inversionTile.getRefreshCallback());
+        parent.addView(inversionTile);
+
+        // Contrast enhancement tile
+        final SystemSettingTile contrastTile = new SystemSettingTile(mContext);
+        contrastTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
+                SystemSettingTile.TYPE_SECURE);
+        contrastTile.setFragment("Settings$AccessibilityContrastSettingsActivity");
+        mModel.addContrastTile(contrastTile, contrastTile.getRefreshCallback());
+        parent.addView(contrastTile);
+
+        // Color space adjustment tile
+        final SystemSettingTile colorSpaceTile = new SystemSettingTile(mContext);
+        colorSpaceTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
+                SystemSettingTile.TYPE_SECURE);
+        colorSpaceTile.setFragment("Settings$AccessibilityDaltonizerSettingsActivity");
+        mModel.addColorSpaceTile(colorSpaceTile, colorSpaceTile.getRefreshCallback());
+        parent.addView(colorSpaceTile);
+    }
+
+    private void addUserTiles(final ViewGroup parent, final LayoutInflater inflater) {
         QuickSettingsTileView userTile = (QuickSettingsTileView)
                 inflater.inflate(R.layout.quick_settings_tile, parent, false);
         userTile.setContent(R.layout.quick_settings_tile_user, inflater);
         userTile.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {
-                collapsePanels();
                 final UserManager um = UserManager.get(mContext);
                 if (um.isUserSwitcherEnabled()) {
-                    // Since keyguard and systemui were merged into the same process to save
-                    // memory, they share the same Looper and graphics context.  As a result,
-                    // there's no way to allow concurrent animation while keyguard inflates.
-                    // The workaround is to add a slight delay to allow the animation to finish.
-                    mHandler.postDelayed(new Runnable() {
+                    final ViewGroup switcherParent = getService().getQuickSettingsOverlayParent();
+                    final UserSwitcherHostView switcher = (UserSwitcherHostView) inflater.inflate(
+                            R.layout.user_switcher_host, switcherParent, false);
+                    switcher.setFinishRunnable(new Runnable() {
+                        @Override
                         public void run() {
-                            try {
-                                WindowManagerGlobal.getWindowManagerService().lockNow(null);
-                            } catch (RemoteException e) {
-                                Log.e(TAG, "Couldn't show user switcher", e);
-                            }
+                            switcherParent.removeView(switcher);
                         }
-                    }, 400); // TODO: ideally this would be tied to the collapse of the panel
+                    });
+                    switcher.refreshUsers();
+                    switcherParent.addView(switcher);
                 } else {
+                    collapsePanels();
                     Intent intent = ContactsContract.QuickContact.composeQuickContactsIntent(
                             mContext, v, ContactsContract.Profile.CONTENT_URI,
                             ContactsContract.QuickContact.MODE_LARGE, null);
@@ -385,35 +413,6 @@
                 new QuickSettingsModel.BasicRefreshCallback(settingsTile));
         parent.addView(settingsTile);
         mDynamicSpannedTiles.add(settingsTile);
-
-        if (SHOW_ACCESSIBILITY_TILES) {
-            // Color inversion tile
-            final SystemSettingTile inversionTile = new SystemSettingTile(mContext);
-            inversionTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED,
-                    SystemSettingTile.TYPE_SECURE);
-            inversionTile.setFragment("Settings$AccessibilityInversionSettingsActivity");
-            mModel.addInversionTile(inversionTile, inversionTile.getRefreshCallback());
-            parent.addView(inversionTile);
-            mDynamicSpannedTiles.add(inversionTile);
-
-            // Contrast enhancement tile
-            final SystemSettingTile contrastTile = new SystemSettingTile(mContext);
-            contrastTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_CONTRAST_ENABLED,
-                    SystemSettingTile.TYPE_SECURE);
-            contrastTile.setFragment("Settings$AccessibilityContrastSettingsActivity");
-            mModel.addContrastTile(contrastTile, contrastTile.getRefreshCallback());
-            parent.addView(contrastTile);
-            mDynamicSpannedTiles.add(contrastTile);
-
-            // Color space adjustment tile
-            final SystemSettingTile colorSpaceTile = new SystemSettingTile(mContext);
-            colorSpaceTile.setUri(Settings.Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED,
-                    SystemSettingTile.TYPE_SECURE);
-            colorSpaceTile.setFragment("Settings$AccessibilityDaltonizerSettingsActivity");
-            mModel.addColorSpaceTile(colorSpaceTile, colorSpaceTile.getRefreshCallback());
-            parent.addView(colorSpaceTile);
-            mDynamicSpannedTiles.add(colorSpaceTile);
-        }
     }
 
     private void addSystemTiles(ViewGroup parent, LayoutInflater inflater) {
@@ -575,49 +574,6 @@
         });
         parent.addView(batteryTile);
 
-        // Airplane Mode
-        final QuickSettingsBasicTile airplaneTile
-                = new QuickSettingsBasicTile(mContext);
-        mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
-            @Override
-            public void refreshView(QuickSettingsTileView unused, State state) {
-                airplaneTile.setImageResource(state.iconId);
-
-                String airplaneState = mContext.getString(
-                        (state.enabled) ? R.string.accessibility_desc_on
-                                : R.string.accessibility_desc_off);
-                airplaneTile.setContentDescription(
-                        mContext.getString(R.string.accessibility_quick_settings_airplane, airplaneState));
-                airplaneTile.setText(state.label);
-            }
-        });
-        parent.addView(airplaneTile);
-
-        // Zen Mode
-        final QuickSettingsBasicTile zenModeTile = new QuickSettingsBasicTile(mContext);
-        zenModeTile.setOnClickListener(new View.OnClickListener() {
-            @Override
-            public void onClick(View v) {
-                showZenModeDialog();
-            }
-        });
-        mModel.addZenModeTile(zenModeTile, new QuickSettingsModel.RefreshCallback() {
-            @Override
-            public void refreshView(QuickSettingsTileView unused, State state) {
-                zenModeTile.setImageResource(state.iconId);
-                // TODO cut new assets
-                zenModeTile.getImageView().setAlpha(state.enabled ? 1 : .2f);
-                zenModeTile.getImageView().setScaleX(1.5f);
-                zenModeTile.getImageView().setScaleY(1.5f);
-                // for landscape version
-                zenModeTile.getTextView().setMaxLines(2);
-                zenModeTile.getTextView().setEllipsize(TruncateAt.END);
-                // TODO content description
-                zenModeTile.setText(state.label);
-            }
-        });
-        parent.addView(zenModeTile);
-
         // Bluetooth
         if (mModel.deviceSupportsBluetooth()
                 || DEBUG_GONE_TILES) {
@@ -711,6 +667,50 @@
             }
         });
         parent.addView(locationTile);
+
+        // Airplane Mode
+        final QuickSettingsBasicTile airplaneTile
+                = new QuickSettingsBasicTile(mContext);
+        mModel.addAirplaneModeTile(airplaneTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView unused, State state) {
+                airplaneTile.setImageResource(state.iconId);
+
+                String airplaneState = mContext.getString(
+                        (state.enabled) ? R.string.accessibility_desc_on
+                                : R.string.accessibility_desc_off);
+                airplaneTile.setContentDescription(
+                        mContext.getString(R.string.accessibility_quick_settings_airplane,
+                                airplaneState));
+                airplaneTile.setText(state.label);
+            }
+        });
+        parent.addView(airplaneTile);
+
+        // Zen Mode
+        final QuickSettingsBasicTile zenModeTile = new QuickSettingsBasicTile(mContext);
+        zenModeTile.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                showZenModeDialog();
+            }
+        });
+        mModel.addZenModeTile(zenModeTile, new QuickSettingsModel.RefreshCallback() {
+            @Override
+            public void refreshView(QuickSettingsTileView unused, State state) {
+                zenModeTile.setImageResource(state.iconId);
+                // TODO cut new assets
+                zenModeTile.getImageView().setAlpha(state.enabled ? 1 : .2f);
+                zenModeTile.getImageView().setScaleX(1.5f);
+                zenModeTile.getImageView().setScaleY(1.5f);
+                // for landscape version
+                zenModeTile.getTextView().setMaxLines(2);
+                zenModeTile.getTextView().setEllipsize(TruncateAt.END);
+                // TODO content description
+                zenModeTile.setText(state.label);
+            }
+        });
+        parent.addView(zenModeTile);
     }
 
     private void addTemporaryTiles(final ViewGroup parent, final LayoutInflater inflater) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
index 17ee017..c44cb0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsContainerView.java
@@ -19,7 +19,13 @@
 import android.animation.LayoutTransition;
 import android.content.Context;
 import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.Rect;
+import android.graphics.Typeface;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.FrameLayout;
@@ -31,30 +37,59 @@
  */
 class QuickSettingsContainerView extends FrameLayout {
 
+    private static boolean sShowScrim = true;
+
+    private final Context mContext;
+
     // The number of columns in the QuickSettings grid
     private int mNumColumns;
 
+    private boolean mKeyguardShowing;
+    private int mMaxRows;
+    private int mMaxRowsOnKeyguard;
+
     // The gap between tiles in the QuickSettings grid
     private float mCellGap;
 
+    private ScrimView mScrim;
+
     public QuickSettingsContainerView(Context context, AttributeSet attrs) {
         super(context, attrs);
-
+        mContext = context;
         updateResources();
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
-
+        if (sShowScrim) {
+            mScrim = new ScrimView(mContext);
+            addView(mScrim);
+        }
         // TODO: Setup the layout transitions
         LayoutTransition transitions = getLayoutTransition();
     }
 
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        if (mScrim != null) {
+            sShowScrim = false;
+            removeView(mScrim);
+        }
+        return super.onTouchEvent(event);
+    }
+
     void updateResources() {
         Resources r = getContext().getResources();
         mCellGap = r.getDimension(R.dimen.quick_settings_cell_gap);
         mNumColumns = r.getInteger(R.integer.quick_settings_num_columns);
+        mMaxRows = r.getInteger(R.integer.quick_settings_max_rows);
+        mMaxRowsOnKeyguard = r.getInteger(R.integer.quick_settings_max_rows_keyguard);
+        requestLayout();
+    }
+
+    void setKeyguardShowing(boolean showing) {
+        mKeyguardShowing = showing;
         requestLayout();
     }
 
@@ -71,10 +106,18 @@
         final int N = getChildCount();
         int cellHeight = 0;
         int cursor = 0;
+        int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
+
         for (int i = 0; i < N; ++i) {
+            if (getChildAt(i).equals(mScrim)) {
+                continue;
+            }
             // Update the child's width
             QuickSettingsTileView v = (QuickSettingsTileView) getChildAt(i);
             if (v.getVisibility() != View.GONE) {
+                int row = (int) (cursor / mNumColumns);
+                if (row >= maxRows) continue;
+
                 ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
                 int colSpan = v.getColumnSpan();
                 lp.width = (int) ((colSpan * cellWidth) + (colSpan - 1) * mCellGap);
@@ -102,6 +145,9 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        if (mScrim != null) {
+            mScrim.bringToFront();
+        }
         final int N = getChildCount();
         final boolean isLayoutRtl = isLayoutRtl();
         final int width = getWidth();
@@ -109,8 +155,18 @@
         int x = getPaddingStart();
         int y = getPaddingTop();
         int cursor = 0;
+        int maxRows = mKeyguardShowing ? mMaxRowsOnKeyguard : mMaxRows;
 
         for (int i = 0; i < N; ++i) {
+            if (getChildAt(i).equals(mScrim)) {
+                int w = right - left - getPaddingLeft() - getPaddingRight();
+                int h = bottom - top - getPaddingTop() - getPaddingBottom();
+                mScrim.measure(
+                        MeasureSpec.makeMeasureSpec(w, MeasureSpec.EXACTLY),
+                        MeasureSpec.makeMeasureSpec(h, MeasureSpec.EXACTLY));
+                mScrim.layout(getPaddingLeft(), getPaddingTop(), right, bottom);
+                continue;
+            }
             QuickSettingsTileView child = (QuickSettingsTileView) getChildAt(i);
             ViewGroup.LayoutParams lp = child.getLayoutParams();
             if (child.getVisibility() != GONE) {
@@ -121,6 +177,7 @@
                 final int childHeight = lp.height;
 
                 int row = (int) (cursor / mNumColumns);
+                if (row >= maxRows) continue;
 
                 // Push the item to the next row if it can't fit on this one
                 if ((col + colSpan) > mNumColumns) {
@@ -150,4 +207,89 @@
             }
         }
     }
+
+    private static final class ScrimView extends View {
+        private static final int SCRIM = 0x4f000000;
+        private static final int COLOR = 0xaf4285f4;
+
+        private final Paint mLinePaint;
+        private final int mStrokeWidth;
+        private final Rect mTmp = new Rect();
+        private final Paint mTextPaint;
+        private final int mTextSize;
+
+        public ScrimView(Context context) {
+            super(context);
+            setFocusable(false);
+            final Resources res = context.getResources();
+            mStrokeWidth = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_stroke_width);
+            mTextSize = res.getDimensionPixelSize(R.dimen.quick_settings_tmp_scrim_text_size);
+
+            mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mLinePaint.setColor(COLOR);
+            mLinePaint.setStrokeWidth(mStrokeWidth);
+            mLinePaint.setStrokeJoin(Paint.Join.ROUND);
+            mLinePaint.setStrokeCap(Paint.Cap.ROUND);
+            mLinePaint.setStyle(Paint.Style.STROKE);
+
+            mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
+            mTextPaint.setColor(COLOR);
+            mTextPaint.setTextSize(mTextSize);
+            mTextPaint.setTypeface(Typeface.create("sans-serif-condensed", Typeface.BOLD));
+        }
+
+        @Override
+        protected void onDraw(Canvas canvas) {
+            final int w = getMeasuredWidth();
+            final int h = getMeasuredHeight();
+            final int f = mStrokeWidth * 3 / 4;
+
+            canvas.drawColor(SCRIM);
+            canvas.drawPath(line(f, h / 2, w - f, h / 2), mLinePaint);
+            canvas.drawPath(line(w / 2, f, w / 2, h - f), mLinePaint);
+
+            final int s = mStrokeWidth;
+            mTextPaint.setTextAlign(Paint.Align.RIGHT);
+            canvas.drawText("FUTURE", w / 2 - s, h / 2 - s, mTextPaint);
+            mTextPaint.setTextAlign(Paint.Align.LEFT);
+            canvas.drawText("SITE OF", w / 2 + s, h / 2 - s , mTextPaint);
+            mTextPaint.setTextAlign(Paint.Align.RIGHT);
+            drawUnder(canvas, "QUANTUM", w / 2 - s, h / 2 + s);
+            mTextPaint.setTextAlign(Paint.Align.LEFT);
+            drawUnder(canvas, "SETTINGS", w / 2 + s, h / 2 + s);
+        }
+
+        private void drawUnder(Canvas c, String text, float x, float y) {
+            if (mTmp.isEmpty()) {
+                mTextPaint.getTextBounds(text, 0, text.length(), mTmp);
+            }
+            c.drawText(text, x, y + mTmp.height() * .85f, mTextPaint);
+        }
+
+        private Path line(float x1, float y1, float x2, float y2) {
+            final int a = mStrokeWidth * 2;
+            final Path p = new Path();
+            p.moveTo(x1, y1);
+            p.lineTo(x2, y2);
+            if (y1 == y2) {
+                p.moveTo(x1 + a, y1 + a);
+                p.lineTo(x1, y1);
+                p.lineTo(x1 + a, y1 - a);
+
+                p.moveTo(x2 - a, y2 - a);
+                p.lineTo(x2, y2);
+                p.lineTo(x2 - a, y2 + a);
+            }
+            if (x1 == x2) {
+                p.moveTo(x1 - a, y1 + a);
+                p.lineTo(x1, y1);
+                p.lineTo(x1 + a, y1 + a);
+
+                p.moveTo(x2 - a, y2 - a);
+                p.lineTo(x2, y2);
+                p.lineTo(x2 + a, y2 - a);
+            }
+            return p;
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
index 9b25046..e1ef83a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/QuickSettingsModel.java
@@ -608,7 +608,7 @@
                 Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
         mZenModeState.enabled = mode != Settings.Global.ZEN_MODE_OFF;
         mZenModeState.zenMode = mode;
-        mZenModeState.label = ZenModeView.MODE_LABEL;
+        mZenModeState.label = mContext.getString(R.string.zen_mode_title);
         mZenModeState.iconId = R.drawable.stat_sys_zen_limited;
         mZenModeCallback.refreshView(mZenModeTile, mZenModeState);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
deleted file mode 100644
index c10a0d4..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SettingsPanelView.java
+++ /dev/null
@@ -1,161 +0,0 @@
-/*
- * Copyright (C) 2012 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 com.android.systemui.statusbar.phone;
-
-import android.content.Context;
-import android.content.res.Resources;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.util.AttributeSet;
-import android.util.EventLog;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.accessibility.AccessibilityEvent;
-
-import com.android.systemui.EventLogTags;
-import com.android.systemui.R;
-import com.android.systemui.statusbar.GestureRecorder;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BluetoothController;
-import com.android.systemui.statusbar.policy.LocationController;
-import com.android.systemui.statusbar.policy.NetworkController;
-import com.android.systemui.statusbar.policy.RotationLockController;
-
-public class SettingsPanelView extends PanelView {
-    public static final boolean DEBUG_GESTURES = true;
-
-    private QuickSettings mQS;
-    private QuickSettingsContainerView mQSContainer;
-
-    Drawable mHandleBar;
-    int mHandleBarHeight;
-    View mHandleView;
-
-    public SettingsPanelView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    @Override
-    protected void onFinishInflate() {
-        super.onFinishInflate();
-
-        mQSContainer = (QuickSettingsContainerView) findViewById(R.id.quick_settings_container);
-
-        Resources resources = getContext().getResources();
-        mHandleBar = resources.getDrawable(R.drawable.status_bar_close);
-        mHandleBarHeight = resources.getDimensionPixelSize(R.dimen.close_handle_height);
-        mHandleView = findViewById(R.id.handle);
-    }
-
-    public void setQuickSettings(QuickSettings qs) {
-        mQS = qs;
-    }
-
-    @Override
-    public void setBar(PanelBar panelBar) {
-        super.setBar(panelBar);
-
-        if (mQS != null) {
-            mQS.setBar(panelBar);
-        }
-    }
-
-    public void setImeWindowStatus(boolean visible) {
-        if (mQS != null) {
-            mQS.setImeWindowStatus(visible);
-        }
-    }
-
-    public void setup(NetworkController networkController, BluetoothController bluetoothController,
-            BatteryController batteryController, LocationController locationController,
-            RotationLockController rotationLockController) {
-        if (mQS != null) {
-            mQS.setup(networkController, bluetoothController, batteryController,
-                    locationController, rotationLockController);
-        }
-    }
-
-    void updateResources() {
-        if (mQS != null) {
-            mQS.updateResources();
-        }
-        if (mQSContainer != null) {
-            mQSContainer.updateResources();
-        }
-        requestLayout();
-    }
-
-    @Override
-    public void fling(float vel, boolean always) {
-        GestureRecorder gr = ((PhoneStatusBarView) mBar).mBar.getGestureRecorder();
-        if (gr != null) {
-            gr.tag(
-                "fling " + ((vel > 0) ? "open" : "closed"),
-                "settings,v=" + vel);
-        }
-        super.fling(vel, always);
-    }
-
-    public void setService(PhoneStatusBar phoneStatusBar) {
-        if (mQS != null) {
-            mQS.setService(phoneStatusBar);
-        }
-    }
-
-    @Override
-    public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
-        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
-            event.getText()
-                    .add(getContext().getString(R.string.accessibility_desc_quick_settings));
-            return true;
-        }
-
-        return super.dispatchPopulateAccessibilityEvent(event);
-    }
-
-    // We draw the handle ourselves so that it's always glued to the bottom of the window.
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        if (changed) {
-            final int pl = getPaddingLeft();
-            final int pr = getPaddingRight();
-            mHandleBar.setBounds(pl, 0, getWidth() - pr, (int) mHandleBarHeight);
-        }
-    }
-
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-        final int off = (int) (getHeight() - mHandleBarHeight - getPaddingBottom());
-        canvas.translate(0, off);
-        mHandleBar.setState(mHandleView.getDrawableState());
-        mHandleBar.draw(canvas);
-        canvas.translate(0, -off);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent event) {
-        if (DEBUG_GESTURES) {
-            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
-                EventLog.writeEvent(EventLogTags.SYSUI_QUICKPANEL_TOUCH,
-                       event.getActionMasked(), (int) event.getX(), (int) event.getY());
-            }
-        }
-        return super.onTouchEvent(event);
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
new file mode 100644
index 0000000..c2595cf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.util.Slog;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.widget.LockPatternUtils;
+import com.android.keyguard.KeyguardHostView;
+import com.android.keyguard.KeyguardSimpleHostView;
+import com.android.keyguard.R;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.keyguard.KeyguardViewMediator;
+
+/**
+ * Manages creating, showing, hiding and resetting the keyguard within the status bar. Calls back
+ * via {@link ViewMediatorCallback} to poke the wake lock and report that the keyguard is done,
+ * which is in turn, reported to this class by the current
+ * {@link com.android.keyguard.KeyguardViewBase}.
+ */
+public class StatusBarKeyguardViewManager {
+    private static String TAG = "StatusBarKeyguardViewManager";
+
+    private final Context mContext;
+
+    private LockPatternUtils mLockPatternUtils;
+    private ViewMediatorCallback mViewMediatorCallback;
+    private PhoneStatusBar mPhoneStatusBar;
+
+    private ViewGroup mContainer;
+    private StatusBarWindowManager mStatusBarWindowManager;
+
+    private boolean mScreenOn = false;
+    private KeyguardBouncer mBouncer;
+    private boolean mShowing;
+    private boolean mOccluded;
+
+    public StatusBarKeyguardViewManager(Context context, ViewMediatorCallback callback,
+            LockPatternUtils lockPatternUtils) {
+        mContext = context;
+        mViewMediatorCallback = callback;
+        mLockPatternUtils = lockPatternUtils;
+    }
+
+    public void registerStatusBar(PhoneStatusBar phoneStatusBar,
+            ViewGroup container, StatusBarWindowManager statusBarWindowManager) {
+        mPhoneStatusBar = phoneStatusBar;
+        mContainer = container;
+        mStatusBarWindowManager = statusBarWindowManager;
+        mBouncer = new KeyguardBouncer(mContext, mViewMediatorCallback, mLockPatternUtils,
+                mStatusBarWindowManager, container);
+    }
+
+    /**
+     * Show the keyguard.  Will handle creating and attaching to the view manager
+     * lazily.
+     */
+    public void show(Bundle options) {
+        mShowing = true;
+        mStatusBarWindowManager.setKeyguardShowing(true);
+        showBouncerOrKeyguard();
+        updateBackButtonState();
+    }
+
+    /**
+     * Shows the notification keyguard or the bouncer depending on
+     * {@link KeyguardBouncer#needsFullscreenBouncer()}.
+     */
+    private void showBouncerOrKeyguard() {
+        if (mBouncer.needsFullscreenBouncer()) {
+
+            // The keyguard might be showing (already). So we need to hide it.
+            mPhoneStatusBar.hideKeyguard();
+            mBouncer.show();
+        } else {
+            mPhoneStatusBar.showKeyguard();
+            mBouncer.hide();
+            mBouncer.prepare();
+        }
+    }
+
+    public void showBouncer() {
+        mBouncer.show();
+        updateBackButtonState();
+    }
+
+    /**
+     * Reset the state of the view.
+     */
+    public void reset() {
+        showBouncerOrKeyguard();
+        updateBackButtonState();
+    }
+
+    public void onScreenTurnedOff() {
+        mScreenOn = false;
+        mBouncer.onScreenTurnedOff();
+    }
+
+    public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
+        mScreenOn = true;
+        if (callback != null) {
+            callbackAfterDraw(callback);
+        }
+    }
+
+    private void callbackAfterDraw(final IKeyguardShowCallback callback) {
+        mContainer.post(new Runnable() {
+            @Override
+            public void run() {
+                try {
+                    callback.onShown(mContainer.getWindowToken());
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Exception calling onShown():", e);
+                }
+            }
+        });
+    }
+
+    public void verifyUnlock() {
+        dismiss();
+    }
+
+    public void setNeedsInput(boolean needsInput) {
+        mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+    }
+
+    public void updateUserActivityTimeout() {
+        mStatusBarWindowManager.setKeyguardUserActivityTimeout(mBouncer.getUserActivityTimeout());
+    }
+
+    public void setOccluded(boolean occluded) {
+        mOccluded = occluded;
+        mStatusBarWindowManager.setKeyguardOccluded(occluded);
+        updateBackButtonState();
+    }
+
+    /**
+     * Hides the keyguard view
+     */
+    public void hide() {
+        mShowing = false;
+        mPhoneStatusBar.hideKeyguard();
+        mStatusBarWindowManager.setKeyguardShowing(false);
+        mBouncer.hide();
+        mViewMediatorCallback.keyguardGone();
+        updateBackButtonState();
+    }
+
+    /**
+     * Dismisses the keyguard by going to the next screen or making it gone.
+     */
+    public void dismiss() {
+        if (mScreenOn) {
+            showBouncer();
+        }
+    }
+
+    public boolean isSecure() {
+        return mBouncer.isSecure();
+    }
+
+    /**
+     * @return Whether the keyguard is showing
+     */
+    public boolean isShowing() {
+        return mShowing;
+    }
+
+    /**
+     * Notifies this manager that the back button has been pressed.
+     *
+     * @return whether the back press has been handled
+     */
+    public boolean onBackPressed() {
+        if (mBouncer.isShowing()) {
+            mBouncer.hide();
+            mPhoneStatusBar.showKeyguard();
+            updateBackButtonState();
+            return true;
+        }
+        return false;
+    }
+
+    private void updateBackButtonState() {
+        int vis = mContainer.getSystemUiVisibility();
+        boolean bouncerDismissable = mBouncer.isShowing() && !mBouncer.needsFullscreenBouncer();
+        if (bouncerDismissable || !mShowing) {
+            mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
+        } else {
+            mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
+        }
+        if (!(mShowing && !mOccluded) || mBouncer.isShowing()) {
+            mPhoneStatusBar.getNavigationBarView().setVisibility(View.VISIBLE);
+        } else {
+            mPhoneStatusBar.getNavigationBarView().setVisibility(View.GONE);
+        }
+    }
+
+    public boolean onMenuPressed() {
+        return mBouncer.onMenuPressed();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
new file mode 100644
index 0000000..d175d7a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import android.app.ActionBar;
+import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Resources;
+import android.graphics.PixelFormat;
+import android.os.SystemProperties;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
+
+import com.android.keyguard.R;
+
+/**
+ * Encapsulates all logic for the status bar window state management.
+ */
+public class StatusBarWindowManager {
+
+    private final Context mContext;
+    private final WindowManager mWindowManager;
+    private View mStatusBarView;
+    private WindowManager.LayoutParams mLp;
+    private int mBarHeight;
+    private final boolean mKeyguardScreenRotation;
+
+    private final State mCurrentState = new State();
+
+    public StatusBarWindowManager(Context context) {
+        mContext = context;
+        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
+        mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
+    }
+
+    private boolean shouldEnableKeyguardScreenRotation() {
+        Resources res = mContext.getResources();
+        return SystemProperties.getBoolean("lockscreen.rot_override", false)
+                || res.getBoolean(R.bool.config_enableLockScreenRotation);
+    }
+
+    /**
+     * Adds the status bar view to the window manager.
+     *
+     * @param statusBarView The view to add.
+     * @param barHeight The height of the status bar in collapsed state.
+     */
+    public void add(View statusBarView, int barHeight) {
+
+        // Now that the status bar window encompasses the sliding panel and its
+        // translucent backdrop, the entire thing is made TRANSLUCENT and is
+        // hardware-accelerated.
+        mLp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                barHeight,
+                WindowManager.LayoutParams.TYPE_STATUS_BAR,
+                WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
+                        | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
+                        | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
+                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION
+                        | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
+                PixelFormat.TRANSLUCENT);
+
+        mLp.flags |= WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED;
+        mLp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
+        mLp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
+        mLp.setTitle("StatusBar");
+        mLp.packageName = mContext.getPackageName();
+        mStatusBarView = statusBarView;
+        mBarHeight = barHeight;
+        mWindowManager.addView(mStatusBarView, mLp);
+    }
+
+    private void applyKeyguardFlags(State state) {
+        if (state.keyguardShowing) {
+            mLp.flags |= WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLp.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        } else {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+            mLp.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+        }
+    }
+
+    private void adjustScreenOrientation(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()) {
+            if (mKeyguardScreenRotation) {
+                mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_USER;
+            } else {
+                mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
+            }
+        } else {
+            mLp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+        }
+    }
+
+    private void applyFocusableFlag(State state) {
+        if (state.isKeyguardShowingAndNotOccluded() && state.keyguardNeedsInput) {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else if (state.isKeyguardShowingAndNotOccluded() || state.statusBarFocusable) {
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags |= WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        } else {
+            mLp.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+            mLp.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+        }
+    }
+
+    private void applyHeight(State state) {
+        boolean expanded = state.isKeyguardShowingAndNotOccluded() || state.statusBarExpanded;
+        if (expanded) {
+            mLp.height = ViewGroup.LayoutParams.MATCH_PARENT;
+        } else {
+            mLp.height = mBarHeight;
+        }
+    }
+
+    private void applyFitsSystemWindows(State state) {
+        mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
+    }
+
+    private void applyUserActivityTimeout(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()) {
+            mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
+        } else {
+            mLp.userActivityTimeout = -1;
+        }
+    }
+
+    private void applyInputFeatures(State state) {
+        if (state.isKeyguardShowingAndNotOccluded()) {
+            mLp.inputFeatures |= WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        } else {
+            mLp.inputFeatures &= ~WindowManager.LayoutParams.INPUT_FEATURE_DISABLE_USER_ACTIVITY;
+        }
+    }
+
+    private void apply(State state) {
+        applyKeyguardFlags(state);
+        applyFocusableFlag(state);
+        adjustScreenOrientation(state);
+        applyHeight(state);
+        applyUserActivityTimeout(state);
+        applyInputFeatures(state);
+        applyFitsSystemWindows(state);
+        mWindowManager.updateViewLayout(mStatusBarView, mLp);
+    }
+
+    public void setKeyguardShowing(boolean showing) {
+        mCurrentState.keyguardShowing = showing;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardOccluded(boolean occluded) {
+        mCurrentState.keyguardOccluded = occluded;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardNeedsInput(boolean needsInput) {
+        mCurrentState.keyguardNeedsInput = needsInput;
+        apply(mCurrentState);
+    }
+
+    public void setStatusBarExpanded(boolean expanded) {
+        mCurrentState.statusBarExpanded = expanded;
+        mCurrentState.statusBarFocusable = expanded;
+        apply(mCurrentState);
+    }
+
+    public void setStatusBarFocusable(boolean focusable) {
+        mCurrentState.statusBarFocusable = focusable;
+        apply(mCurrentState);
+    }
+
+    public void setKeyguardUserActivityTimeout(long timeout) {
+        mCurrentState.keyguardUserActivityTimeout = timeout;
+        apply(mCurrentState);
+    }
+
+    private static class State {
+        boolean keyguardShowing;
+        boolean keyguardOccluded;
+        boolean keyguardNeedsInput;
+        boolean statusBarExpanded;
+        boolean statusBarFocusable;
+        long keyguardUserActivityTimeout;
+
+        private boolean isKeyguardShowingAndNotOccluded() {
+            return keyguardShowing && !keyguardOccluded;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a7121c4..6b5ef5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -20,6 +20,7 @@
 import android.content.Context;
 import android.graphics.Canvas;
 import android.graphics.Paint;
+import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
@@ -52,14 +53,24 @@
     }
 
     @Override
+    protected boolean fitSystemWindows(Rect insets) {
+        if (getFitsSystemWindows()) {
+            setPadding(insets.left, insets.top, insets.right, insets.bottom);
+        } else {
+            setPadding(0, 0, 0, 0);
+        }
+        return true;
+    }
+
+    @Override
     protected void onAttachedToWindow () {
         super.onAttachedToWindow();
 
         mStackScrollLayout = (NotificationStackScrollLayout) findViewById(
                 R.id.notification_stack_scroller);
         mNotificationPanel = (NotificationPanelView) findViewById(R.id.notification_panel);
-        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
-        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
+        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
         mExpandHelper = new ExpandHelper(getContext(), mStackScrollLayout,
                 minHeight, maxHeight);
         mExpandHelper.setEventSource(this);
@@ -77,11 +88,15 @@
     public boolean dispatchKeyEvent(KeyEvent event) {
         boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         switch (event.getKeyCode()) {
-        case KeyEvent.KEYCODE_BACK:
-            if (!down) {
-                mService.animateCollapsePanels();
-            }
-            return true;
+            case KeyEvent.KEYCODE_BACK:
+                if (!down) {
+                    mService.onBackPressed();
+                }
+                return true;
+            case KeyEvent.KEYCODE_MENU:
+                if (!down) {
+                    return mService.onMenuPressed();
+                }
         }
         return super.dispatchKeyEvent(event);
     }
@@ -90,7 +105,8 @@
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         boolean intercept = false;
         if (mNotificationPanel.isFullyExpanded()
-                && mStackScrollLayout.getVisibility() == View.VISIBLE) {
+                && mStackScrollLayout.getVisibility() == View.VISIBLE
+                && !mService.isOnKeyguard()) {
             intercept = mExpandHelper.onInterceptTouchEvent(ev);
         }
         if (!intercept) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
index 49cf78b..20011ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeView.java
@@ -42,13 +42,13 @@
 import android.widget.TextView;
 import android.widget.Toast;
 
+import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.ZenModeView.Adapter.ExitCondition;
 
 public class ZenModeView extends RelativeLayout {
     private static final String TAG = ZenModeView.class.getSimpleName();
     private static final boolean DEBUG = false;
 
-    public static final String MODE_LABEL = "Limited interruptions";
     public static final int BACKGROUND = 0xff282828;
 
     private static final Typeface CONDENSED =
@@ -91,7 +91,7 @@
         LayoutParams lp = null;
 
         mModeText = new TextView(mContext);
-        mModeText.setText(MODE_LABEL);
+        mModeText.setText(R.string.zen_mode_title);
         mModeText.setId(android.R.id.title);
         mModeText.setTextColor(GRAY);
         mModeText.setTypeface(CONDENSED);
@@ -212,6 +212,13 @@
         }
     }
 
+    @Override
+    protected void onDetachedFromWindow() {
+        if (mAdapter != null) {
+            mAdapter.dispose();
+        }
+    }
+
     public void setAutoActivate(boolean value) {
         mAutoActivate = value;
     }
@@ -396,6 +403,7 @@
         void setMode(boolean mode);
         void select(ExitCondition ec);
         void init();
+        void dispose();
         void setCallbacks(Callbacks callbacks);
         ExitCondition getExitCondition(int d);
         int getExitConditionCount();
@@ -406,6 +414,7 @@
             public String line1;
             public String line2;
             public String action;
+            public Object tag;
         }
 
         public interface Callbacks {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
index c97ba8d..1bc97a0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ZenModeViewAdapter.java
@@ -16,14 +16,22 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.INotificationManager;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.database.ContentObserver;
+import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Handler;
+import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.provider.Settings;
+import android.service.notification.Condition;
+import android.service.notification.IConditionListener;
+import android.util.ArrayMap;
 import android.util.Log;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 
@@ -34,8 +42,10 @@
     private final ContentResolver mResolver;
     private final Handler mHandler = new Handler();
     private final SettingsObserver mObserver;
-    private final List<ExitCondition> mExits = Arrays.asList(
-            newExit("Until you turn this off", "Until", "You turn this off"));
+    private final List<ExitCondition> mExits = new ArrayList<ExitCondition>(Arrays.asList(
+            newExit("Until you turn this off", "Until", "You turn this off", null)));
+    private final INotificationManager mNoMan;
+    private final ArrayMap<Uri, Condition> mConditions = new ArrayMap<Uri, Condition>();
 
     private Callbacks mCallbacks;
     private int mExitIndex;
@@ -45,6 +55,13 @@
         mContext = context;
         mResolver = mContext.getContentResolver();
         mObserver = new SettingsObserver(mHandler);
+        mNoMan = INotificationManager.Stub.asInterface(
+                ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+        try {
+            mNoMan.requestZenModeConditions(mListener, true /*requested*/);
+        } catch (RemoteException e) {
+            // noop
+        }
         mObserver.init();
         init();
     }
@@ -75,6 +92,16 @@
             mExitIndex = 0;
             dispatchChanged();
         }
+        setZenModeCondition();
+    }
+
+    @Override
+    public void dispose() {
+        try {
+            mNoMan.requestZenModeConditions(mListener, false /*requested*/);
+        } catch (RemoteException e) {
+            // noop
+        }
     }
 
     private void dispatchChanged() {
@@ -117,13 +144,28 @@
         }
         mExitIndex = i;
         dispatchChanged();
+        setZenModeCondition();
     }
 
-    private static ExitCondition newExit(String summary, String line1, String line2) {
+    private void setZenModeCondition() {
+        if (mExitIndex < 0 || mExitIndex >= mExits.size()) {
+            Log.w(TAG, "setZenModeCondition to bad index " + mExitIndex + " of " + mExits.size());
+            return;
+        }
+        final Uri conditionUri = (Uri) mExits.get(mExitIndex).tag;
+        try {
+            mNoMan.setZenModeCondition(conditionUri);
+        } catch (RemoteException e) {
+            // noop
+        }
+    }
+
+    private static ExitCondition newExit(String summary, String line1, String line2, Object tag) {
         final ExitCondition rt = new ExitCondition();
         rt.summary = summary;
         rt.line1 = line1;
         rt.line2 = line2;
+        rt.tag = tag;
         return rt;
     }
 
@@ -168,4 +210,21 @@
             return v != Settings.Global.ZEN_MODE_OFF;
         }
     }
+
+    private final IConditionListener mListener = new IConditionListener.Stub() {
+        @Override
+        public void onConditionsReceived(Condition[] conditions) {
+            if (conditions == null || conditions.length == 0) return;
+            for (Condition c : conditions) {
+                mConditions.put(c.id, c);
+            }
+            for (int i = mExits.size() - 1; i > 0; i--) {
+                mExits.remove(i);
+            }
+            for (Condition c : mConditions.values()) {
+                mExits.add(newExit(c.caption, "", "", c.id));
+            }
+            dispatchChanged();
+        }
+    };
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
index 79932a7..c94c65f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpNotificationView.java
@@ -78,7 +78,7 @@
         }
 
         if (mHeadsUp != null) {
-            mHeadsUp.row.setExpanded(true);
+            mHeadsUp.row.setSystemExpanded(true);
             mHeadsUp.row.setShowingPublic(false);
             if (mContentHolder == null) {
                 // too soon!
@@ -135,8 +135,8 @@
         mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
         mEdgeSwipeHelper = new EdgeSwipeHelper(touchSlop);
 
-        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_min_height);
-        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_row_max_height);
+        int minHeight = getResources().getDimensionPixelSize(R.dimen.notification_min_height);
+        int maxHeight = getResources().getDimensionPixelSize(R.dimen.notification_max_height);
         mExpandHelper = new ExpandHelper(getContext(), this, minHeight, maxHeight);
 
         mContentHolder = (ViewGroup) findViewById(R.id.content_holder);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
deleted file mode 100644
index 266cecf..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NotificationRowLayout.java
+++ /dev/null
@@ -1,284 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.systemui.statusbar.policy;
-
-import android.animation.LayoutTransition;
-import android.animation.ValueAnimator;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.Rect;
-import android.util.AttributeSet;
-import android.util.Log;
-import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.LinearLayout;
-
-import com.android.systemui.ExpandHelper;
-import com.android.systemui.R;
-import com.android.systemui.SwipeHelper;
-import com.android.systemui.statusbar.ExpandableNotificationRow;
-
-import java.util.HashMap;
-
-public class NotificationRowLayout
-        extends LinearLayout
-        implements SwipeHelper.Callback, ExpandHelper.Callback
-{
-    private static final String TAG = "NotificationRowLayout";
-    private static final boolean DEBUG = false;
-    private static final boolean SLOW_ANIMATIONS = DEBUG;
-
-    private static final int APPEAR_ANIM_LEN = SLOW_ANIMATIONS ? 5000 : 250;
-    private static final int DISAPPEAR_ANIM_LEN = APPEAR_ANIM_LEN;
-
-    boolean mAnimateBounds = true;
-
-    Rect mTmpRect = new Rect();
-
-    HashMap<View, ValueAnimator> mAppearingViews = new HashMap<View, ValueAnimator>();
-    HashMap<View, ValueAnimator> mDisappearingViews = new HashMap<View, ValueAnimator>();
-
-    private SwipeHelper mSwipeHelper;
-
-    private OnSizeChangedListener mOnSizeChangedListener;
-
-    // Flag set during notification removal animation to avoid causing too much work until
-    // animation is done
-    boolean mRemoveViews = true;
-
-    private LayoutTransition mRealLayoutTransition;
-
-    public NotificationRowLayout(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public NotificationRowLayout(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
-
-        mRealLayoutTransition = new LayoutTransition();
-        mRealLayoutTransition.setAnimateParentHierarchy(true);
-        setLayoutTransitionsEnabled(true);
-
-        setOrientation(LinearLayout.VERTICAL);
-
-        if (DEBUG) {
-            setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
-                @Override
-                public void onChildViewAdded(View parent, View child) {
-                    Log.d(TAG, "view added: " + child + "; new count: " + getChildCount());
-                }
-                @Override
-                public void onChildViewRemoved(View parent, View child) {
-                    Log.d(TAG, "view removed: " + child + "; new count: " + (getChildCount() - 1));
-                }
-            });
-
-            setBackgroundColor(0x80FF8000);
-        }
-
-        float densityScale = getResources().getDisplayMetrics().density;
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper = new SwipeHelper(SwipeHelper.X, this, densityScale, pagingTouchSlop);
-    }
-
-    public void setLongPressListener(View.OnLongClickListener listener) {
-        mSwipeHelper.setLongPressListener(listener);
-    }
-
-    public void setOnSizeChangedListener(OnSizeChangedListener l) {
-        mOnSizeChangedListener = l;
-    }
-
-    @Override
-    public void onWindowFocusChanged(boolean hasWindowFocus) {
-        super.onWindowFocusChanged(hasWindowFocus);
-        if (!hasWindowFocus) {
-            mSwipeHelper.removeLongPressCallback();
-        }
-    }
-
-    public void setAnimateBounds(boolean anim) {
-        mAnimateBounds = anim;
-    }
-
-    private void logLayoutTransition() {
-        Log.v(TAG, "layout " +
-              (mRealLayoutTransition.isChangingLayout() ? "is " : "is not ") +
-              "in transition and animations " +
-              (mRealLayoutTransition.isRunning() ? "are " : "are not ") +
-              "running.");
-    }
-
-    @Override
-    public boolean onInterceptTouchEvent(MotionEvent ev) {
-        if (DEBUG) Log.v(TAG, "onInterceptTouchEvent()");
-        if (DEBUG) logLayoutTransition();
-
-        return mSwipeHelper.onInterceptTouchEvent(ev) ||
-                super.onInterceptTouchEvent(ev);
-    }
-
-    @Override
-    public boolean onTouchEvent(MotionEvent ev) {
-        if (DEBUG) Log.v(TAG, "onTouchEvent()");
-        if (DEBUG) logLayoutTransition();
-
-        return mSwipeHelper.onTouchEvent(ev) ||
-                super.onTouchEvent(ev);
-    }
-
-    public boolean canChildBeDismissed(View v) {
-        final View veto = v.findViewById(R.id.veto);
-        return (veto != null && veto.getVisibility() != View.GONE);
-    }
-
-    public boolean canChildBeExpanded(View v) {
-        return v instanceof ExpandableNotificationRow
-                && ((ExpandableNotificationRow) v).isExpandable();
-    }
-
-    public void setUserExpandedChild(View v, boolean userExpanded) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setUserExpanded(userExpanded);
-        }
-    }
-
-    public void setUserLockedChild(View v, boolean userLocked) {
-        if (v instanceof ExpandableNotificationRow) {
-            ((ExpandableNotificationRow) v).setUserLocked(userLocked);
-        }
-    }
-
-    public void onChildDismissed(View v) {
-        if (DEBUG) Log.v(TAG, "onChildDismissed: " + v + " mRemoveViews=" + mRemoveViews);
-        final View veto = v.findViewById(R.id.veto);
-        if (veto != null && veto.getVisibility() != View.GONE && mRemoveViews) {
-            veto.performClick();
-        }
-    }
-
-    public void onBeginDrag(View v) {
-        // We need to prevent the surrounding ScrollView from intercepting us now;
-        // the scroll position will be locked while we swipe
-        requestDisallowInterceptTouchEvent(true);
-    }
-
-    public void onDragCancelled(View v) {
-    }
-
-    public View getChildAtPosition(MotionEvent ev) {
-        return getChildAtPosition(ev.getX(), ev.getY());
-    }
-
-    public View getChildAtRawPosition(float touchX, float touchY) {
-        int[] location = new int[2];
-        getLocationOnScreen(location);
-        return getChildAtPosition((float) (touchX - location[0]), (float) (touchY - location[1]));
-    }
-
-    public View getChildAtPosition(float touchX, float touchY) {
-        // find the view under the pointer, accounting for GONE views
-        final int count = getChildCount();
-        int y = 0;
-        int childIdx = 0;
-        View slidingChild;
-        for (; childIdx < count; childIdx++) {
-            slidingChild = getChildAt(childIdx);
-            if (slidingChild.getVisibility() == GONE) {
-                continue;
-            }
-            y += slidingChild.getMeasuredHeight();
-            if (touchY < y) return slidingChild;
-        }
-        return null;
-    }
-
-    public View getChildContentView(View v) {
-        return v;
-    }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-        float densityScale = getResources().getDisplayMetrics().density;
-        mSwipeHelper.setDensityScale(densityScale);
-        float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
-        mSwipeHelper.setPagingTouchSlop(pagingTouchSlop);
-    }
-
-
-    /**
-     * Sets a flag to tell us whether to actually remove views. Removal is delayed by setting this
-     * to false during some animations to smooth out performance. Callers should restore the
-     * flag to true after the animation is done, and then they should make sure that the views
-     * get removed properly.
-     */
-    public void setViewRemoval(boolean removeViews) {
-        if (DEBUG) Log.v(TAG, "setViewRemoval: " + removeViews);
-        mRemoveViews = removeViews;
-    }
-
-    // Suppress layout transitions for a little while.
-    public void setLayoutTransitionsEnabled(boolean b) {
-        if (b) {
-            setLayoutTransition(mRealLayoutTransition);
-        } else {
-            if (mRealLayoutTransition.isRunning()) {
-                mRealLayoutTransition.cancel();
-            }
-            setLayoutTransition(null);
-        }
-    }
-
-    public void dismissRowAnimated(View child) {
-        dismissRowAnimated(child, 0);
-    }
-
-    public void dismissRowAnimated(View child, int vel) {
-        mSwipeHelper.dismissChild(child, vel);
-    }
-
-    @Override
-    public void onFinishInflate() {
-        super.onFinishInflate();
-        if (DEBUG) setWillNotDraw(false);
-    }
-
-    @Override
-    public void onDraw(android.graphics.Canvas c) {
-        super.onDraw(c);
-        if (DEBUG) logLayoutTransition();
-        if (DEBUG) {
-            //Log.d(TAG, "onDraw: canvas height: " + c.getHeight() + "px; measured height: "
-            //        + getMeasuredHeight() + "px");
-            c.save();
-            c.clipRect(6, 6, c.getWidth() - 6, getMeasuredHeight() - 6,
-                    android.graphics.Region.Op.DIFFERENCE);
-            c.drawColor(0xFFFF8000);
-            c.restore();
-        }
-    }
-
-    @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        if (mOnSizeChangedListener != null) {
-            mOnSizeChangedListener.onSizeChanged(this, w, h, oldw, oldh);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index e2d6c5b..a364b416 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -20,7 +20,6 @@
 import android.content.res.Configuration;
 
 import android.graphics.Canvas;
-import android.graphics.Outline;
 import android.graphics.Paint;
 
 import android.util.AttributeSet;
@@ -31,20 +30,26 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
+import android.view.animation.AnimationUtils;
 import android.widget.OverScroller;
 
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
 import com.android.systemui.SwipeHelper;
 import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.ExpandableView;
 import com.android.systemui.statusbar.stack.StackScrollState.ViewState;
 import com.android.systemui.statusbar.policy.ScrollAdapter;
 
+import java.util.ArrayList;
+
 /**
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
 public class NotificationStackScrollLayout extends ViewGroup
-        implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter {
+        implements SwipeHelper.Callback, ExpandHelper.Callback, ScrollAdapter,
+        ExpandableView.OnHeightChangedListener {
 
     private static final String TAG = "NotificationStackScrollLayout";
     private static final boolean DEBUG = false;
@@ -55,7 +60,7 @@
     private static final int INVALID_POINTER = -1;
 
     private SwipeHelper mSwipeHelper;
-    private boolean mSwipingInProgress = true;
+    private boolean mSwipingInProgress;
     private int mCurrentStackHeight = Integer.MAX_VALUE;
     private int mOwnScrollY;
     private int mMaxLayoutHeight;
@@ -73,12 +78,13 @@
 
     private int mSidePaddings;
     private Paint mDebugPaint;
-    private int mBackgroundRoundedRectCornerRadius;
     private int mContentHeight;
     private int mCollapsedSize;
     private int mBottomStackPeekSize;
     private int mEmptyMarginBottom;
     private int mPaddingBetweenElements;
+    private int mTopPadding;
+    private boolean mListenForHeightChanges = true;
 
     /**
      * The algorithm which calculates the properties for our children
@@ -88,9 +94,28 @@
     /**
      * The current State this Layout is in
      */
-    private final StackScrollState mCurrentStackScrollState = new StackScrollState(this);
-    
+    private StackScrollState mCurrentStackScrollState = new StackScrollState(this);
+    private ArrayList<View> mChildrenToAddAnimated = new ArrayList<View>();
+    private ArrayList<View> mChildrenToRemoveAnimated = new ArrayList<View>();
+    private ArrayList<ChildHierarchyChangeEvent> mAnimationEvents
+            = new ArrayList<ChildHierarchyChangeEvent>();
+    private ArrayList<View> mSwipedOutViews = new ArrayList<View>();
+    private final StackStateAnimator mStateAnimator = new StackStateAnimator(this);
+
     private OnChildLocationsChangedListener mListener;
+    private ExpandableView.OnHeightChangedListener mOnHeightChangedListener;
+    private boolean mChildHierarchyDirty;
+    private boolean mIsExpanded = true;
+    private ViewTreeObserver.OnPreDrawListener mAfterLayoutPreDrawListener
+            = new ViewTreeObserver.OnPreDrawListener() {
+        @Override
+        public boolean onPreDraw() {
+            updateScrollPositionIfNecessary();
+            updateChildren();
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            return true;
+        }
+    };
 
     public NotificationStackScrollLayout(Context context) {
         this(context, null);
@@ -145,17 +170,14 @@
 
         mSidePaddings = context.getResources()
                 .getDimensionPixelSize(R.dimen.notification_side_padding);
-        mBackgroundRoundedRectCornerRadius = context.getResources()
-                .getDimensionPixelSize(
-                        com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
         mCollapsedSize = context.getResources()
-                .getDimensionPixelSize(R.dimen.notification_row_min_height);
+                .getDimensionPixelSize(R.dimen.notification_min_height);
         mBottomStackPeekSize = context.getResources()
                 .getDimensionPixelSize(R.dimen.bottom_stack_peek_amount);
         mEmptyMarginBottom = context.getResources().getDimensionPixelSize(
                 R.dimen.notification_stack_margin_bottom);
-        // currently the padding is in the elements themself
-        mPaddingBetweenElements = 0;
+        mPaddingBetweenElements = context.getResources()
+                .getDimensionPixelSize(R.dimen.notification_padding);
         mStackScrollAlgorithm = new StackScrollAlgorithm(context);
     }
 
@@ -177,18 +199,14 @@
             View child = getChildAt(i);
             float width = child.getMeasuredWidth();
             float height = child.getMeasuredHeight();
-            int oldWidth = child.getWidth();
-            int oldHeight = child.getHeight();
             child.layout((int) (centerX - width / 2.0f),
                     0,
                     (int) (centerX + width / 2.0f),
                     (int) height);
-            updateChildOutline(child, width, height, oldWidth, oldHeight);
         }
         setMaxLayoutHeight(getHeight() - mEmptyMarginBottom);
-        updateScrollPositionIfNecessary();
-        updateChildren();
         updateContentHeight();
+        getViewTreeObserver().addOnPreDrawListener(mAfterLayoutPreDrawListener);
     }
 
     public void setChildLocationsChangedListener(OnChildLocationsChangedListener listener) {
@@ -211,11 +229,31 @@
 
     private void setMaxLayoutHeight(int maxLayoutHeight) {
         mMaxLayoutHeight = maxLayoutHeight;
-        updateAlgorithmHeight();
+        updateAlgorithmHeightAndPadding();
     }
 
-    private void updateAlgorithmHeight() {
+    private void updateAlgorithmHeightAndPadding() {
         mStackScrollAlgorithm.setLayoutHeight(getLayoutHeight());
+        mStackScrollAlgorithm.setTopPadding(mTopPadding);
+    }
+
+    /**
+     * @return whether the height of the layout needs to be adapted, in order to ensure that the
+     *         last child is not in the bottom stack.
+     */
+    private boolean needsHeightAdaption() {
+        View lastChild = getLastChildNotGone();
+        View firstChild = getFirstChildNotGone();
+        boolean isLastChildExpanded = isViewExpanded(lastChild);
+        return isLastChildExpanded && lastChild != firstChild;
+    }
+
+    private boolean isViewExpanded(View view) {
+        if (view != null) {
+            ExpandableView expandView = (ExpandableView) view;
+            return expandView.getActualHeight() > mCollapsedSize;
+        }
+        return false;
     }
 
     /**
@@ -223,46 +261,20 @@
      * modifications to {@link #mOwnScrollY} are performed to reflect it in the view layout.
      */
     private void updateChildren() {
-        if (!isCurrentlyAnimating()) {
-            mCurrentStackScrollState.setScrollY(mOwnScrollY);
-            mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
-            mCurrentStackScrollState.apply();
-            mOwnScrollY = mCurrentStackScrollState.getScrollY();
+        mCurrentStackScrollState.setScrollY(mOwnScrollY);
+        mStackScrollAlgorithm.getStackScrollState(mCurrentStackScrollState);
+        if (!isCurrentlyAnimating() && !mChildHierarchyDirty) {
+            applyCurrentState();
             if (mListener != null) {
                 mListener.onChildLocationsChanged(this);
             }
         } else {
-            // TODO: handle animation
+            startAnimationToState(mCurrentStackScrollState);
         }
     }
 
     private boolean isCurrentlyAnimating() {
-        return false;
-    }
-
-    private void updateChildOutline(View child,
-                                    float width,
-                                    float height,
-                                    int oldWidth,
-                                    int oldHeight) {
-        // The children currently have paddings inside themselfs because of the expansion
-        // visualization. In order for the shadows to work correctly we have to set the correct
-        // outline.
-        View container = child.findViewById(R.id.container);
-        if (container != null && (oldWidth != width || oldHeight != height)) {
-            Outline outline = getOutlineForSize(container.getLeft(),
-                    container.getTop(),
-                    container.getWidth(),
-                    container.getHeight());
-            child.setOutline(outline);
-        }
-    }
-
-    private Outline getOutlineForSize(int leftInset, int topInset, int width, int height) {
-        Outline result = new Outline();
-        result.setRoundRect(leftInset, topInset, leftInset + width, topInset + height,
-                mBackgroundRoundedRectCornerRadius);
-        return result;
+        return mStateAnimator.isRunning();
     }
 
     private void updateScrollPositionIfNecessary() {
@@ -272,10 +284,52 @@
         }
     }
 
-    public void setCurrentStackHeight(int currentStackHeight) {
-        this.mCurrentStackHeight = currentStackHeight;
-        updateAlgorithmHeight();
-        updateChildren();
+    public int getTopPadding() {
+        return mTopPadding;
+    }
+
+    public void setTopPadding(int topPadding) {
+        if (mTopPadding != topPadding) {
+            mTopPadding = topPadding;
+            updateAlgorithmHeightAndPadding();
+            updateContentHeight();
+            updateChildren();
+        }
+    }
+
+    /**
+     * Update the height of the stack to a new height.
+     *
+     * @param height the new height of the stack
+     */
+    public void setStackHeight(float height) {
+        setIsExpanded(height > 0.0f);
+        int newStackHeight = (int) height;
+        int itemHeight = getItemHeight();
+        int bottomStackPeekSize = mBottomStackPeekSize;
+        int minStackHeight = itemHeight + bottomStackPeekSize;
+        int stackHeight;
+        if (newStackHeight - mTopPadding >= minStackHeight) {
+            setTranslationY(0);
+            stackHeight = newStackHeight;
+        } else {
+
+            // We did not reach the position yet where we actually start growing,
+            // so we translate the stack upwards.
+            int translationY = (newStackHeight - minStackHeight);
+            // A slight parallax effect is introduced in order for the stack to catch up with
+            // the top card.
+            float partiallyThere = (float) (newStackHeight - mTopPadding) / minStackHeight;
+            partiallyThere = Math.max(0, partiallyThere);
+            translationY += (1 - partiallyThere) * bottomStackPeekSize;
+            setTranslationY(translationY - mTopPadding);
+            stackHeight = (int) (height - (translationY - mTopPadding));
+        }
+        if (stackHeight != mCurrentStackHeight) {
+            mCurrentStackHeight = stackHeight;
+            updateAlgorithmHeightAndPadding();
+            updateChildren();
+        }
     }
 
     /**
@@ -284,7 +338,7 @@
      *
      * @return either the layout height or the externally defined height, whichever is smaller
      */
-    private float getLayoutHeight() {
+    private int getLayoutHeight() {
         return Math.min(mMaxLayoutHeight, mCurrentStackHeight);
     }
 
@@ -307,6 +361,7 @@
             veto.performClick();
         }
         setSwipingInProgress(false);
+        mSwipedOutViews.add(v);
     }
 
     public void onBeginDrag(View v) {
@@ -331,12 +386,12 @@
         // find the view under the pointer, accounting for GONE views
         final int count = getChildCount();
         for (int childIdx = 0; childIdx < count; childIdx++) {
-            View slidingChild = getChildAt(childIdx);
+            ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
             if (slidingChild.getVisibility() == GONE) {
                 continue;
             }
             float top = slidingChild.getTranslationY();
-            float bottom = top + slidingChild.getMeasuredHeight();
+            float bottom = top + slidingChild.getActualHeight();
             int left = slidingChild.getLeft();
             int right = slidingChild.getRight();
 
@@ -640,14 +695,63 @@
 
     private int getScrollRange() {
         int scrollRange = 0;
-        if (getChildCount() > 0) {
+        ExpandableView firstChild = (ExpandableView) getFirstChildNotGone();
+        if (firstChild != null) {
             int contentHeight = getContentHeight();
-            scrollRange = Math.max(0,
-                    contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+            int firstChildMaxExpandHeight = getMaxExpandHeight(firstChild);
+
+            scrollRange = Math.max(0, contentHeight - mMaxLayoutHeight + mBottomStackPeekSize);
+            if (scrollRange > 0) {
+                View lastChild = getLastChildNotGone();
+                if (isViewExpanded(lastChild)) {
+                    // last child is expanded, so we have to ensure that it can exit the
+                    // bottom stack
+                    scrollRange += mCollapsedSize + mPaddingBetweenElements;
+                }
+                // We want to at least be able collapse the first item and not ending in a weird
+                // end state.
+                scrollRange = Math.max(scrollRange, firstChildMaxExpandHeight - mCollapsedSize);
+            }
         }
         return scrollRange;
     }
 
+    /**
+     * @return the first child which has visibility unequal to GONE
+     */
+    private View getFirstChildNotGone() {
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * @return the last child which has visibility unequal to GONE
+     */
+    private View getLastChildNotGone() {
+        int childCount = getChildCount();
+        for (int i = childCount - 1; i >= 0; i--) {
+            View child = getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    private int getMaxExpandHeight(View view) {
+        if (view instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) view;
+            return row.getMaximumAllowedExpandHeight();
+        }
+        return view.getHeight();
+    }
+
     private int getContentHeight() {
         return mContentHeight;
     }
@@ -656,12 +760,21 @@
         int height = 0;
         for (int i = 0; i < getChildCount(); i++) {
             View child = getChildAt(i);
-            height += child.getHeight();
-            if (i < getChildCount()-1) {
-                height += mPaddingBetweenElements;
+            if (child.getVisibility() != View.GONE) {
+                if (height != 0) {
+                    // add the padding before this element
+                    height += mPaddingBetweenElements;
+                }
+                if (child instanceof ExpandableNotificationRow) {
+                    ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+                    height += row.getMaximumAllowedExpandHeight();
+                } else if (child instanceof ExpandableView) {
+                    ExpandableView expandableView = (ExpandableView) child;
+                    height += expandableView.getActualHeight();
+                }
             }
         }
-        mContentHeight = height;
+        mContentHeight = height + mTopPadding;
     }
 
     /**
@@ -712,7 +825,118 @@
     @Override
     protected void onViewRemoved(View child) {
         super.onViewRemoved(child);
+        ((ExpandableView) child).setOnHeightChangedListener(null);
         mCurrentStackScrollState.removeViewStateForView(child);
+        mStackScrollAlgorithm.notifyChildrenChanged(this);
+        updateScrollStateForRemovedChild(child);
+        if (mIsExpanded) {
+
+            // Generate Animations
+            mChildrenToRemoveAnimated.add(child);
+            mChildHierarchyDirty = true;
+        }
+    }
+
+    /**
+     * Updates the scroll position when a child was removed
+     *
+     * @param removedChild the removed child
+     */
+    private void updateScrollStateForRemovedChild(View removedChild) {
+        int startingPosition = getPositionInLinearLayout(removedChild);
+        int childHeight = removedChild.getHeight() + mPaddingBetweenElements;
+        int endPosition = startingPosition + childHeight;
+        if (endPosition <= mOwnScrollY) {
+            // This child is fully scrolled of the top, so we have to deduct its height from the
+            // scrollPosition
+            mOwnScrollY -= childHeight;
+        } else if (startingPosition < mOwnScrollY) {
+            // This child is currently being scrolled into, set the scroll position to the start of
+            // this child
+            mOwnScrollY = startingPosition;
+        }
+    }
+
+    private int getPositionInLinearLayout(View requestedChild) {
+        int position = 0;
+        for (int i = 0; i < getChildCount(); i++) {
+            View child = getChildAt(i);
+            if (child == requestedChild) {
+                return position;
+            }
+            if (child.getVisibility() != View.GONE) {
+                position += child.getHeight();
+                if (i < getChildCount()-1) {
+                    position += mPaddingBetweenElements;
+                }
+            }
+        }
+        return 0;
+    }
+
+    @Override
+    protected void onViewAdded(View child) {
+        super.onViewAdded(child);
+        mStackScrollAlgorithm.notifyChildrenChanged(this);
+        ((ExpandableView) child).setOnHeightChangedListener(this);
+        if (child.getVisibility() != View.GONE) {
+            generateAddAnimation(child);
+        }
+    }
+
+    public void generateAddAnimation(View child) {
+        if (mIsExpanded) {
+
+            // Generate Animations
+            mChildrenToAddAnimated.add(child);
+            mChildHierarchyDirty = true;
+        }
+    }
+
+    /**
+     * Change the position of child to a new location
+     *
+     * @param child the view to change the position for
+     * @param newIndex the new index
+     */
+    public void changeViewPosition(View child, int newIndex) {
+        if (child != null && child.getParent() == this) {
+            // TODO: handle this
+        }
+    }
+
+    private void startAnimationToState(StackScrollState finalState) {
+        if (mChildHierarchyDirty) {
+            generateChildHierarchyEvents();
+            mChildHierarchyDirty = false;
+        }
+        mStateAnimator.startAnimationForEvents(mAnimationEvents, finalState);
+    }
+
+    private void generateChildHierarchyEvents() {
+        generateChildAdditionEvents();
+        generateChildRemovalEvents();
+        mChildHierarchyDirty = false;
+    }
+
+    private void generateChildRemovalEvents() {
+        for (View  child : mChildrenToRemoveAnimated) {
+            boolean childWasSwipedOut = mSwipedOutViews.contains(child);
+            int animationType = childWasSwipedOut
+                    ? ChildHierarchyChangeEvent.ANIMATION_TYPE_REMOVE_SWIPED_OUT
+                    : ChildHierarchyChangeEvent.ANIMATION_TYPE_REMOVE;
+            mAnimationEvents.add(new ChildHierarchyChangeEvent(child, animationType));
+        }
+        mSwipedOutViews.clear();
+        mChildrenToRemoveAnimated.clear();
+    }
+
+    private void generateChildAdditionEvents() {
+        for (View  child : mChildrenToAddAnimated) {
+            mAnimationEvents.add(new ChildHierarchyChangeEvent(child,
+                    ChildHierarchyChangeEvent.ANIMATION_TYPE_ADD));
+        }
+        mChildrenToAddAnimated.clear();
     }
 
     private boolean onInterceptTouchEventScroll(MotionEvent ev) {
@@ -855,7 +1079,55 @@
     }
 
     public int getEmptyBottomMargin() {
-        return Math.max(getHeight() - mContentHeight, 0);
+        int emptyMargin = mMaxLayoutHeight - mContentHeight;
+        if (needsHeightAdaption()) {
+            emptyMargin = emptyMargin - mCollapsedSize - mBottomStackPeekSize;
+        }
+        return Math.max(emptyMargin, 0);
+    }
+
+    public void onExpansionStarted() {
+        mStackScrollAlgorithm.onExpansionStarted(mCurrentStackScrollState);
+    }
+
+    public void onExpansionStopped() {
+        mStackScrollAlgorithm.onExpansionStopped();
+    }
+
+    private void setIsExpanded(boolean isExpanded) {
+        mIsExpanded = isExpanded;
+        mStackScrollAlgorithm.setIsExpanded(isExpanded);
+        if (!isExpanded) {
+            mOwnScrollY = 0;
+        }
+    }
+
+    @Override
+    public void onHeightChanged(ExpandableView view) {
+        if (mListenForHeightChanges && !isCurrentlyAnimating()) {
+            updateContentHeight();
+            updateScrollPositionIfNecessary();
+            if (mOnHeightChangedListener != null) {
+                mOnHeightChangedListener.onHeightChanged(view);
+            }
+            updateChildren();
+        }
+    }
+
+    public void setOnHeightChangedListener(
+            ExpandableView.OnHeightChangedListener mOnHeightChangedListener) {
+        this.mOnHeightChangedListener = mOnHeightChangedListener;
+    }
+
+    public void onChildAnimationFinished() {
+        applyCurrentState();
+        mAnimationEvents.clear();
+    }
+
+    private void applyCurrentState() {
+        mListenForHeightChanges = false;
+        mCurrentStackScrollState.apply();
+        mListenForHeightChanges = true;
     }
 
     /**
@@ -864,4 +1136,21 @@
     public interface OnChildLocationsChangedListener {
         public void onChildLocationsChanged(NotificationStackScrollLayout stackScrollLayout);
     }
+
+    static class ChildHierarchyChangeEvent {
+
+        static int ANIMATION_TYPE_ADD = 1;
+        static int ANIMATION_TYPE_REMOVE = 2;
+        static int ANIMATION_TYPE_REMOVE_SWIPED_OUT = 3;
+        final long eventStartTime;
+        final View changingView;
+        final int animationType;
+
+        ChildHierarchyChangeEvent(View view, int type) {
+            eventStartTime = AnimationUtils.currentAnimationTimeMillis();
+            changingView = view;
+            animationType = type;
+        }
+    }
+
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
index 4745f3b..42edbf3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollAlgorithm.java
@@ -20,7 +20,12 @@
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
+
 import com.android.systemui.R;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.ExpandableView;
+
+import java.util.ArrayList;
 
 /**
  * The Algorithm of the {@link com.android.systemui.statusbar.stack
@@ -44,19 +49,28 @@
     private StackIndentationFunctor mTopStackIndentationFunctor;
     private StackIndentationFunctor mBottomStackIndentationFunctor;
 
-    private float mLayoutHeight;
+    private int mLayoutHeight;
+
+    /** mLayoutHeight - mTopPadding */
+    private int mInnerHeight;
+    private int mTopPadding;
     private StackScrollAlgorithmState mTempAlgorithmState = new StackScrollAlgorithmState();
+    private boolean mIsExpansionChanging;
+    private int mFirstChildMaxHeight;
+    private boolean mIsExpanded;
+    private ExpandableView mFirstChildWhileExpanding;
+    private boolean mExpandedOnStart;
+    private int mTopStackTotalSize;
 
     public StackScrollAlgorithm(Context context) {
         initConstants(context);
     }
 
     private void initConstants(Context context) {
-
-        // currently the padding is in the elements themself
-        mPaddingBetweenElements = 0;
+        mPaddingBetweenElements = context.getResources()
+                .getDimensionPixelSize(R.dimen.notification_padding);
         mCollapsedSize = context.getResources()
-                .getDimensionPixelSize(R.dimen.notification_row_min_height);
+                .getDimensionPixelSize(R.dimen.notification_min_height);
         mTopStackPeekSize = context.getResources()
                 .getDimensionPixelSize(R.dimen.top_stack_peek_amount);
         mBottomStackPeekSize = context.getResources()
@@ -64,16 +78,16 @@
         mZDistanceBetweenElements = context.getResources()
                 .getDimensionPixelSize(R.dimen.z_distance_between_notifications);
         mZBasicHeight = (MAX_ITEMS_IN_BOTTOM_STACK + 1) * mZDistanceBetweenElements;
-
+        mTopStackTotalSize = mCollapsedSize + mPaddingBetweenElements;
         mTopStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
                 MAX_ITEMS_IN_TOP_STACK,
                 mTopStackPeekSize,
-                mCollapsedSize + mPaddingBetweenElements,
+                mTopStackTotalSize,
                 0.5f);
         mBottomStackIndentationFunctor = new PiecewiseLinearIndentationFunctor(
                 MAX_ITEMS_IN_BOTTOM_STACK,
                 mBottomStackPeekSize,
-                mBottomStackPeekSize,
+                mCollapsedSize + mBottomStackPeekSize + mPaddingBetweenElements,
                 0.5f);
     }
 
@@ -86,12 +100,15 @@
         // First we reset the view states to their default values.
         resultState.resetViewStates();
 
-        // The first element is always in there so it's initialized with 1.0f;
-        algorithmState.itemsInTopStack = 1.0f;
+        algorithmState.itemsInTopStack = 0.0f;
         algorithmState.partialInTop = 0.0f;
         algorithmState.lastTopStackIndex = 0;
-        algorithmState.scrollY = resultState.getScrollY();
+        algorithmState.scrolledPixelsTop = 0;
         algorithmState.itemsInBottomStack = 0.0f;
+        algorithmState.partialInBottom = 0.0f;
+        algorithmState.scrollY = resultState.getScrollY() + mCollapsedSize;
+
+        updateVisibleChildren(resultState, algorithmState);
 
         // Phase 1:
         findNumberOfItemsInTopStackAndUpdateState(resultState, algorithmState);
@@ -101,9 +118,23 @@
 
         // Phase 3:
         updateZValuesForState(resultState, algorithmState);
+    }
 
-        // write the algorithm state to the result
-        resultState.setScrollY(algorithmState.scrollY);
+    /**
+     * Update the visible children on the state.
+     */
+    private void updateVisibleChildren(StackScrollState resultState,
+            StackScrollAlgorithmState state) {
+        ViewGroup hostView = resultState.getHostView();
+        int childCount = hostView.getChildCount();
+        state.visibleChildren.clear();
+        state.visibleChildren.ensureCapacity(childCount);
+        for (int i = 0; i < childCount; i++) {
+            ExpandableView v = (ExpandableView) hostView.getChildAt(i);
+            if (v.getVisibility() != View.GONE) {
+                state.visibleChildren.add(v);
+            }
+        }
     }
 
     /**
@@ -115,10 +146,12 @@
      */
     private void updatePositionsForState(StackScrollState resultState,
             StackScrollAlgorithmState algorithmState) {
-        float stackHeight = getLayoutHeight();
+
+        // The starting position of the bottom stack peek
+        float bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
 
         // The position where the bottom stack starts.
-        float transitioningPositionStart = stackHeight - mCollapsedSize - mBottomStackPeekSize;
+        float bottomStackStart = bottomPeekStart - mCollapsedSize;
 
         // The y coordinate of the current child.
         float currentYPosition = 0.0f;
@@ -126,101 +159,161 @@
         // How far in is the element currently transitioning into the bottom stack.
         float yPositionInScrollView = 0.0f;
 
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
         int numberOfElementsCompletelyIn = (int) algorithmState.itemsInTopStack;
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            ExpandableView child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
-            childViewState.yTranslation = currentYPosition;
             childViewState.location = StackScrollState.ViewState.LOCATION_UNKNOWN;
-            int childHeight = child.getHeight();
-            // The y position after this element
-            float nextYPosition = currentYPosition + childHeight + mPaddingBetweenElements;
+            int childHeight = getMaxAllowedChildHeight(child);
             float yPositionInScrollViewAfterElement = yPositionInScrollView
                     + childHeight
                     + mPaddingBetweenElements;
-            float scrollOffset = yPositionInScrollViewAfterElement - algorithmState.scrollY;
-            if (i < algorithmState.lastTopStackIndex) {
+            float scrollOffset = yPositionInScrollView - algorithmState.scrollY + mCollapsedSize;
+
+            if (i == algorithmState.lastTopStackIndex + 1) {
+                // Normally the position of this child is the position in the regular scrollview,
+                // but if the two stacks are very close to each other,
+                // then have have to push it even more upwards to the position of the bottom
+                // stack start.
+                currentYPosition = Math.min(scrollOffset, bottomStackStart);
+            }
+            childViewState.yTranslation = currentYPosition;
+
+            // The y position after this element
+            float nextYPosition = currentYPosition + childHeight +
+                    mPaddingBetweenElements;
+
+            if (i <= algorithmState.lastTopStackIndex) {
                 // Case 1:
                 // We are in the top Stack
-                nextYPosition = updateStateForTopStackChild(algorithmState,
-                        numberOfElementsCompletelyIn,
-                        i, childViewState);
-            } else if (i == algorithmState.lastTopStackIndex) {
+                updateStateForTopStackChild(algorithmState,
+                        numberOfElementsCompletelyIn, i, childHeight, childViewState, scrollOffset);
+                clampYTranslation(childViewState, childHeight);
+                // check if we are overlapping with the bottom stack
+                if (childViewState.yTranslation + childHeight + mPaddingBetweenElements
+                        >= bottomStackStart && !mIsExpansionChanging && i != 0) {
+                    // TODO: handle overlapping sizes with end stack better
+                    // we just collapse this element
+                    childViewState.height = mCollapsedSize;
+                }
+            } else if (nextYPosition >= bottomStackStart) {
                 // Case 2:
-                // First element of regular scrollview comes next, so the position is just the
-                // scrolling position
-                nextYPosition = Math.min(scrollOffset, transitioningPositionStart);
-                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
-            } else if (nextYPosition >= transitioningPositionStart) {
-                if (currentYPosition >= transitioningPositionStart) {
-                    // Case 3:
+                // We are in the bottom stack.
+                if (currentYPosition >= bottomStackStart) {
                     // According to the regular scroll view we are fully translated out of the
                     // bottom of the screen so we are fully in the bottom stack
-                    nextYPosition = updateStateForChildFullyInBottomStack(algorithmState,
-                            transitioningPositionStart, childViewState, childHeight);
+                    updateStateForChildFullyInBottomStack(algorithmState,
+                            bottomStackStart, childViewState, childHeight);
                 } else {
-                    // Case 4:
                     // According to the regular scroll view we are currently translating out of /
                     // into the bottom of the screen
-                    nextYPosition = updateStateForChildTransitioningInBottom(
-                            algorithmState, stackHeight, transitioningPositionStart,
-                            currentYPosition, childViewState,
-                            childHeight, nextYPosition);
+                    updateStateForChildTransitioningInBottom(algorithmState,
+                            bottomStackStart, bottomPeekStart, currentYPosition,
+                            childViewState, childHeight);
                 }
             } else {
+                // Case 3:
+                // We are in the regular scroll area.
                 childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+                clampYTranslation(childViewState, childHeight);
             }
+
             // The first card is always rendered.
             if (i == 0) {
                 childViewState.alpha = 1.0f;
+                childViewState.yTranslation = 0;
                 childViewState.location = StackScrollState.ViewState.LOCATION_FIRST_CARD;
             }
             if (childViewState.location == StackScrollState.ViewState.LOCATION_UNKNOWN) {
                 Log.wtf(LOG_TAG, "Failed to assign location for child " + i);
             }
-            nextYPosition = Math.max(0, nextYPosition);
-            currentYPosition = nextYPosition;
+            currentYPosition = childViewState.yTranslation + childHeight + mPaddingBetweenElements;
             yPositionInScrollView = yPositionInScrollViewAfterElement;
+
+            childViewState.yTranslation += mTopPadding;
         }
     }
 
-    private float updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
-            float stackHeight, float transitioningPositionStart, float currentYPosition,
-            StackScrollState.ViewState childViewState, int childHeight, float nextYPosition) {
-        float newSize = transitioningPositionStart + mCollapsedSize - currentYPosition;
-        newSize = Math.min(childHeight, newSize);
-        // Transitioning element on top of bottom stack:
+    /**
+     * Clamp the yTranslation both up and down to valid positions.
+     *
+     * @param childViewState the view state of the child
+     * @param childHeight the height of this child
+     */
+    private void clampYTranslation(StackScrollState.ViewState childViewState, int childHeight) {
+        clampPositionToBottomStackStart(childViewState, childHeight);
+        clampPositionToTopStackEnd(childViewState, childHeight);
+    }
+
+    /**
+     * Clamp the yTranslation of the child down such that its end is at most on the beginning of
+     * the bottom stack.
+     *
+     * @param childViewState the view state of the child
+     * @param childHeight the height of this child
+     */
+    private void clampPositionToBottomStackStart(StackScrollState.ViewState childViewState,
+            int childHeight) {
+        childViewState.yTranslation = Math.min(childViewState.yTranslation,
+                mInnerHeight - mBottomStackPeekSize - childHeight);
+    }
+
+    /**
+     * Clamp the yTranslation of the child up such that its end is at lest on the end of the top
+     * stack.get
+     *
+     * @param childViewState the view state of the child
+     * @param childHeight the height of this child
+     */
+    private void clampPositionToTopStackEnd(StackScrollState.ViewState childViewState,
+            int childHeight) {
+        childViewState.yTranslation = Math.max(childViewState.yTranslation,
+                mCollapsedSize - childHeight);
+    }
+
+    private int getMaxAllowedChildHeight(View child) {
+        if (child instanceof ExpandableNotificationRow) {
+            ExpandableNotificationRow row = (ExpandableNotificationRow) child;
+            return row.getMaximumAllowedExpandHeight();
+        } else if (child instanceof ExpandableView) {
+            ExpandableView expandableView = (ExpandableView) child;
+            return expandableView.getActualHeight();
+        }
+        return child == null? mCollapsedSize : child.getHeight();
+    }
+
+    private void updateStateForChildTransitioningInBottom(StackScrollAlgorithmState algorithmState,
+            float transitioningPositionStart, float bottomPeakStart, float currentYPosition,
+            StackScrollState.ViewState childViewState, int childHeight) {
+
+        // This is the transitioning element on top of bottom stack, calculate how far we are in.
         algorithmState.partialInBottom = 1.0f - (
-                (stackHeight - mBottomStackPeekSize - nextYPosition) / mCollapsedSize);
-        // Our element can be expanded, so we might even have to scroll further than
-        // mCollapsedSize
-        algorithmState.partialInBottom = Math.min(1.0f, algorithmState.partialInBottom);
-        float offset = mBottomStackIndentationFunctor.getValue(
-                algorithmState.partialInBottom);
-        nextYPosition = transitioningPositionStart + offset;
-        algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
-        // TODO: only temporarily collapse
-        if (childHeight != (int) newSize) {
-            childViewState.height = (int) newSize;
-        }
-        childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
+                (transitioningPositionStart - currentYPosition) / (childHeight +
+                        mPaddingBetweenElements));
 
-        return nextYPosition;
+        // the offset starting at the transitionPosition of the bottom stack
+        float offset = mBottomStackIndentationFunctor.getValue(algorithmState.partialInBottom);
+        algorithmState.itemsInBottomStack += algorithmState.partialInBottom;
+        childViewState.yTranslation = transitioningPositionStart + offset - childHeight
+                - mPaddingBetweenElements;
+
+        // We want at least to be at the end of the top stack when collapsing
+        clampPositionToTopStackEnd(childViewState, childHeight);
+        childViewState.location = StackScrollState.ViewState.LOCATION_MAIN_AREA;
     }
 
-    private float updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
+    private void updateStateForChildFullyInBottomStack(StackScrollAlgorithmState algorithmState,
             float transitioningPositionStart, StackScrollState.ViewState childViewState,
             int childHeight) {
 
-        float nextYPosition;
+        float currentYPosition;
         algorithmState.itemsInBottomStack += 1.0f;
         if (algorithmState.itemsInBottomStack < MAX_ITEMS_IN_BOTTOM_STACK) {
             // We are visually entering the bottom stack
-            nextYPosition = transitioningPositionStart
-                    + mBottomStackIndentationFunctor.getValue(
-                            algorithmState.itemsInBottomStack);
+            currentYPosition = transitioningPositionStart
+                    + mBottomStackIndentationFunctor.getValue(algorithmState.itemsInBottomStack)
+                    - mPaddingBetweenElements;
             childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_PEEKING;
         } else {
             // we are fully inside the stack
@@ -231,43 +324,56 @@
                 childViewState.alpha = 1.0f - algorithmState.partialInBottom;
             }
             childViewState.location = StackScrollState.ViewState.LOCATION_BOTTOM_STACK_HIDDEN;
-            nextYPosition = transitioningPositionStart + mBottomStackPeekSize;
+            currentYPosition = mInnerHeight;
         }
-        // TODO: only temporarily collapse
-        if (childHeight != mCollapsedSize) {
-            childViewState.height = mCollapsedSize;
-        }
-        return nextYPosition;
+        childViewState.yTranslation = currentYPosition - childHeight;
+        clampPositionToTopStackEnd(childViewState, childHeight);
     }
 
-    private float updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
-            int numberOfElementsCompletelyIn, int i, StackScrollState.ViewState childViewState) {
+    private void updateStateForTopStackChild(StackScrollAlgorithmState algorithmState,
+            int numberOfElementsCompletelyIn, int i, int childHeight,
+            StackScrollState.ViewState childViewState, float scrollOffset) {
 
-        float nextYPosition = 0;
 
         // First we calculate the index relative to the current stack window of size at most
         // {@link #MAX_ITEMS_IN_TOP_STACK}
-        int paddedIndex = i
+        int paddedIndex = i - 1
                 - Math.max(numberOfElementsCompletelyIn - MAX_ITEMS_IN_TOP_STACK, 0);
         if (paddedIndex >= 0) {
+
             // We are currently visually entering the top stack
-            nextYPosition = mCollapsedSize + mPaddingBetweenElements -
-                    mTopStackIndentationFunctor.getValue(
-                            algorithmState.itemsInTopStack - i - 1);
-            nextYPosition = Math.min(nextYPosition, mLayoutHeight - mCollapsedSize
-                    - mBottomStackPeekSize);
-            if (paddedIndex == 0) {
-                childViewState.alpha = 1.0f - algorithmState.partialInTop;
-                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
+            float distanceToStack = childHeight - algorithmState.scrolledPixelsTop;
+            if (i == algorithmState.lastTopStackIndex && distanceToStack > mTopStackTotalSize) {
+
+                // Child is currently translating into stack but not yet inside slow down zone.
+                // Handle it like the regular scrollview.
+                childViewState.yTranslation = scrollOffset;
             } else {
-                childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
+                // Apply stacking logic.
+                float numItemsBefore;
+                if (i == algorithmState.lastTopStackIndex) {
+                    numItemsBefore = 1.0f - (distanceToStack / mTopStackTotalSize);
+                } else {
+                    numItemsBefore = algorithmState.itemsInTopStack - i;
+                }
+                // The end position of the current child
+                float currentChildEndY = mCollapsedSize + mTopStackTotalSize -
+                        mTopStackIndentationFunctor.getValue(numItemsBefore);
+                childViewState.yTranslation = currentChildEndY - childHeight;
             }
+            childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_PEEKING;
         } else {
-            // We are hidden behind the top card and faded out, so we can hide ourselves.
-            childViewState.alpha = 0.0f;
+            if (paddedIndex == -1) {
+                childViewState.alpha = 1.0f - algorithmState.partialInTop;
+            } else {
+                // We are hidden behind the top card and faded out, so we can hide ourselves.
+                childViewState.alpha = 0.0f;
+            }
+            childViewState.yTranslation = mCollapsedSize - childHeight;
             childViewState.location = StackScrollState.ViewState.LOCATION_TOP_STACK_HIDDEN;
         }
-        return nextYPosition;
+
+
     }
 
     /**
@@ -282,22 +388,33 @@
 
         // The y Position if the element would be in a regular scrollView
         float yPositionInScrollView = 0.0f;
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
 
         // find the number of elements in the top stack.
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            ExpandableView child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
-            int childHeight = child.getHeight();
+            int childHeight = getMaxAllowedChildHeight(child);
             float yPositionInScrollViewAfterElement = yPositionInScrollView
                     + childHeight
                     + mPaddingBetweenElements;
             if (yPositionInScrollView < algorithmState.scrollY) {
-                if (yPositionInScrollViewAfterElement <= algorithmState.scrollY) {
+                if (i == 0 && algorithmState.scrollY == mCollapsedSize) {
+
+                    // The starting position of the bottom stack peek
+                    int bottomPeekStart = mInnerHeight - mBottomStackPeekSize;
+                    // Collapse and expand the first child while the shade is being expanded
+                    float maxHeight = mIsExpansionChanging && child == mFirstChildWhileExpanding
+                            ? mFirstChildMaxHeight
+                            : childHeight;
+                    childViewState.height = (int) Math.max(Math.min(bottomPeekStart, maxHeight),
+                            mCollapsedSize);
+                    algorithmState.itemsInTopStack = 1.0f;
+
+                } else if (yPositionInScrollViewAfterElement < algorithmState.scrollY) {
                     // According to the regular scroll view we are fully off screen
                     algorithmState.itemsInTopStack += 1.0f;
-                    if (childHeight != mCollapsedSize) {
+                    if (i == 0) {
                         childViewState.height = mCollapsedSize;
                     }
                 } else {
@@ -307,35 +424,27 @@
                             - mPaddingBetweenElements
                             - algorithmState.scrollY;
 
+                    if (i == 0) {
+                        newSize += mCollapsedSize;
+                    }
+
                     // How much did we scroll into this child
-                    algorithmState.partialInTop = (mCollapsedSize - newSize) / (mCollapsedSize
+                    algorithmState.scrolledPixelsTop = childHeight - newSize;
+                    algorithmState.partialInTop = (algorithmState.scrolledPixelsTop) / (childHeight
                             + mPaddingBetweenElements);
 
                     // Our element can be expanded, so this can get negative
                     algorithmState.partialInTop = Math.max(0.0f, algorithmState.partialInTop);
                     algorithmState.itemsInTopStack += algorithmState.partialInTop;
-                    // TODO: handle overlapping sizes with end stack
                     newSize = Math.max(mCollapsedSize, newSize);
-                    // TODO: only temporarily collapse
-                    if (newSize != childHeight) {
+                    if (i == 0) {
                         childViewState.height = (int) newSize;
-
-                        // We decrease scrollY by the same amount we made this child smaller.
-                        // The new scroll position is therefore the start of the element
-                        algorithmState.scrollY = (int) yPositionInScrollView;
-                        resultState.setScrollY(algorithmState.scrollY);
                     }
-                    if (childHeight > mCollapsedSize) {
-                        // If we are just resizing this child, this element is not treated to be
-                        // transitioning into the stack and therefore it is the last element in
-                        // the stack.
-                        algorithmState.lastTopStackIndex = i;
-                        break;
-                    }
+                    algorithmState.lastTopStackIndex = i;
+                    break;
                 }
             } else {
-                algorithmState.lastTopStackIndex = i;
-
+                algorithmState.lastTopStackIndex = i - 1;
                 // We are already past the stack so we can end the loop
                 break;
             }
@@ -352,10 +461,9 @@
      */
     private void updateZValuesForState(StackScrollState resultState,
             StackScrollAlgorithmState algorithmState) {
-        ViewGroup hostView = resultState.getHostView();
-        int childCount = hostView.getChildCount();
+        int childCount = algorithmState.visibleChildren.size();
         for (int i = 0; i < childCount; i++) {
-            View child = hostView.getChildAt(i);
+            View child = algorithmState.visibleChildren.get(i);
             StackScrollState.ViewState childViewState = resultState.getViewStateForView(child);
             if (i < algorithmState.itemsInTopStack) {
                 float stackIndex = algorithmState.itemsInTopStack - i;
@@ -373,12 +481,89 @@
         }
     }
 
-    public float getLayoutHeight() {
-        return mLayoutHeight;
+    public void setLayoutHeight(int layoutHeight) {
+        this.mLayoutHeight = layoutHeight;
+        updateInnerHeight();
     }
 
-    public void setLayoutHeight(float layoutHeight) {
-        this.mLayoutHeight = layoutHeight;
+    public void setTopPadding(int topPadding) {
+        mTopPadding = topPadding;
+        updateInnerHeight();
+    }
+
+    private void updateInnerHeight() {
+        mInnerHeight = mLayoutHeight - mTopPadding;
+    }
+
+    public void onExpansionStarted(StackScrollState currentState) {
+        mIsExpansionChanging = true;
+        mExpandedOnStart = mIsExpanded;
+        ViewGroup hostView = currentState.getHostView();
+        updateFirstChildHeightWhileExpanding(hostView);
+    }
+
+    private void updateFirstChildHeightWhileExpanding(ViewGroup hostView) {
+        mFirstChildWhileExpanding = (ExpandableView) findFirstVisibleChild(hostView);
+        if (mFirstChildWhileExpanding != null) {
+            if (mExpandedOnStart) {
+
+                // We are collapsing the shade, so the first child can get as most as high as the
+                // current height.
+                mFirstChildMaxHeight = mFirstChildWhileExpanding.getActualHeight();
+            } else {
+
+                // We are expanding the shade, expand it to its full height.
+                if (mFirstChildWhileExpanding.getWidth() == 0) {
+
+                    // This child was not layouted yet, wait for a layout pass
+                    mFirstChildWhileExpanding
+                            .addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
+                                @Override
+                                public void onLayoutChange(View v, int left, int top, int right,
+                                        int bottom, int oldLeft, int oldTop, int oldRight,
+                                        int oldBottom) {
+                                    if (mFirstChildWhileExpanding != null) {
+                                        mFirstChildMaxHeight = getMaxAllowedChildHeight(
+                                                mFirstChildWhileExpanding);
+                                    } else {
+                                        mFirstChildMaxHeight = 0;
+                                    }
+                                    v.removeOnLayoutChangeListener(this);
+                                }
+                            });
+                } else {
+                    mFirstChildMaxHeight = getMaxAllowedChildHeight(mFirstChildWhileExpanding);
+                }
+            }
+        } else {
+            mFirstChildMaxHeight = 0;
+        }
+    }
+
+    private View findFirstVisibleChild(ViewGroup container) {
+        int childCount = container.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = container.getChildAt(i);
+            if (child.getVisibility() != View.GONE) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    public void onExpansionStopped() {
+        mIsExpansionChanging = false;
+        mFirstChildWhileExpanding = null;
+    }
+
+    public void setIsExpanded(boolean isExpanded) {
+        this.mIsExpanded = isExpanded;
+    }
+
+    public void notifyChildrenChanged(ViewGroup hostView) {
+        if (mIsExpansionChanging) {
+            updateFirstChildHeightWhileExpanding(hostView);
+        }
     }
 
     class StackScrollAlgorithmState {
@@ -399,10 +584,12 @@
         public float partialInTop;
 
         /**
+         * The number of pixels the last child in the top stack has scrolled in to the stack
+         */
+        public float scrolledPixelsTop;
+
+        /**
          * The last item index which is in the top stack.
-         * NOTE: In the top stack the item after the transitioning element is also in the stack!
-         * This is needed to ensure a smooth transition between the y position in the regular
-         * scrollview and the one in the stack.
          */
         public int lastTopStackIndex;
 
@@ -415,6 +602,11 @@
          * how far in is the element currently transitioning into the bottom stack
          */
         public float partialInBottom;
+
+        /**
+         * The children from the host view which are not gone.
+         */
+        public final ArrayList<ExpandableView> visibleChildren = new ArrayList<ExpandableView>();
     }
 
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
index 67a1735..8c75adc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackScrollState.java
@@ -16,10 +16,14 @@
 
 package com.android.systemui.statusbar.stack;
 
+import android.graphics.Outline;
+import android.graphics.Rect;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
 
+import com.android.systemui.statusbar.ExpandableView;
+
 import java.util.HashMap;
 import java.util.Map;
 
@@ -32,8 +36,11 @@
     private static final String CHILD_NOT_FOUND_TAG = "StackScrollStateNoSuchChild";
 
     private final ViewGroup mHostView;
-    private Map<View, ViewState> mStateMap;
+    private Map<ExpandableView, ViewState> mStateMap;
     private int mScrollY;
+    private final Rect mClipRect = new Rect();
+    private int mBackgroundRoundedRectCornerRadius;
+    private final Outline mChildOutline = new Outline();
 
     public int getScrollY() {
         return mScrollY;
@@ -45,7 +52,9 @@
 
     public StackScrollState(ViewGroup hostView) {
         mHostView = hostView;
-        mStateMap = new HashMap<View, ViewState>();
+        mStateMap = new HashMap<ExpandableView, ViewState>();
+        mBackgroundRoundedRectCornerRadius = hostView.getResources().getDimensionPixelSize(
+                com.android.internal.R.dimen.notification_quantum_rounded_rect_radius);
     }
 
     public ViewGroup getHostView() {
@@ -55,19 +64,19 @@
     public void resetViewStates() {
         int numChildren = mHostView.getChildCount();
         for (int i = 0; i < numChildren; i++) {
-            View child = mHostView.getChildAt(i);
+            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
             ViewState viewState = mStateMap.get(child);
             if (viewState == null) {
                 viewState = new ViewState();
                 mStateMap.put(child, viewState);
             }
             // initialize with the default values of the view
-            viewState.height = child.getHeight();
-            viewState.alpha = 1.0f;
+            viewState.height = child.getActualHeight();
+            viewState.gone = child.getVisibility() == View.GONE;
+            viewState.alpha = 1;
         }
     }
 
-
     public ViewState getViewStateForView(View requestedView) {
         return mStateMap.get(requestedView);
     }
@@ -82,14 +91,21 @@
      */
     public void apply() {
         int numChildren = mHostView.getChildCount();
+        float previousNotificationEnd = 0;
+        float previousNotificationStart = 0;
         for (int i = 0; i < numChildren; i++) {
-            View child = mHostView.getChildAt(i);
+            ExpandableView child = (ExpandableView) mHostView.getChildAt(i);
             ViewState state = mStateMap.get(child);
-            if (state != null) {
+            if (state == null) {
+                Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
+                        "to the hostView");
+                continue;
+            }
+            if (!state.gone) {
                 float alpha = child.getAlpha();
                 float yTranslation = child.getTranslationY();
                 float zTranslation = child.getTranslationZ();
-                int height = child.getHeight();
+                int height = child.getActualHeight();
                 float newAlpha = state.alpha;
                 float newYTranslation = state.yTranslation;
                 float newZTranslation = state.zTranslation;
@@ -132,21 +148,59 @@
 
                 // apply height
                 if (height != newHeight) {
-                    applyNewHeight(child, newHeight);
+                    child.setActualHeight(newHeight);
                 }
-            } else {
-                Log.wtf(CHILD_NOT_FOUND_TAG, "No child state was found when applying this state " +
-                        "to the hostView");
+
+                // apply clipping and shadow
+                float newNotificationEnd = newYTranslation + newHeight;
+                updateChildClippingAndBackground(child, newHeight,
+                        newNotificationEnd - (previousNotificationEnd),
+                        (int) (newHeight - (previousNotificationStart - newYTranslation)));
+
+                previousNotificationStart = newYTranslation;
+                previousNotificationEnd = newNotificationEnd;
             }
         }
     }
 
-    private void applyNewHeight(View child, int newHeight) {
-        ViewGroup.LayoutParams lp = child.getLayoutParams();
-        lp.height = newHeight;
-        child.setLayoutParams(lp);
+    /**
+     * Updates the shadow outline and the clipping for a view.
+     *
+     * @param child the view to update
+     * @param realHeight the currently applied height of the view
+     * @param clipHeight the desired clip height, the rest of the view will be clipped from the top
+     * @param backgroundHeight the desired background height. The shadows of the view will be
+     *                         based on this height and the content will be clipped from the top
+     */
+    private void updateChildClippingAndBackground(ExpandableView child, int realHeight,
+            float clipHeight, int backgroundHeight) {
+        if (realHeight > clipHeight) {
+            updateChildClip(child, realHeight, clipHeight);
+        } else {
+            child.setClipBounds(null);
+        }
+        if (realHeight > backgroundHeight) {
+            child.setClipTopAmount(realHeight - backgroundHeight);
+        } else {
+            child.setClipTopAmount(0);
+        }
     }
 
+    /**
+     * Updates the clipping of a view
+     *
+     * @param child the view to update
+     * @param height the currently applied height of the view
+     * @param clipHeight the desired clip height, the rest of the view will be clipped from the top
+     */
+    private void updateChildClip(View child, int height, float clipHeight) {
+        int clipInset = (int) (height - clipHeight);
+        mClipRect.set(0,
+                clipInset,
+                child.getWidth(),
+                height);
+        child.setClipBounds(mClipRect);
+    }
 
     public static class ViewState {
 
@@ -164,6 +218,7 @@
         float yTranslation;
         float zTranslation;
         int height;
+        boolean gone;
 
         /**
          * The location this view is currently rendered at.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
new file mode 100644
index 0000000..24daa4f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.stack;
+
+import android.animation.Animator;
+import android.animation.ValueAnimator;
+import android.view.View;
+import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
+import com.android.systemui.statusbar.ExpandableView;
+
+import java.util.ArrayList;
+
+/**
+ * An stack state animator which handles animations to new StackScrollStates
+ */
+public class StackStateAnimator {
+
+    private static final int ANIMATION_DURATION = 360;
+
+    private final Interpolator mFastOutSlowInInterpolator;
+    public NotificationStackScrollLayout mHostLayout;
+    private boolean mAnimationIsRunning;
+    private ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> mHandledEvents =
+            new ArrayList<>();
+
+    public StackStateAnimator(NotificationStackScrollLayout hostLayout) {
+        mHostLayout = hostLayout;
+        mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(hostLayout.getContext(),
+                        android.R.interpolator.fast_out_slow_in);
+    }
+
+    public boolean isRunning() {
+        return mAnimationIsRunning;
+    }
+
+    public void startAnimationForEvents(
+            ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> mAnimationEvents,
+            StackScrollState finalState) {
+        int numEvents = mAnimationEvents.size();
+        if (numEvents == 0) {
+            // No events, so we don't perform any animation
+            return;
+        }
+        long lastEventStartTime = mAnimationEvents.get(numEvents - 1).eventStartTime;
+        long eventEnd = lastEventStartTime + ANIMATION_DURATION;
+        long currentTime = AnimationUtils.currentAnimationTimeMillis();
+        long newDuration = eventEnd - currentTime;
+        if (newDuration <= 0) {
+            // last event is long before this, so we don't do anything
+            return;
+        }
+        initializeAddedViewStates(mAnimationEvents, finalState);
+        int childCount = mHostLayout.getChildCount();
+        boolean isFirstAnimatingView = true;
+        for (int i = 0; i < childCount; i++) {
+            final ExpandableView child = (ExpandableView) mHostLayout.getChildAt(i);
+            StackScrollState.ViewState viewState = finalState.getViewStateForView(child);
+            if (viewState == null) {
+                continue;
+            }
+            int childVisibility = child.getVisibility();
+            boolean wasVisible = childVisibility == View.VISIBLE;
+            final float alpha = viewState.alpha;
+            if (!wasVisible && alpha != 0 && !viewState.gone) {
+                child.setVisibility(View.VISIBLE);
+            }
+
+            startPropertyAnimation(newDuration, isFirstAnimatingView, child, viewState, alpha);
+
+            // TODO: animate clipBounds
+            child.setClipBounds(null);
+            int currentHeigth = child.getActualHeight();
+            if (viewState.height != currentHeigth) {
+                startHeightAnimation(newDuration, child, viewState, currentHeigth);
+            }
+            isFirstAnimatingView = false;
+        }
+        mAnimationIsRunning = true;
+    }
+
+    private void startPropertyAnimation(long newDuration, final boolean hasFinishAction,
+            final ExpandableView child, StackScrollState.ViewState viewState, final float alpha) {
+        child.animate().setInterpolator(mFastOutSlowInInterpolator)
+                .alpha(alpha)
+                .translationY(viewState.yTranslation)
+                .translationZ(viewState.zTranslation)
+                .setDuration(newDuration)
+                .withEndAction(new Runnable() {
+                    @Override
+                    public void run() {
+                        mAnimationIsRunning = false;
+                        if (hasFinishAction) {
+                            mHandledEvents.clear();
+                            mHostLayout.onChildAnimationFinished();
+                        }
+                        if (alpha == 0) {
+                            child.setVisibility(View.INVISIBLE);
+                        }
+                    }
+                });
+    }
+
+    private void startHeightAnimation(long newDuration, final ExpandableView child,
+            StackScrollState.ViewState viewState, int currentHeigth) {
+        ValueAnimator heightAnimator = ValueAnimator.ofInt(currentHeigth, viewState.height);
+        heightAnimator.setInterpolator(mFastOutSlowInInterpolator);
+        heightAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+            @Override
+            public void onAnimationUpdate(ValueAnimator animation) {
+                child.setActualHeight((int) animation.getAnimatedValue());
+            }
+        });
+        heightAnimator.setDuration(newDuration);
+        heightAnimator.start();
+    }
+
+    /**
+     * Initialize the viewStates for the added children
+     *
+     * @param animationEvents the animation events who contain the added children
+     * @param finalState the final state to animate to
+     */
+    private void initializeAddedViewStates(
+            ArrayList<NotificationStackScrollLayout.ChildHierarchyChangeEvent> animationEvents,
+            StackScrollState finalState) {
+        for (NotificationStackScrollLayout.ChildHierarchyChangeEvent event: animationEvents) {
+            View changingView = event.changingView;
+            if (event.animationType == NotificationStackScrollLayout.ChildHierarchyChangeEvent
+                    .ANIMATION_TYPE_ADD && !mHandledEvents.contains(event)) {
+
+                // This item is added, initialize it's properties.
+                StackScrollState.ViewState viewState = finalState.getViewStateForView(changingView);
+                if (viewState == null) {
+                    // The position for this child was never generated, let's continue.
+                    continue;
+                }
+                changingView.setAlpha(0);
+                changingView.setTranslationY(viewState.yTranslation);
+                changingView.setTranslationZ(viewState.zTranslation);
+                mHandledEvents.add(event);
+            }
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index dd13e31..d615542 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -22,6 +22,7 @@
 import android.view.ViewGroup.LayoutParams;
 import android.view.WindowManager;
 
+import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.statusbar.StatusBarIcon;
 import com.android.systemui.statusbar.BaseStatusBar;
 
@@ -93,10 +94,6 @@
     }
 
     @Override
-    protected void createAndAddWindows() {
-    }
-
-    @Override
     protected WindowManager.LayoutParams getSearchLayoutParams(
             LayoutParams layoutParams) {
         return null;
@@ -141,10 +138,19 @@
     }
 
     @Override
+    protected int getMaxKeyguardNotifications() {
+        return 0;
+    }
+
+    @Override
     public void animateExpandSettingsPanel() {
     }
 
     @Override
+    protected void createAndAddWindows() {
+    }
+
+    @Override
     protected void refreshLayout(int layoutDirection) {
     }
 
diff --git a/packages/services/PacProcessor/Android.mk b/packages/services/PacProcessor/Android.mk
index d9566d5..79f8a1f 100644
--- a/packages/services/PacProcessor/Android.mk
+++ b/packages/services/PacProcessor/Android.mk
@@ -25,7 +25,9 @@
 LOCAL_PACKAGE_NAME := PacProcessor
 LOCAL_CERTIFICATE := platform
 
-LOCAL_REQUIRED_MODULES := libjni_pacprocessor
+LOCAL_JNI_SHARED_LIBRARIES := libjni_pacprocessor
+
+LOCAL_MULTILIB := 32
 
 include $(BUILD_PACKAGE)
 
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index c6972b1..fec9dda 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -51,6 +51,7 @@
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
+import android.util.ArraySet;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.InputDevice;
@@ -83,6 +84,15 @@
 
     private static final boolean SHOW_SILENT_TOGGLE = true;
 
+    /* Valid settings for global actions keys.
+     * see config.xml config_globalActionList */
+    private static final String GLOBAL_ACTION_KEY_POWER = "power";
+    private static final String GLOBAL_ACTION_KEY_AIRPLANE = "airplane";
+    private static final String GLOBAL_ACTION_KEY_BUGREPORT = "bugreport";
+    private static final String GLOBAL_ACTION_KEY_SILENT = "silent";
+    private static final String GLOBAL_ACTION_KEY_USERS = "users";
+    private static final String GLOBAL_ACTION_KEY_SETTINGS = "settings";
+
     private final Context mContext;
     private final WindowManagerFuncs mWindowManagerFuncs;
     private final AudioManager mAudioManager;
@@ -235,92 +245,36 @@
         onAirplaneModeChanged();
 
         mItems = new ArrayList<Action>();
+        String[] defaultActions = mContext.getResources().getStringArray(
+                com.android.internal.R.array.config_globalActionsList);
 
-        // first: power off
-        mItems.add(
-            new SinglePressAction(
-                    com.android.internal.R.drawable.ic_lock_power_off,
-                    R.string.global_action_power_off) {
-
-                public void onPress() {
-                    // shutdown by making sure radio and power are handled accordingly.
-                    mWindowManagerFuncs.shutdown(true);
-                }
-
-                public boolean onLongPress() {
-                    mWindowManagerFuncs.rebootSafeMode(true);
-                    return true;
-                }
-
-                public boolean showDuringKeyguard() {
-                    return true;
-                }
-
-                public boolean showBeforeProvisioning() {
-                    return true;
-                }
-            });
-
-        // next: airplane mode
-        mItems.add(mAirplaneModeOn);
-
-        // next: bug report, if enabled
-        if (Settings.Global.getInt(mContext.getContentResolver(),
-                Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner()) {
-            mItems.add(
-                new SinglePressAction(com.android.internal.R.drawable.ic_lock_bugreport,
-                        R.string.global_action_bug_report) {
-
-                    public void onPress() {
-                        AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
-                        builder.setTitle(com.android.internal.R.string.bugreport_title);
-                        builder.setMessage(com.android.internal.R.string.bugreport_message);
-                        builder.setNegativeButton(com.android.internal.R.string.cancel, null);
-                        builder.setPositiveButton(com.android.internal.R.string.report,
-                                new DialogInterface.OnClickListener() {
-                                    @Override
-                                    public void onClick(DialogInterface dialog, int which) {
-                                        // Add a little delay before executing, to give the
-                                        // dialog a chance to go away before it takes a
-                                        // screenshot.
-                                        mHandler.postDelayed(new Runnable() {
-                                            @Override public void run() {
-                                                try {
-                                                    ActivityManagerNative.getDefault()
-                                                            .requestBugReport();
-                                                } catch (RemoteException e) {
-                                                }
-                                            }
-                                        }, 500);
-                                    }
-                                });
-                        AlertDialog dialog = builder.create();
-                        dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
-                        dialog.show();
-                    }
-
-                    public boolean onLongPress() {
-                        return false;
-                    }
-
-                    public boolean showDuringKeyguard() {
-                        return true;
-                    }
-
-                    public boolean showBeforeProvisioning() {
-                        return false;
-                    }
-                });
-        }
-
-        // last: silent mode
-        if (mShowSilentToggle) {
-            mItems.add(mSilentModeAction);
-        }
-
-        // one more thing: optionally add a list of users to switch to
-        if (SystemProperties.getBoolean("fw.power_user_switcher", false)) {
-            addUsersToMenu(mItems);
+        ArraySet<String> addedKeys = new ArraySet<String>();
+        for (int i = 0; i < defaultActions.length; i++) {
+            String actionKey = defaultActions[i];
+            if (addedKeys.contains(actionKey)) {
+                // If we already have added this, don't add it again.
+                continue;
+            }
+            if (GLOBAL_ACTION_KEY_POWER.equals(actionKey)) {
+                mItems.add(getPowerAction());
+            } else if (GLOBAL_ACTION_KEY_AIRPLANE.equals(actionKey)) {
+                mItems.add(mAirplaneModeOn);
+            } else if (GLOBAL_ACTION_KEY_BUGREPORT.equals(actionKey)
+                    && (Settings.Global.getInt(mContext.getContentResolver(),
+                        Settings.Global.BUGREPORT_IN_POWER_MENU, 0) != 0 && isCurrentUserOwner())) {
+                mItems.add(getBugReportAction());
+            } else if (GLOBAL_ACTION_KEY_SILENT.equals(actionKey) && mShowSilentToggle) {
+                mItems.add(mSilentModeAction);
+            } else if (GLOBAL_ACTION_KEY_USERS.equals(actionKey)
+                    && SystemProperties.getBoolean("fw.power_user_switcher", false)) {
+                addUsersToMenu(mItems);
+            } else if (GLOBAL_ACTION_KEY_SETTINGS.equals(actionKey)) {
+                mItems.add(getSettingsAction());
+            } else {
+                Log.e(TAG, "Invalid global action key " + actionKey);
+            }
+            // Add here so we don't add more than one.
+            addedKeys.add(actionKey);
         }
 
         mAdapter = new MyAdapter();
@@ -350,6 +304,105 @@
         return dialog;
     }
 
+    private Action getPowerAction() {
+        return new SinglePressAction(
+                com.android.internal.R.drawable.ic_lock_power_off,
+                R.string.global_action_power_off) {
+
+            public void onPress() {
+                // shutdown by making sure radio and power are handled accordingly.
+                mWindowManagerFuncs.shutdown(true);
+            }
+
+            public boolean onLongPress() {
+                mWindowManagerFuncs.rebootSafeMode(true);
+                return true;
+            }
+
+            public boolean showDuringKeyguard() {
+                return true;
+            }
+
+            public boolean showBeforeProvisioning() {
+                return true;
+            }
+        };
+    }
+
+    private Action getBugReportAction() {
+        return new SinglePressAction(com.android.internal.R.drawable.stat_sys_adb,
+                R.string.global_action_bug_report) {
+
+            public void onPress() {
+                AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
+                builder.setTitle(com.android.internal.R.string.bugreport_title);
+                builder.setMessage(com.android.internal.R.string.bugreport_message);
+                builder.setNegativeButton(com.android.internal.R.string.cancel, null);
+                builder.setPositiveButton(com.android.internal.R.string.report,
+                        new DialogInterface.OnClickListener() {
+                            @Override
+                            public void onClick(DialogInterface dialog, int which) {
+                                // Add a little delay before executing, to give the
+                                // dialog a chance to go away before it takes a
+                                // screenshot.
+                                mHandler.postDelayed(new Runnable() {
+                                    @Override public void run() {
+                                        try {
+                                            ActivityManagerNative.getDefault()
+                                                    .requestBugReport();
+                                        } catch (RemoteException e) {
+                                        }
+                                    }
+                                }, 500);
+                            }
+                        });
+                AlertDialog dialog = builder.create();
+                dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
+                dialog.show();
+            }
+
+            public boolean onLongPress() {
+                return false;
+            }
+
+            public boolean showDuringKeyguard() {
+                return true;
+            }
+
+            public boolean showBeforeProvisioning() {
+                return false;
+            }
+        };
+    }
+
+    private Action getSettingsAction() {
+        return new SinglePressAction(com.android.internal.R.drawable.ic_settings,
+                R.string.global_action_settings) {
+
+            @Override
+            public void onPress() {
+                Intent intent = new Intent(Settings.ACTION_SETTINGS);
+                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+                mContext.startActivity(intent);
+            }
+
+            @Override
+            public boolean onLongPress() {
+                return false;
+            }
+
+            @Override
+            public boolean showDuringKeyguard() {
+                return true;
+            }
+
+            @Override
+            public boolean showBeforeProvisioning() {
+                return false;
+            }
+        };
+    }
+
     private UserInfo getCurrentUser() {
         try {
             return ActivityManagerNative.getDefault().getCurrentUser();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 79ed866..50e2a2e 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -22,19 +22,6 @@
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 import static android.view.WindowManager.LayoutParams.*;
 
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.app.ActivityOptions;
-import android.os.Looper;
-import android.transition.Fade;
-import android.transition.Scene;
-import android.transition.Transition;
-import android.transition.TransitionInflater;
-import android.transition.TransitionManager;
-import android.transition.TransitionSet;
-import android.util.ArrayMap;
-import android.view.ViewConfiguration;
-
 import com.android.internal.R;
 import com.android.internal.view.RootViewSurfaceTaker;
 import com.android.internal.view.StandaloneActionMode;
@@ -51,6 +38,9 @@
 import com.android.internal.widget.ActionBarView;
 import com.android.internal.widget.SwipeDismissLayout;
 
+import android.animation.Animator;
+import android.animation.ObjectAnimator;
+import android.app.ActivityOptions;
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
@@ -65,11 +55,22 @@
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.ServiceManager;
+import android.transition.ChangeBounds;
+import android.transition.Explode;
+import android.transition.Fade;
+import android.transition.MoveImage;
+import android.transition.Scene;
+import android.transition.Transition;
+import android.transition.TransitionInflater;
+import android.transition.TransitionManager;
+import android.transition.TransitionSet;
 import android.util.AndroidRuntimeException;
+import android.util.ArrayMap;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.Log;
@@ -90,6 +91,7 @@
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewGroup;
 import android.view.ViewManager;
 import android.view.ViewParent;
@@ -124,16 +126,6 @@
     private final static String TAG = "PhoneWindow";
 
     private final static boolean SWEEP_OPEN_MENU = false;
-    private static final long MAX_TRANSITION_START_WAIT = 500;
-    private static final long MAX_TRANSITION_FINISH_WAIT = 1000;
-
-    private static final String KEY_SCREEN_X = "shared_element:screenX";
-    private static final String KEY_SCREEN_Y = "shared_element:screenY";
-    private static final String KEY_TRANSLATION_Z = "shared_element:translationZ";
-    private static final String KEY_WIDTH = "shared_element:width";
-    private static final String KEY_HEIGHT = "shared_element:height";
-    private static final String KEY_NAME = "shared_element:name";
-
     /**
      * Simple callback used by the context menu and its submenus. The options
      * menu submenus do not use this (their behavior is more complex).
@@ -252,12 +244,12 @@
         }
     };
 
-    private ActivityOptions mActivityOptions;
-    private SceneTransitionListener mSceneTransitionListener;
-    private boolean mAllowEnterOverlap = true;
-    private boolean mAllowExitOverlap = true;
-    private Map<String, String> mSharedElementsMap;
-    private ArrayList<View> mTransitioningViews;
+    private Transition mEnterTransition;
+    private Transition mExitTransition;
+    private Transition mSharedElementEnterTransition;
+    private Transition mSharedElementExitTransition;
+    private Boolean mAllowExitTransitionOverlap;
+    private Boolean mAllowEnterTransitionOverlap;
 
     static class WindowManagerHolder {
         static final IWindowManager sWindowManager = IWindowManager.Stub.asInterface(
@@ -410,9 +402,6 @@
     private void transitionTo(Scene scene) {
         if (mContentScene == null) {
             scene.enter();
-            if (mActivityOptions != null) {
-                new EnterScene().start();
-            }
         } else {
             mTransitionManager.transitionTo(scene);
         }
@@ -3307,20 +3296,55 @@
 
             // Only inflate or create a new TransitionManager if the caller hasn't
             // already set a custom one.
-            if (hasFeature(FEATURE_CONTENT_TRANSITIONS) && mTransitionManager == null) {
-                final int transitionRes = getWindowStyle().getResourceId(
-                        com.android.internal.R.styleable.Window_windowContentTransitionManager, 0);
-                if (transitionRes != 0) {
-                    final TransitionInflater inflater = TransitionInflater.from(getContext());
-                    mTransitionManager = inflater.inflateTransitionManager(transitionRes,
-                            mContentParent);
-                } else {
-                    mTransitionManager = new TransitionManager();
+            if (hasFeature(FEATURE_CONTENT_TRANSITIONS)) {
+                if (mTransitionManager == null) {
+                    final int transitionRes = getWindowStyle().getResourceId(
+                            com.android.internal.R.styleable.Window_windowContentTransitionManager,
+                            0);
+                    if (transitionRes != 0) {
+                        final TransitionInflater inflater = TransitionInflater.from(getContext());
+                        mTransitionManager = inflater.inflateTransitionManager(transitionRes,
+                                mContentParent);
+                    } else {
+                        mTransitionManager = new TransitionManager();
+                    }
+                }
+
+                mEnterTransition = getTransition(mEnterTransition,
+                        com.android.internal.R.styleable.Window_windowEnterTransition);
+                mExitTransition = getTransition(mExitTransition,
+                        com.android.internal.R.styleable.Window_windowExitTransition);
+                mSharedElementEnterTransition = getTransition(mSharedElementEnterTransition,
+                        com.android.internal.R.styleable.Window_windowSharedElementEnterTransition);
+                mSharedElementExitTransition = getTransition(mSharedElementExitTransition,
+                        com.android.internal.R.styleable.Window_windowSharedElementExitTransition);
+                if (mAllowEnterTransitionOverlap == null) {
+                    mAllowEnterTransitionOverlap = getWindowStyle().getBoolean(
+                            com.android.internal.R.styleable.
+                                    Window_windowAllowEnterTransitionOverlap, true);
+                }
+                if (mAllowExitTransitionOverlap == null) {
+                    mAllowExitTransitionOverlap = getWindowStyle().getBoolean(
+                            com.android.internal.R.styleable.
+                                    Window_windowAllowExitTransitionOverlap, true);
                 }
             }
         }
     }
 
+    private Transition getTransition(Transition currentValue, int id) {
+        if (currentValue != null) {
+            return currentValue;
+        }
+        int transitionId = getWindowStyle().getResourceId(id, -1);
+        Transition transition = null;
+        if (transitionId != -1 && transitionId != com.android.internal.R.transition.no_transition) {
+            TransitionInflater inflater = TransitionInflater.from(getContext());
+            transition = inflater.inflateTransition(transitionId);
+        }
+        return transition;
+    }
+
     private Drawable loadImageURI(Uri uri) {
         try {
             final Context context = getContext();
@@ -3549,13 +3573,14 @@
         });
         swipeDismiss.setOnSwipeProgressChangedListener(
                 new SwipeDismissLayout.OnSwipeProgressChangedListener() {
+                    private static final float ALPHA_DECREASE = 0.5f;
                     private boolean mIsTranslucent = false;
-
                     @Override
                     public void onSwipeProgressChanged(
                             SwipeDismissLayout layout, float progress, float translate) {
                         WindowManager.LayoutParams newParams = getAttributes();
                         newParams.x = (int) translate;
+                        newParams.alpha = 1 - (progress * ALPHA_DECREASE);
                         setAttributes(newParams);
 
                         int flags = 0;
@@ -3571,6 +3596,7 @@
                     public void onSwipeCancelled(SwipeDismissLayout layout) {
                         WindowManager.LayoutParams newParams = getAttributes();
                         newParams.x = 0;
+                        newParams.alpha = 1;
                         setAttributes(newParams);
                         setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN | FLAG_LAYOUT_NO_LIMITS);
                     }
@@ -3649,6 +3675,66 @@
                 com.android.internal.R.styleable.Window_windowIsTranslucent, 0), false);
     }
 
+    @Override
+    public void setEnterTransition(Transition enterTransition) {
+        mEnterTransition = enterTransition;
+    }
+
+    @Override
+    public void setExitTransition(Transition exitTransition) {
+        mExitTransition = exitTransition;
+    }
+
+    @Override
+    public void setSharedElementEnterTransition(Transition sharedElementEnterTransition) {
+        mSharedElementEnterTransition = sharedElementEnterTransition;
+    }
+
+    @Override
+    public void setSharedElementExitTransition(Transition sharedElementExitTransition) {
+        mSharedElementExitTransition = sharedElementExitTransition;
+    }
+
+    @Override
+    public Transition getEnterTransition() {
+        return mEnterTransition;
+    }
+
+    @Override
+    public Transition getExitTransition() {
+        return mExitTransition;
+    }
+
+    @Override
+    public Transition getSharedElementEnterTransition() {
+        return mSharedElementEnterTransition;
+    }
+
+    @Override
+    public Transition getSharedElementExitTransition() {
+        return mSharedElementExitTransition;
+    }
+
+    @Override
+    public void setAllowEnterTransitionOverlap(boolean allow) {
+        mAllowEnterTransitionOverlap = allow;
+    }
+
+    @Override
+    public boolean getAllowEnterTransitionOverlap() {
+        return (mAllowEnterTransitionOverlap == null) ? true : mAllowEnterTransitionOverlap;
+    }
+
+    @Override
+    public void setAllowExitTransitionOverlap(boolean allowExitTransitionOverlap) {
+        mAllowExitTransitionOverlap = allowExitTransitionOverlap;
+    }
+
+    @Override
+    public boolean getAllowExitTransitionOverlap() {
+        return (mAllowExitTransitionOverlap == null) ? true : mAllowExitTransitionOverlap;
+    }
+
     private static final class DrawableFeatureState {
         DrawableFeatureState(int _featureId) {
             featureId = _featureId;
@@ -4082,670 +4168,4 @@
     void sendCloseSystemWindows(String reason) {
         PhoneWindowManager.sendCloseSystemWindows(getContext(), reason);
     }
-
-    @Override
-    public void setTransitionOptions(Bundle options, SceneTransitionListener listener) {
-        mSceneTransitionListener = listener;
-        ActivityOptions activityOptions = null;
-        if (options != null) {
-            activityOptions = new ActivityOptions(options);
-            if (activityOptions.getAnimationType() != ActivityOptions.ANIM_SCENE_TRANSITION) {
-                activityOptions = null;
-            }
-        }
-        mActivityOptions = activityOptions;
-    }
-
-    @Override
-    public void setAllowOverlappingEnterTransition(boolean allow) {
-        mAllowEnterOverlap = allow;
-    }
-
-    @Override
-    public void setAllowOverlappingExitTransition(boolean allow) {
-        mAllowExitOverlap = allow;
-    }
-
-    @Override
-    public void mapTransitionTargets(Map<String, String> sharedElementNames) {
-        mSharedElementsMap = sharedElementNames;
-    }
-
-    @Override
-    public void restoreViewVisibilityAfterTransitionToCallee() {
-        if (mTransitioningViews != null) {
-            setViewVisibility(mTransitioningViews, View.VISIBLE);
-        }
-    }
-
-    @Override
-    public void startExitTransitionToCaller(final Runnable onTransitionEnd) {
-        Transition transition;
-        if (mContentScene == null || mTransitionManager == null || mActivityOptions == null
-                || (transition = mTransitionManager.getEnterTransition(mContentScene)) == null) {
-            onTransitionEnd.run();
-            return;
-        }
-        if (mAllowExitOverlap) {
-            TransitionSet transitionSet = new TransitionSet();
-            transitionSet.addTransition(transition);
-            Fade fade = new Fade();
-            transitionSet.addTransition(fade);
-            transition = transitionSet;
-        }
-
-        final ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
-        mapSharedElements(sharedElements);
-        final Bundle sharedElementArgs = new Bundle();
-        captureTerminalSharedElementState(sharedElements, sharedElementArgs);
-
-        final ArrayList<View> transitioningViews = new ArrayList<View>();
-        mDecor.captureTransitioningViews(transitioningViews);
-        transitioningViews.removeAll(sharedElements.values());
-
-        mSceneTransitionListener.convertToTranslucent();
-        transition = transition.clone();
-        Rect epicenter = calcEpicenter(sharedElements, mActivityOptions.getSharedElementNames());
-        transition.setEpicenterCallback(new FixedEpicenterCallback(epicenter));
-        ExitSceneBack exitScene =
-                new ExitSceneBack(onTransitionEnd, sharedElementArgs, sharedElements.values());
-        exitScene.start(transition);
-        mTransitionManager.beginDelayedTransition(mDecor, transition);
-        setViewVisibility(transitioningViews, View.INVISIBLE);
-    }
-
-    @Override
-    public Bundle startExitTransitionToCallee(Bundle options) {
-        if (mContentScene == null) {
-            return null;
-        }
-        Transition transition = mTransitionManager.getExitTransition(mContentScene);
-        if (transition == null) {
-            return null;
-        }
-
-        ActivityOptions activityOptions = new ActivityOptions(options);
-        ArrayMap<String, View> sharedElements = findSharedElements(activityOptions);
-
-        // Find exiting Views and shared elements
-        ArrayList<View> transitioningViews = captureTransitioningViews(sharedElements.values());
-
-        Transition exitTransition = addTransitionTargets(transition,
-                transitioningViews, true);
-        Transition sharedElementTransition = addTransitionTargets(transition,
-                transitioningViews, false);
-
-        // transitionSet is the total exit transition, including hero animation.
-        TransitionSet transitionSet = new TransitionSet();
-        transitionSet.addTransition(exitTransition);
-        transitionSet.addTransition(sharedElementTransition);
-
-        Rect epicenter = calcEpicenter(sharedElements, activityOptions.getSharedElementNames());
-        FixedEpicenterCallback epicenterCallback = new FixedEpicenterCallback(epicenter);
-        transitionSet.setEpicenterCallback(epicenterCallback);
-
-        updateExitActivityOptions(activityOptions, sharedElements,
-                sharedElementTransition, transitioningViews, exitTransition, epicenterCallback);
-
-        // Start exiting the Views that need to exit
-        TransitionManager.beginDelayedTransition(mDecor, transitionSet);
-        setViewVisibility(transitioningViews, View.INVISIBLE);
-
-        return activityOptions.toBundle();
-    }
-
-    private ArrayList<View> captureTransitioningViews(Collection<View> sharedElements) {
-        mTransitioningViews = new ArrayList<View>();
-        mDecor.captureTransitioningViews(mTransitioningViews);
-        ArrayList<View> transitioningViews = (ArrayList<View>) mTransitioningViews.clone();
-        transitioningViews.removeAll(sharedElements);
-        return transitioningViews;
-    }
-
-    private ArrayMap<String, View> findSharedElements(ActivityOptions activityOptions) {
-        ArrayMap<String, View> sharedElements = new ArrayMap<String, View>();
-        mDecor.findSharedElements(sharedElements);
-        ArrayList<String> localNames = activityOptions.getLocalElementNames();
-        sharedElements.keySet().retainAll(localNames);
-
-        ArrayList<String> targetNames = activityOptions.getSharedElementNames();
-        for (int i = 0; i < localNames.size(); i++) {
-            String localName = localNames.get(i);
-            View sharedElement = sharedElements.remove(localName);
-            String targetName = targetNames.get(i);
-            sharedElements.put(targetName, sharedElement);
-        }
-        return sharedElements;
-    }
-
-    private static void runOnUiThread(Handler handler, Runnable runnable) {
-        if (handler.getLooper() != Looper.myLooper()) {
-            handler.post(runnable);
-        } else {
-            runnable.run();
-        }
-    }
-
-    private void updateExitActivityOptions(ActivityOptions activityOptions,
-            final Map<String, View> sharedElements, Transition sharedElementTransition,
-            final ArrayList<View> transitioningViews, Transition exitTransition,
-            final Transition.EpicenterCallback epicenterCallback) {
-
-        // Schedule capturing of the shared element state
-        final Bundle sharedElementArgs = new Bundle();
-        captureTerminalSharedElementState(sharedElements, sharedElementArgs);
-
-        ActivityOptions.SharedElementSource sharedElementSource
-                = new ActivityOptions.SharedElementSource() {
-            private Handler mHandler = new Handler();
-
-            @Override
-            public Bundle getSharedElementExitState() {
-                return sharedElementArgs;
-            }
-
-            @Override
-            public void acceptedSharedElements(final ArrayList<String> sharedElementNames) {
-                if (sharedElementNames.size() == sharedElements.size()) {
-                    return; // They were all accepted
-                }
-                runOnUiThread(mHandler, new Runnable() {
-                    @Override
-                    public void run() {
-                        Transition transition = mTransitionManager.getExitTransition(mContentScene);
-                        transition = transition.clone();
-                        transition.setEpicenterCallback(epicenterCallback);
-                        TransitionManager.beginDelayedTransition(mDecor, transition);
-                        for (String name : sharedElements.keySet()) {
-                            if (!sharedElementNames.contains(name)) {
-                                sharedElements.get(name).setVisibility(View.INVISIBLE);
-                            }
-                        }
-                        sharedElements.keySet().retainAll(sharedElementNames);
-                    }
-                });
-            }
-
-            @Override
-            public void hideSharedElements() {
-                if (sharedElements != null) {
-                    runOnUiThread(mHandler, new Runnable() {
-                        @Override
-                        public void run() {
-                            setViewVisibility(sharedElements.values(), View.INVISIBLE);
-                        }
-                    });
-                }
-            }
-
-            @Override
-            public void restore(final Bundle sharedElementState) {
-                runOnUiThread(mHandler, new Runnable() {
-                    @Override
-                    public void run() {
-                        mTransitioningViews = null;
-                        Transition transition = mTransitionManager.getExitTransition(mContentScene);
-                        transition = transition.clone();
-                        transition.setEpicenterCallback(epicenterCallback);
-                        setSharedElementState(sharedElements, sharedElementState);
-                        setViewVisibility(sharedElements.values(), View.VISIBLE);
-                        if (mSceneTransitionListener != null) {
-                            mSceneTransitionListener.sharedElementStart(transition);
-                            mDecor.getViewTreeObserver().addOnPreDrawListener(
-                                    new ViewTreeObserver.OnPreDrawListener() {
-                                        @Override
-                                        public boolean onPreDraw() {
-                                            mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
-                                            mSceneTransitionListener.sharedElementEnd();
-                                            return true;
-                                        }
-                                    });
-                        }
-                        TransitionManager.beginDelayedTransition(mDecor, transition);
-                        setViewVisibility(transitioningViews, View.VISIBLE);
-                        for (View sharedElement: sharedElements.values()) {
-                            sharedElement.requestLayout();
-                        }
-                    }
-                });
-            }
-
-            @Override
-            public void prepareForRestore() {
-                if (mTransitioningViews != null) {
-                    runOnUiThread(mHandler, new Runnable() {
-                        @Override
-                        public void run() {
-                            setViewVisibility(mTransitioningViews, View.INVISIBLE);
-                        }
-                    });
-                }
-            }
-        };
-
-        activityOptions.updateSceneTransitionAnimation(
-                exitTransition, sharedElementTransition, sharedElementSource);
-    }
-
-    private void captureTerminalSharedElementState(final Map<String, View> sharedElements,
-            final Bundle sharedElementArgs) {
-        mDecor.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
-            @Override
-            public boolean onPreDraw() {
-                mDecor.getViewTreeObserver().removeOnPreDrawListener(this);
-                int[] tempLoc = new int[2];
-                for (String name : sharedElements.keySet()) {
-                    View sharedElement = sharedElements.get(name);
-                    captureSharedElementState(sharedElement, name, sharedElementArgs, tempLoc);
-                }
-                return true;
-            }
-        });
-    }
-
-    private static Transition addTransitionTargets(Transition transition, Collection<View> views,
-            boolean add) {
-        TransitionSet set = new TransitionSet();
-        set.addTransition(transition.clone());
-        for (View view: views) {
-            if (add) {
-                set.addTarget(view);
-            } else {
-                set.excludeTarget(view, true);
-            }
-        }
-        return set;
-    }
-
-    private static void setViewVisibility(Collection<View> views, int visibility) {
-        for (View view : views) {
-            view.setVisibility(visibility);
-        }
-    }
-
-    private static void setSharedElementState(Map<String, View> sharedElements,
-            Bundle sharedElementState) {
-        int[] tempLoc = new int[2];
-        for (Map.Entry<String, View> entry: sharedElements.entrySet()) {
-            setSharedElementState(entry.getValue(), entry.getKey(), sharedElementState, tempLoc);
-        }
-    }
-
-    /**
-     * Sets the captured values from a previous
-     * {@link #captureSharedElementState(android.view.View, String, android.os.Bundle, int[])}
-     * @param view The View to apply placement changes to.
-     * @param name The shared element name given from the source Activity.
-     * @param transitionArgs A <code>Bundle</code> containing all placementinformation for named
-     *                       shared elements in the scene.
-     * @param tempLoc A temporary int[2] for capturing the current location of views.
-     */
-    private static void setSharedElementState(View view, String name, Bundle transitionArgs,
-            int[] tempLoc) {
-        Bundle sharedElementBundle = transitionArgs.getBundle(name);
-        if (sharedElementBundle == null) {
-            return;
-        }
-
-        float z = sharedElementBundle.getFloat(KEY_TRANSLATION_Z);
-        view.setTranslationZ(z);
-
-        int x = sharedElementBundle.getInt(KEY_SCREEN_X);
-        int y = sharedElementBundle.getInt(KEY_SCREEN_Y);
-        int width = sharedElementBundle.getInt(KEY_WIDTH);
-        int height = sharedElementBundle.getInt(KEY_HEIGHT);
-
-        int widthSpec = View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY);
-        int heightSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY);
-        view.measure(widthSpec, heightSpec);
-
-        ViewGroup parent = (ViewGroup) view.getParent();
-        parent.getLocationOnScreen(tempLoc);
-        int left = x - tempLoc[0];
-        int top = y - tempLoc[1];
-        int right = left + width;
-        int bottom = top + height;
-        view.layout(left, top, right, bottom);
-
-        view.requestLayout();
-    }
-
-    /**
-     * Captures placement information for Views with a shared element name for
-     * Activity Transitions.
-     * @param view The View to capture the placement information for.
-     * @param name The shared element name in the target Activity to apply the placement
-     *             information for.
-     * @param transitionArgs Bundle to store shared element placement information.
-     * @param tempLoc A temporary int[2] for capturing the current location of views.
-     * @see #setSharedElementState(android.view.View, String, android.os.Bundle, int[])
-     */
-    private static void captureSharedElementState(View view, String name, Bundle transitionArgs,
-            int[] tempLoc) {
-        Bundle sharedElementBundle = new Bundle();
-        view.getLocationOnScreen(tempLoc);
-        float scaleX = view.getScaleX();
-        sharedElementBundle.putInt(KEY_SCREEN_X, tempLoc[0]);
-        int width = Math.round(view.getWidth() * scaleX);
-        sharedElementBundle.putInt(KEY_WIDTH, width);
-
-        float scaleY = view.getScaleY();
-        sharedElementBundle.putInt(KEY_SCREEN_Y, tempLoc[1]);
-        int height= Math.round(view.getHeight() * scaleY);
-        sharedElementBundle.putInt(KEY_HEIGHT, height);
-
-        sharedElementBundle.putFloat(KEY_TRANSLATION_Z, view.getTranslationZ());
-
-        sharedElementBundle.putString(KEY_NAME, view.getSharedElementName());
-
-        transitionArgs.putBundle(name, sharedElementBundle);
-    }
-
-    private void mapSharedElements(ArrayMap<String, View> sharedElements) {
-        ArrayList<String> sharedElementNames = mActivityOptions.getSharedElementNames();
-        if (sharedElementNames != null) {
-            mDecor.findSharedElements(sharedElements);
-            if (mSharedElementsMap != null) {
-                for (Map.Entry<String, String> entry : mSharedElementsMap.entrySet()) {
-                    View sharedElement = sharedElements.remove(entry.getValue());
-                    if (sharedElement != null) {
-                        sharedElements.put(entry.getKey(), sharedElement);
-                    }
-                }
-            }
-            sharedElements.keySet().retainAll(sharedElementNames);
-        }
-    }
-
-    private static Rect calcEpicenter(ArrayMap<String, View> sharedElements,
-            ArrayList<String> sharedElementNames) {
-        if (sharedElementNames != null) {
-            for (String name: sharedElementNames) {
-                if (name.startsWith("android:")) {
-                    return null;
-                }
-                View view = sharedElements.get(name);
-                if (view != null) {
-                    int[] loc = new int[2];
-                    view.getLocationOnScreen(loc);
-                    int left = loc[0] + Math.round(view.getTranslationX());
-                    int top = loc[1] + Math.round(view.getTranslationY());
-                    int right = left + view.getWidth();
-                    int bottom = top + view.getHeight();
-                    return new Rect(left, top, right, bottom);
-                }
-            }
-        }
-        return null;
-    }
-
-    private class ExitSceneBack extends Transition.TransitionListenerAdapter implements
-            Animator.AnimatorListener {
-        private boolean mExitTransitionComplete;
-        private boolean mBackgroundFadeComplete;
-        private boolean mOnCompleteExecuted;
-        private boolean mSharedElementTransitioned;
-        private Runnable mOnComplete;
-        private Bundle mSharedElementArgs;
-        private Collection<View> mSharedElements;
-
-        public ExitSceneBack(Runnable onComplete, Bundle sharedElementArgs,
-                Collection<View> sharedElements) {
-            mOnComplete = onComplete;
-            mSharedElementArgs = sharedElementArgs;
-            mSharedElements = sharedElements;
-        }
-
-        public void start(Transition exitTransition) {
-            if (mActivityOptions != null) {
-                mActivityOptions.dispatchPrepareRestore();
-            }
-            exitTransition.addListener(this);
-            Drawable background = mDecor.getBackground();
-            if (background != null) {
-                ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 0);
-                animator.addListener(this);
-                animator.start();
-            } else {
-                mBackgroundFadeComplete = true;
-                startCalledActivityEnter();
-            }
-        }
-
-        @Override
-        public void onTransitionEnd(Transition transition) {
-            transition.removeListener(this);
-            mExitTransitionComplete = true;
-            notifyComplete();
-            if (!mAllowExitOverlap) {
-                startCalledActivityEnter();
-            }
-        }
-
-        private void notifyComplete() {
-            if (mExitTransitionComplete && mBackgroundFadeComplete
-                    && mSharedElementTransitioned && !mOnCompleteExecuted) {
-                mOnComplete.run();
-                mSceneTransitionListener.nullPendingTransition();
-                mOnCompleteExecuted = true;
-            }
-        }
-
-        @Override
-        public void onAnimationStart(Animator animation) {
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mBackgroundFadeComplete = true;
-            if (mAllowExitOverlap) {
-                startCalledActivityEnter();
-            }
-        }
-
-        @Override
-        public void onAnimationCancel(Animator animation) {
-        }
-
-        @Override
-        public void onAnimationRepeat(Animator animation) {
-        }
-
-        private void startCalledActivityEnter() {
-            mActivityOptions.dispatchRestore(mSharedElementArgs);
-            setViewVisibility(mSharedElements, View.INVISIBLE);
-            mSharedElementTransitioned = true;
-            notifyComplete();
-        }
-    }
-
-    /**
-     * Provides code for handling the Activity transition entering scene.
-     * When the first scene is laid out (onPreDraw), it makes views invisible.
-     * It then starts the entering transition by making non-shared elements visible. When
-     * the entering transition is started, the calling Activity is notified that
-     * this Activity is ready to receive the shared element. When the calling Activity notifies
-     * that the shared element is ready, this Activity is notified through the
-     * SceneTransitionListener.
-     *
-     * This class also takes into account fading the background -- either waiting until the
-     * shared element is ready or the calling Activity's exit transition is complete.
-     */
-    private class EnterScene implements ViewTreeObserver.OnPreDrawListener, Runnable,
-            ActivityOptions.ActivityTransitionTarget, Animator.AnimatorListener {
-        private boolean mSharedElementReadyReceived;
-        private boolean mAllDone;
-        private Handler mHandler = new Handler();
-        private boolean mEnterTransitionStarted;
-        private ArrayMap<String, View> mSharedElementTargets = new ArrayMap<String, View>();
-        private ArrayList<View> mEnteringViews = new ArrayList<View>();
-        private Transition.EpicenterCallback mEpicenterCallback;
-
-        public EnterScene() {
-            mSceneTransitionListener.nullPendingTransition();
-            Drawable background = getDecorView().getBackground();
-            if (background != null) {
-                background.setAlpha(0);
-                mDecor.drawableChanged();
-            }
-            mSceneTransitionListener.convertToTranslucent();
-        }
-
-        @Override
-        public boolean onPreDraw() {
-            ViewTreeObserver observer = mDecor.getViewTreeObserver();
-            observer.removeOnPreDrawListener(this);
-            if (!mEnterTransitionStarted && mSceneTransitionListener != null) {
-                mEnterTransitionStarted = true;
-                mDecor.captureTransitioningViews(mEnteringViews);
-                mapSharedElements(mSharedElementTargets);
-                mEnteringViews.removeAll(mSharedElementTargets.values());
-                Rect epicenter = calcEpicenter(mSharedElementTargets,
-                        mActivityOptions.getSharedElementNames());
-                mEpicenterCallback = new FixedEpicenterCallback(epicenter);
-
-                setViewVisibility(mEnteringViews, View.INVISIBLE);
-                setViewVisibility(mSharedElementTargets.values(), View.INVISIBLE);
-                if (mAllowEnterOverlap) {
-                    beginEnterScene();
-                }
-                observer.addOnPreDrawListener(this);
-                return false;
-            } else {
-                mHandler.postDelayed(this, MAX_TRANSITION_START_WAIT);
-                mActivityOptions.dispatchSceneTransitionStarted(this,
-                        new ArrayList<String>(mSharedElementTargets.keySet()));
-                return !mSharedElementReadyReceived;
-            }
-        }
-
-        public void start() {
-            ViewTreeObserver observer = mDecor.getViewTreeObserver();
-            observer.addOnPreDrawListener(this);
-        }
-
-        @Override
-        public void run() {
-            exitTransitionComplete();
-        }
-
-        @Override
-        public void sharedElementTransitionComplete(final Bundle transitionArgs) {
-            if (!mSharedElementReadyReceived) {
-                mSharedElementReadyReceived = true;
-                mHandler.removeCallbacks(this);
-                mHandler.postDelayed(this, MAX_TRANSITION_FINISH_WAIT);
-                if (!mSharedElementTargets.isEmpty()) {
-                    runOnUiThread(mHandler, new Runnable() {
-                        @Override
-                        public void run() {
-                            Transition transition = getTransitionManager().getEnterTransition(
-                                    mContentScene);
-                            if (transition == null) {
-                                transition = TransitionManager.getDefaultTransition();
-                            }
-                            transition = addTransitionTargets(transition,
-                                    mSharedElementTargets.values(),
-                                    true);
-                            transition.setEpicenterCallback(mEpicenterCallback);
-                            if (transitionArgs == null) {
-                                TransitionManager.beginDelayedTransition(mDecor, transition);
-                                setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
-                            } else {
-                                mSceneTransitionListener.sharedElementStart(transition);
-                                setSharedElementState(mSharedElementTargets, transitionArgs);
-                                setViewVisibility(mSharedElementTargets.values(), View.VISIBLE);
-                                mDecor.getViewTreeObserver().addOnPreDrawListener(
-                                        new ViewTreeObserver.OnPreDrawListener() {
-                                            @Override
-                                            public boolean onPreDraw() {
-                                                mDecor.getViewTreeObserver()
-                                                        .removeOnPreDrawListener(this);
-                                                mSceneTransitionListener.sharedElementEnd();
-                                                mActivityOptions.dispatchSharedElementsReady();
-                                                return true;
-                                            }
-                                        });
-                                TransitionManager.beginDelayedTransition(mDecor, transition);
-                            }
-                        }
-                    });
-                }
-                if (mAllowEnterOverlap) {
-                    fadeInBackground();
-                }
-            }
-        }
-
-        private void fadeInBackground() {
-            Drawable background = getDecorView().getBackground();
-            if (background == null) {
-                mSceneTransitionListener.convertFromTranslucent();
-            } else {
-                ObjectAnimator animator = ObjectAnimator.ofInt(background, "alpha", 255);
-                animator.addListener(this);
-                animator.start();
-            }
-        }
-
-        @Override
-        public void exitTransitionComplete() {
-            if (mAllDone) {
-                return;
-            }
-            mAllDone = true;
-            sharedElementTransitionComplete(null);
-            mHandler.removeCallbacks(this);
-            if (!mAllowEnterOverlap) {
-                runOnUiThread(mHandler, new Runnable() {
-                    @Override
-                    public void run() {
-                        beginEnterScene();
-                        fadeInBackground();
-                    }
-                });
-            }
-        }
-
-        @Override
-        public void onAnimationStart(Animator animation) {
-        }
-
-        @Override
-        public void onAnimationEnd(Animator animation) {
-            mSceneTransitionListener.convertFromTranslucent();
-        }
-
-        @Override
-        public void onAnimationCancel(Animator animation) {
-        }
-
-        @Override
-        public void onAnimationRepeat(Animator animation) {
-        }
-
-        private void beginEnterScene() {
-            Transition transition = getTransitionManager().getEnterTransition(mContentScene);
-            if (transition == null) {
-                transition = TransitionManager.getDefaultTransition();
-            }
-            transition = addTransitionTargets(transition, mEnteringViews, true);
-            transition.setEpicenterCallback(mEpicenterCallback);
-            TransitionManager.beginDelayedTransition(mDecor, transition);
-            setViewVisibility(mEnteringViews, View.VISIBLE);
-        }
-    }
-
-    private static class FixedEpicenterCallback extends Transition.EpicenterCallback {
-        private Rect mEpicenter;
-
-        public FixedEpicenterCallback(Rect epicenter) {
-            mEpicenter = epicenter;
-        }
-
-        @Override
-        public Rect getEpicenter(Transition transition) {
-            return mEpicenter;
-        }
-    };
 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index ccdacea..8bc669a 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -96,6 +96,8 @@
 import android.view.animation.AnimationUtils;
 
 import com.android.internal.R;
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
 import com.android.internal.statusbar.IStatusBarService;
@@ -174,6 +176,8 @@
      * Keyguard stuff
      */
     private WindowState mKeyguardScrim;
+    private boolean mKeyguardHidden;
+    private boolean mKeyguardDrawn;
 
     /* Table of Application Launch keys.  Maps from key codes to intent categories.
      *
@@ -248,7 +252,6 @@
     int[] mNavigationBarHeightForRotation = new int[4];
     int[] mNavigationBarWidthForRotation = new int[4];
 
-    WindowState mKeyguard = null;
     KeyguardServiceDelegate mKeyguardDelegate;
     GlobalActions mGlobalActions;
     volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
@@ -986,7 +989,7 @@
         initializeHdmiState();
 
         // Match current screen state.
-        if (mPowerManager.isScreenOn()) {
+        if (mPowerManager.isInteractive()) {
             screenTurningOn(null);
         } else {
             screenTurnedOff(WindowManagerPolicy.OFF_BECAUSE_OF_USER);
@@ -1311,7 +1314,6 @@
             case TYPE_BOOT_PROGRESS:
             case TYPE_DISPLAY_OVERLAY:
             case TYPE_HIDDEN_NAV_CONSUMER:
-            case TYPE_KEYGUARD:
             case TYPE_KEYGUARD_SCRIM:
             case TYPE_KEYGUARD_DIALOG:
             case TYPE_MAGNIFICATION_OVERLAY:
@@ -1348,6 +1350,22 @@
                         | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
                 attrs.flags &= ~WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
                 break;
+            case TYPE_STATUS_BAR:
+
+                // If the Keyguard is in a hidden state (occluded by another window), we force to
+                // remove the wallpaper and keyguard flag so that any change in-flight after setting
+                // the keyguard as occluded wouldn't set these flags again.
+                // See {@link #processKeyguardSetHiddenResultLw}.
+                if (mKeyguardHidden) {
+                    attrs.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
+                    attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+                }
+                break;
+        }
+
+        if (attrs.type != TYPE_STATUS_BAR) {
+            // The status bar is the only window allowed to exhibit keyguard behavior.
+            attrs.privateFlags &= ~WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
         }
     }
     
@@ -1434,54 +1452,50 @@
         case TYPE_KEYGUARD_SCRIM:
             // the safety window that shows behind keyguard while keyguard is starting
             return 12;
-        case TYPE_KEYGUARD:
-            // the keyguard; nothing on top of these can take focus, since they are
-            // responsible for power management when displayed.
-            return 13;
-        case TYPE_KEYGUARD_DIALOG:
-            return 14;
         case TYPE_STATUS_BAR_SUB_PANEL:
-            return 15;
+            return 13;
         case TYPE_STATUS_BAR:
-            return 16;
+            return 14;
         case TYPE_STATUS_BAR_PANEL:
-            return 17;
+            return 15;
+        case TYPE_KEYGUARD_DIALOG:
+            return 16;
         case TYPE_VOLUME_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 18;
+            return 17;
         case TYPE_SYSTEM_OVERLAY:
             // the on-screen volume indicator and controller shown when the user
             // changes the device volume
-            return 19;
+            return 18;
         case TYPE_NAVIGATION_BAR:
             // the navigation bar, if available, shows atop most things
-            return 20;
+            return 19;
         case TYPE_NAVIGATION_BAR_PANEL:
             // some panels (e.g. search) need to show on top of the navigation bar
-            return 21;
+            return 20;
         case TYPE_SYSTEM_ERROR:
             // system-level error dialogs
-            return 22;
+            return 21;
         case TYPE_MAGNIFICATION_OVERLAY:
             // used to highlight the magnified portion of a display
-            return 23;
+            return 22;
         case TYPE_DISPLAY_OVERLAY:
             // used to simulate secondary display devices
-            return 24;
+            return 23;
         case TYPE_DRAG:
             // the drag layer: input for drag-and-drop is associated with this window,
             // which sits above all other focusable windows
-            return 25;
+            return 24;
         case TYPE_SECURE_SYSTEM_OVERLAY:
-            return 26;
+            return 25;
         case TYPE_BOOT_PROGRESS:
-            return 27;
+            return 26;
         case TYPE_POINTER:
             // the (mouse) pointer layer
-            return 28;
+            return 27;
         case TYPE_HIDDEN_NAV_CONSUMER:
-            return 29;
+            return 28;
         }
         Log.e(TAG, "Unknown window type: " + type);
         return 2;
@@ -1551,7 +1565,7 @@
 
     @Override
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
-        return attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD;
+        return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
     }
 
     @Override
@@ -1562,7 +1576,6 @@
             case TYPE_WALLPAPER:
             case TYPE_DREAM:
             case TYPE_UNIVERSE_BACKGROUND:
-            case TYPE_KEYGUARD:
             case TYPE_KEYGUARD_SCRIM:
                 return false;
             default:
@@ -1761,12 +1774,6 @@
                         android.Manifest.permission.STATUS_BAR_SERVICE,
                         "PhoneWindowManager");
                 break;
-            case TYPE_KEYGUARD:
-                if (mKeyguard != null) {
-                    return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
-                }
-                mKeyguard = win;
-                break;
             case TYPE_KEYGUARD_SCRIM:
                 if (mKeyguardScrim != null) {
                     return WindowManagerGlobal.ADD_MULTIPLE_SINGLETON;
@@ -1783,9 +1790,6 @@
         if (mStatusBar == win) {
             mStatusBar = null;
             mStatusBarController.setWindow(null);
-        } else if (mKeyguard == win) {
-            Log.v(TAG, "Removing keyguard window (Did it crash?)");
-            mKeyguard = null;
             mKeyguardDelegate.showScrim();
         } else if (mKeyguardScrim == win) {
             Log.v(TAG, "Removing keyguard scrim");
@@ -1804,12 +1808,13 @@
         if (PRINT_ANIM) Log.i(TAG, "selectAnimation in " + win
               + ": transit=" + transit);
         if (win == mStatusBar) {
+            boolean isKeyguard = (win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
             if (transit == TRANSIT_EXIT
                     || transit == TRANSIT_HIDE) {
-                return R.anim.dock_top_exit;
+                return isKeyguard ? -1 : R.anim.dock_top_exit;
             } else if (transit == TRANSIT_ENTER
                     || transit == TRANSIT_SHOW) {
-                return R.anim.dock_top_enter;
+                return isKeyguard ? -1 : R.anim.dock_top_enter;
             }
         } else if (win == mNavigationBar) {
             // This can be on either the bottom or the right.
@@ -2030,9 +2035,9 @@
             WindowManager.LayoutParams attrs = win != null ? win.getAttrs() : null;
             if (attrs != null) {
                 final int type = attrs.type;
-                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
-                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
-                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
+                if (type == WindowManager.LayoutParams.TYPE_KEYGUARD_SCRIM
+                        || type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG
+                        || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                     // the "app" is keyguard, so give it the key
                     return 0;
                 }
@@ -2357,7 +2362,7 @@
     }
 
     private boolean interceptFallback(WindowState win, KeyEvent fallbackEvent, int policyFlags) {
-        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
+        int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags);
         if ((actions & ACTION_PASS_TO_USER) != 0) {
             long delayMillis = interceptKeyBeforeDispatching(
                     win, fallbackEvent, policyFlags);
@@ -2461,7 +2466,7 @@
      * given the situation with the keyguard.
      */
     void launchHomeFromHotKey() {
-        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotHidden()) {
+        if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) {
             // don't launch home if keyguard showing
         } else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
             // when in keyguard restricted mode, must first verify unlock
@@ -3083,9 +3088,8 @@
                                 + mOverscanScreenHeight;
                     } else if (canHideNavigationBar()
                             && (sysUiFl & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) != 0
-                            && (attrs.type == WindowManager.LayoutParams.TYPE_KEYGUARD || (
-                                attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
-                             && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW))) {
+                            && attrs.type >= WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW
+                            && attrs.type <= WindowManager.LayoutParams.LAST_SUB_WINDOW) {
                         // Asking for layout as if the nav bar is hidden, lets the
                         // application extend into the unrestricted overscan screen area.  We
                         // only do this for application windows to ensure no window that
@@ -3392,16 +3396,19 @@
             mForcingShowNavBar = true;
             mForcingShowNavBarLayer = win.getSurfaceLayer();
         }
+        if (attrs.type == TYPE_STATUS_BAR && (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
+            mForceStatusBarFromKeyguard = true;
+        }
         if (mTopFullscreenOpaqueWindowState == null &&
                 win.isVisibleOrBehindKeyguardLw() && !win.isGoneForLayoutLw()) {
             if ((fl & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
-                if (attrs.type == TYPE_KEYGUARD) {
+                if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                     mForceStatusBarFromKeyguard = true;
                 } else {
                     mForceStatusBar = true;
                 }
             }
-            if (attrs.type == TYPE_KEYGUARD) {
+            if ((attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                 mShowingLockscreen = true;
             }
             boolean appWindow = attrs.type >= FIRST_APPLICATION_WINDOW
@@ -3531,11 +3538,12 @@
 
         // Hide the key guard if a visible window explicitly specifies that it wants to be
         // displayed when the screen is locked.
-        if (mKeyguard != null) {
+        if (mKeyguardDelegate != null && mStatusBar != null) {
             if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
                     + mHideLockScreen);
             if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
-                if (mKeyguard.hideLw(true)) {
+                mKeyguardHidden = true;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3549,24 +3557,22 @@
                     });
                 }
             } else if (mHideLockScreen) {
-                if (mKeyguard.hideLw(true)) {
+                mKeyguardHidden = true;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
                 }
-                if (!mShowingDream) {
-                    mKeyguardDelegate.setHidden(true);
-                }
             } else if (mDismissKeyguard != DISMISS_KEYGUARD_NONE) {
                 // This is the case of keyguard isSecure() and not mHideLockScreen.
                 if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
                     // Only launch the next keyguard unlock window once per window.
-                    if (mKeyguard.showLw(true)) {
+                    mKeyguardHidden = false;
+                    if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
                         changes |= FINISH_LAYOUT_REDO_LAYOUT
                                 | FINISH_LAYOUT_REDO_CONFIG
                                 | FINISH_LAYOUT_REDO_WALLPAPER;
                     }
-                    mKeyguardDelegate.setHidden(false);
                     mHandler.post(new Runnable() {
                         @Override
                         public void run() {
@@ -3576,12 +3582,12 @@
                 }
             } else {
                 mWinDismissingKeyguard = null;
-                if (mKeyguard.showLw(true)) {
+                mKeyguardHidden = false;
+                if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
                     changes |= FINISH_LAYOUT_REDO_LAYOUT
                             | FINISH_LAYOUT_REDO_CONFIG
                             | FINISH_LAYOUT_REDO_WALLPAPER;
                 }
-                mKeyguardDelegate.setHidden(false);
             }
         }
 
@@ -3596,9 +3602,39 @@
         return changes;
     }
 
+    /**
+     * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we
+     * immediately need to put the wallpaper directly behind the Keyguard when a window with flag
+     * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we
+     * would wait for Keyguard to change the flags, that would be running asynchronously and thus be
+     * too late so the user might see the window behind.
+     *
+     * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}.
+     * @return Whether the flags have changed and we have to redo the layout.
+     */
+    private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) {
+        if (setHiddenResult
+                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) {
+            mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
+            mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
+            return true;
+        } else if (setHiddenResult
+                == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) {
+            mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
+            mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    private boolean isStatusBarKeyguard() {
+        return mStatusBar != null
+                && (mStatusBar.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0;
+    }
+
     public boolean allowAppAnimationsLw() {
-        if (mKeyguard != null && mKeyguard.isVisibleLw() && !mKeyguard.isAnimatingLw()
-                || mShowingDream) {
+        if (isStatusBarKeyguard() || mShowingDream) {
             // If keyguard or dreams is currently visible, no reason to animate behind it.
             return false;
         }
@@ -3801,12 +3837,13 @@
 
     /** {@inheritDoc} */
     @Override
-    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
         if (!mSystemBooted) {
             // If we have not yet booted, don't let key events do anything.
             return 0;
         }
 
+        final boolean interactive = (policyFlags & FLAG_INTERACTIVE) != 0;
         final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         final boolean canceled = event.isCanceled();
         final int keyCode = event.getKeyCode();
@@ -3818,19 +3855,13 @@
         // This will prevent any keys other than the power button from waking the screen
         // when the keyguard is hidden by another activity.
         final boolean keyguardActive = (mKeyguardDelegate == null ? false :
-                                            (isScreenOn ?
-                                                mKeyguardDelegate.isShowingAndNotHidden() :
+                                            (interactive ?
+                                                mKeyguardDelegate.isShowingAndNotOccluded() :
                                                 mKeyguardDelegate.isShowing()));
 
-        if (keyCode == KeyEvent.KEYCODE_POWER
-                || keyCode == KeyEvent.KEYCODE_SLEEP
-                || keyCode == KeyEvent.KEYCODE_WAKEUP) {
-            policyFlags |= WindowManagerPolicy.FLAG_WAKE;
-        }
-
         if (DEBUG_INPUT) {
             Log.d(TAG, "interceptKeyTq keycode=" + keyCode
-                    + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
+                    + " interactive=" + interactive + " keyguardActive=" + keyguardActive
                     + " policyFlags=" + Integer.toHexString(policyFlags));
         }
 
@@ -3839,18 +3870,11 @@
             performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
         }
 
-        // Basic policy based on screen state and keyguard.
-        // FIXME: This policy isn't quite correct.  We shouldn't care whether the screen
-        //        is on or off, really.  We should care about whether the device is in an
-        //        interactive state or is in suspend pretending to be "off".
-        //        The primary screen might be turned off due to proximity sensor or
-        //        because we are presenting media on an auxiliary screen or remotely controlling
-        //        the device some other way (which is why we have an exemption here for injected
-        //        events).
+        // Basic policy based on interactive state.
         int result;
-        boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
-                | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-        if (isScreenOn || (isInjected && !isWakeKey)) {
+        boolean isWakeKey = (policyFlags & WindowManagerPolicy.FLAG_WAKE) != 0
+                || event.isWakeKey();
+        if (interactive || (isInjected && !isWakeKey)) {
             // When the screen is on or if the key is injected pass the key to the application.
             result = ACTION_PASS_TO_USER;
         } else {
@@ -3875,7 +3899,7 @@
             case KeyEvent.KEYCODE_VOLUME_MUTE: {
                 if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
                     if (down) {
-                        if (isScreenOn && !mVolumeDownKeyTriggered
+                        if (interactive && !mVolumeDownKeyTriggered
                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                             mVolumeDownKeyTriggered = true;
                             mVolumeDownKeyTime = event.getDownTime();
@@ -3889,7 +3913,7 @@
                     }
                 } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
                     if (down) {
-                        if (isScreenOn && !mVolumeUpKeyTriggered
+                        if (interactive && !mVolumeUpKeyTriggered
                                 && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                             mVolumeUpKeyTriggered = true;
                             cancelPendingPowerKeyAction();
@@ -3957,7 +3981,7 @@
                             Log.w(TAG, "ITelephony threw RemoteException", ex);
                         }
                     }
-                    interceptPowerKeyDown(!isScreenOn || hungUp);
+                    interceptPowerKeyDown(!interactive || hungUp);
                 } else {
                     if (interceptPowerKeyUp(canceled)) {
                         if ((mEndcallBehavior
@@ -3979,12 +4003,12 @@
             case KeyEvent.KEYCODE_POWER: {
                 result &= ~ACTION_PASS_TO_USER;
                 if (down) {
-                    boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn,
+                    boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
                             event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
                     if (panic) {
                         mHandler.post(mRequestTransientNav);
                     }
-                    if (isScreenOn && !mPowerKeyTriggered
+                    if (interactive && !mPowerKeyTriggered
                             && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                         mPowerKeyTriggered = true;
                         mPowerKeyTime = event.getDownTime();
@@ -4001,7 +4025,7 @@
                                 telephonyService.silenceRinger();
                             } else if ((mIncallPowerBehavior
                                     & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
-                                    && telephonyService.isOffhook() && isScreenOn) {
+                                    && telephonyService.isOffhook() && interactive) {
                                 // Otherwise, if "Power button ends call" is enabled,
                                 // the Power button will hang up any current active call.
                                 hungUp = telephonyService.endCall();
@@ -4010,7 +4034,7 @@
                             Log.w(TAG, "ITelephony threw RemoteException", ex);
                         }
                     }
-                    interceptPowerKeyDown(!isScreenOn || hungUp
+                    interceptPowerKeyDown(!interactive || hungUp
                             || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
                 } else {
                     mPowerKeyTriggered = false;
@@ -4143,15 +4167,12 @@
 
     /** {@inheritDoc} */
     @Override
-    public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
-        int result = 0;
-
-        final boolean isWakeMotion = (policyFlags
-                & (WindowManagerPolicy.FLAG_WAKE | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-        if (isWakeMotion) {
-            mPowerManager.wakeUp(whenNanos / 1000000);
-        }
-        return result;
+    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+        // We already know this is a wake motion so just wake up.
+        // Note that we would observe policyFlags containing
+        // FLAG_WAKE and FLAG_INTERACTIVE here.
+        mPowerManager.wakeUp(whenNanos / 1000000);
+        return 0;
     }
 
     void dispatchMediaKeyWithWakeLock(KeyEvent event) {
@@ -4328,21 +4349,16 @@
 
     private void waitForKeyguard(final ScreenOnListener screenOnListener) {
         if (mKeyguardDelegate != null) {
-            if (screenOnListener != null) {
-                mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
-                    @Override
-                    public void onShown(IBinder windowToken) {
-                        waitForKeyguardWindowDrawn(windowToken, screenOnListener);
-                    }
-                });
-                return;
-            } else {
-                mKeyguardDelegate.onScreenTurnedOn(null);
-            }
+            mKeyguardDelegate.onScreenTurnedOn(new KeyguardServiceDelegate.ShowListener() {
+                @Override
+                public void onShown(IBinder windowToken) {
+                    waitForKeyguardWindowDrawn(windowToken, screenOnListener);
+                }
+            });
         } else {
             Slog.i(TAG, "No keyguard interface!");
+            finishScreenTurningOn(screenOnListener);
         }
-        finishScreenTurningOn(screenOnListener);
     }
 
     private void waitForKeyguardWindowDrawn(IBinder windowToken,
@@ -4355,6 +4371,7 @@
                     public void sendResult(Bundle data) {
                         Slog.i(TAG, "Lock screen displayed!");
                         finishScreenTurningOn(screenOnListener);
+                        setKeyguardDrawn();
                     }
                 })) {
                     return;
@@ -4368,6 +4385,7 @@
 
         Slog.i(TAG, "No lock screen! windowToken=" + windowToken);
         finishScreenTurningOn(screenOnListener);
+        setKeyguardDrawn();
     }
 
     private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
@@ -4411,7 +4429,7 @@
 
     private boolean keyguardIsShowingTq() {
         if (mKeyguardDelegate == null) return false;
-        return mKeyguardDelegate.isShowingAndNotHidden();
+        return mKeyguardDelegate.isShowingAndNotOccluded();
     }
 
 
@@ -4448,6 +4466,23 @@
         }
     }
 
+    private void setKeyguardDrawn() {
+        synchronized (mLock) {
+            mKeyguardDrawn = true;
+        }
+        try {
+            mWindowManager.enableScreenIfNeeded();
+        } catch (RemoteException unhandled) {
+        }
+    }
+
+    @Override
+    public boolean isKeyguardDrawnLw() {
+        synchronized (mLock) {
+            return mKeyguardDrawn;
+        }
+    }
+
     void sendCloseSystemWindows() {
         sendCloseSystemWindows(mContext, null);
     }
@@ -4731,6 +4766,7 @@
         synchronized (mLock) {
             mSystemBooted = true;
         }
+        waitForKeyguard(null);
     }
 
     ProgressDialog mBootMsgDialog = null;
@@ -5055,7 +5091,7 @@
         }
         final boolean hapticsDisabled = Settings.System.getIntForUser(mContext.getContentResolver(),
                 Settings.System.HAPTIC_FEEDBACK_ENABLED, 0, UserHandle.USER_CURRENT) == 0;
-        if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotHidden())) {
+        if (!always && (hapticsDisabled || mKeyguardDelegate.isShowingAndNotOccluded())) {
             return false;
         }
         long[] pattern = null;
@@ -5106,7 +5142,7 @@
 
     @Override
     public void keepScreenOnStoppedLw() {
-        if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotHidden()) {
+        if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) {
             mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
         }
     }
@@ -5118,7 +5154,7 @@
         if (win == null) {
             return 0;
         }
-        if (win.getAttrs().type == TYPE_KEYGUARD && mHideLockScreen == true) {
+        if ((win.getAttrs().privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 && mHideLockScreen == true) {
             // We are updating at a point where the keyguard has gotten
             // focus, but we were last in a state where the top window is
             // hiding it.  This is probably because the keyguard as been
@@ -5164,8 +5200,8 @@
 
     private int updateSystemBarsLw(WindowState win, int oldVis, int vis) {
         // apply translucent bar vis flags
-        WindowState transWin = mKeyguard != null && mKeyguard.isVisibleLw() && !mHideLockScreen
-                ? mKeyguard
+        WindowState transWin = isStatusBarKeyguard() && !mHideLockScreen
+                ? mStatusBar
                 : mTopFullscreenOpaqueWindowState;
         vis = mStatusBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
         vis = mNavigationBarController.applyTranslucentFlagLw(transWin, vis, oldVis);
@@ -5176,9 +5212,10 @@
             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                     | View.SYSTEM_UI_FLAG_IMMERSIVE
-                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
-                    | View.STATUS_BAR_TRANSLUCENT
-                    | View.NAVIGATION_BAR_TRANSLUCENT;
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+            if (!isStatusBarKeyguard() || mHideLockScreen) {
+                flags |= View.STATUS_BAR_TRANSLUCENT | View.NAVIGATION_BAR_TRANSLUCENT;
+            }
             vis = (vis & ~flags) | (oldVis & flags);
         }
 
@@ -5423,15 +5460,13 @@
         if (mStatusBar != null) {
             pw.print(prefix); pw.print("mStatusBar=");
                     pw.println(mStatusBar);
+            pw.print(prefix); pw.print("isStatusBarKeyguard=");
+                    pw.print(isStatusBarKeyguard());
         }
         if (mNavigationBar != null) {
             pw.print(prefix); pw.print("mNavigationBar=");
                     pw.println(mNavigationBar);
         }
-        if (mKeyguard != null) {
-            pw.print(prefix); pw.print("mKeyguard=");
-                    pw.println(mKeyguard);
-        }
         if (mFocusedWindow != null) {
             pw.print(prefix); pw.print("mFocusedWindow=");
                     pw.println(mFocusedWindow);
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 812e817..966924b 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -29,8 +29,8 @@
  */
 public class KeyguardServiceDelegate {
     // TODO: propagate changes to these to {@link KeyguardTouchDelegate}
-    public static final String KEYGUARD_PACKAGE = "com.android.keyguard";
-    public static final String KEYGUARD_CLASS = "com.android.keyguard.KeyguardService";
+    public static final String KEYGUARD_PACKAGE = "com.android.systemui";
+    public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
 
     private static final String TAG = "KeyguardServiceDelegate";
     private static final boolean DEBUG = true;
@@ -44,13 +44,13 @@
             // the event something checks before the service is actually started.
             // KeyguardService itself should default to this state until the real state is known.
             showing = true;
-            showingAndNotHidden = true;
+            showingAndNotOccluded = true;
             secure = true;
         }
         boolean showing;
-        boolean showingAndNotHidden;
+        boolean showingAndNotOccluded;
         boolean inputRestricted;
-        boolean hidden;
+        boolean occluded;
         boolean secure;
         boolean dreaming;
         boolean systemIsReady;
@@ -109,7 +109,7 @@
                 Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
             if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
             mKeyguardState.showing = false;
-            mKeyguardState.showingAndNotHidden = false;
+            mKeyguardState.showingAndNotOccluded = false;
             mKeyguardState.secure = false;
         } else {
             if (DEBUG) Log.v(TAG, "*** Keyguard started");
@@ -148,11 +148,11 @@
         return mKeyguardState.showing;
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         if (mKeyguardService != null) {
-            mKeyguardState.showingAndNotHidden = mKeyguardService.isShowingAndNotHidden();
+            mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded();
         }
-        return mKeyguardState.showingAndNotHidden;
+        return mKeyguardState.showingAndNotOccluded;
     }
 
     public boolean isInputRestricted() {
@@ -174,11 +174,13 @@
         }
     }
 
-    public void setHidden(boolean isHidden) {
+    public int setOccluded(boolean isOccluded) {
+        int result = 0;
         if (mKeyguardService != null) {
-            mKeyguardService.setHidden(isHidden);
+            result = mKeyguardService.setOccluded(isOccluded);
         }
-        mKeyguardState.hidden = isHidden;
+        mKeyguardState.occluded = isOccluded;
+        return result;
     }
 
     public void dismiss() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 9fb2a50..7cb48fa 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -22,6 +22,7 @@
 import android.util.Slog;
 import android.view.MotionEvent;
 
+import com.android.internal.policy.IKeyguardServiceConstants;
 import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
@@ -57,9 +58,9 @@
         return false; // TODO cache state
     }
 
-    public boolean isShowingAndNotHidden() {
+    public boolean isShowingAndNotOccluded() {
         try {
-            return mService.isShowingAndNotHidden();
+            return mService.isShowingAndNotOccluded();
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
         }
@@ -100,11 +101,12 @@
         }
     }
 
-    public void setHidden(boolean isHidden) {
+    public int setOccluded(boolean isOccluded) {
         try {
-            mService.setHidden(isHidden);
+            return mService.setOccluded(isOccluded);
         } catch (RemoteException e) {
             Slog.w(TAG , "Remote Exception", e);
+            return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
         }
     }
 
diff --git a/preloaded-classes b/preloaded-classes
index 35c52ad..4413cd3 100644
--- a/preloaded-classes
+++ b/preloaded-classes
@@ -601,8 +601,6 @@
 android.media.ResampleInputStream
 android.media.SoundPool
 android.media.ToneGenerator
-android.media.videoeditor.MediaArtistNativeHelper
-android.media.videoeditor.VideoEditorProfile
 android.mtp.MtpDatabase
 android.mtp.MtpDevice
 android.mtp.MtpDeviceInfo
diff --git a/rs/java/android/renderscript/ScriptIntrinsicResize.java b/rs/java/android/renderscript/ScriptIntrinsicResize.java
new file mode 100644
index 0000000..fe56699
--- /dev/null
+++ b/rs/java/android/renderscript/ScriptIntrinsicResize.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.renderscript;
+
+/**
+ * Intrinsic for performing a resize of a 2D allocation.
+ */
+public final class ScriptIntrinsicResize extends ScriptIntrinsic {
+    private Allocation mInput;
+
+    private ScriptIntrinsicResize(long id, RenderScript rs) {
+        super(id, rs);
+    }
+
+    /**
+     * Supported elements types are {@link Element#U8}, {@link
+     * Element#U8_2}, {@link Element#U8_3}, {@link Element#U8_4}
+     *
+     * @param rs The RenderScript context
+     *
+     * @return ScriptIntrinsicResize
+     */
+    public static ScriptIntrinsicResize create(RenderScript rs) {
+        long id = rs.nScriptIntrinsicCreate(12, 0);
+        ScriptIntrinsicResize si = new ScriptIntrinsicResize(id, rs);
+        return si;
+
+    }
+
+    /**
+     * Set the input of the resize.
+     * Must match the element type supplied during create.
+     *
+     * @param ain The input allocation.
+     */
+    public void setInput(Allocation ain) {
+        Element e = ain.getElement();
+        if (!e.isCompatible(Element.U8(mRS)) &&
+            !e.isCompatible(Element.U8_2(mRS)) &&
+            !e.isCompatible(Element.U8_3(mRS)) &&
+            !e.isCompatible(Element.U8_4(mRS))) {
+            throw new RSIllegalArgumentException("Unsuported element type.");
+        }
+
+        mInput = ain;
+        setVar(0, ain);
+    }
+
+    /**
+     * Get a FieldID for the input field of this intrinsic.
+     *
+     * @return Script.FieldID The FieldID object.
+     */
+    public Script.FieldID getFieldID_Input() {
+        return createFieldID(0, null);
+    }
+
+
+    /**
+     * Resize copy the input allocation to the output specified. The
+     * Allocation is rescaled if necessary using bi-cubic
+     * interpolation.
+     *
+     * @param aout Output allocation. Element type must match
+     *             current input.  Must not be same as input.
+     */
+    public void forEach_bicubic(Allocation aout) {
+        if (aout == mInput) {
+            throw new RSIllegalArgumentException("Output cannot be same as Input.");
+        }
+        forEach_bicubic(aout, null);
+    }
+
+    /**
+     * Resize copy the input allocation to the output specified. The
+     * Allocation is rescaled if necessary using bi-cubic
+     * interpolation.
+     *
+     * @param aout Output allocation. Element type must match
+     *             current input.
+     * @param opt LaunchOptions for clipping
+     */
+    public void forEach_bicubic(Allocation aout, Script.LaunchOptions opt) {
+        forEach(0, null, aout, null, opt);
+    }
+
+    /**
+     * Get a KernelID for this intrinsic kernel.
+     *
+     * @return Script.KernelID The KernelID object.
+     */
+    public Script.KernelID getKernelID_bicubic() {
+        return createKernelID(0, 2, null, null);
+    }
+
+
+}
+
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index 671b43d..18a2e31 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -47,24 +47,29 @@
 
 using namespace android;
 
-#define PER_ARRAY_TYPE(flag, fnc, ...) {                                                \
+#define PER_ARRAY_TYPE(flag, fnc, readonly, ...) {                                      \
     jint len = 0;                                                                       \
     void *ptr = NULL;                                                                   \
     size_t typeBytes = 0;                                                               \
+    jint relFlag = 0;                                                                   \
+    if (readonly) {                                                                     \
+        /* The on-release mode should only be JNI_ABORT for read-only accesses. */      \
+        relFlag = JNI_ABORT;                                                            \
+    }                                                                                   \
     switch(dataType) {                                                                  \
     case RS_TYPE_FLOAT_32:                                                              \
         len = _env->GetArrayLength((jfloatArray)data);                                  \
         ptr = _env->GetFloatArrayElements((jfloatArray)data, flag);                     \
         typeBytes = 4;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, JNI_ABORT);   \
+        _env->ReleaseFloatArrayElements((jfloatArray)data, (jfloat *)ptr, relFlag);     \
         return;                                                                         \
     case RS_TYPE_FLOAT_64:                                                              \
         len = _env->GetArrayLength((jdoubleArray)data);                                 \
         ptr = _env->GetDoubleArrayElements((jdoubleArray)data, flag);                   \
         typeBytes = 8;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, JNI_ABORT);\
+        _env->ReleaseDoubleArrayElements((jdoubleArray)data, (jdouble *)ptr, relFlag);  \
         return;                                                                         \
     case RS_TYPE_SIGNED_8:                                                              \
     case RS_TYPE_UNSIGNED_8:                                                            \
@@ -72,7 +77,7 @@
         ptr = _env->GetByteArrayElements((jbyteArray)data, flag);                       \
         typeBytes = 1;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, JNI_ABORT);       \
+        _env->ReleaseByteArrayElements((jbyteArray)data, (jbyte*)ptr, relFlag);         \
         return;                                                                         \
     case RS_TYPE_SIGNED_16:                                                             \
     case RS_TYPE_UNSIGNED_16:                                                           \
@@ -80,7 +85,7 @@
         ptr = _env->GetShortArrayElements((jshortArray)data, flag);                     \
         typeBytes = 2;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, JNI_ABORT);   \
+        _env->ReleaseShortArrayElements((jshortArray)data, (jshort *)ptr, relFlag);     \
         return;                                                                         \
     case RS_TYPE_SIGNED_32:                                                             \
     case RS_TYPE_UNSIGNED_32:                                                           \
@@ -88,7 +93,7 @@
         ptr = _env->GetIntArrayElements((jintArray)data, flag);                         \
         typeBytes = 4;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, JNI_ABORT);         \
+        _env->ReleaseIntArrayElements((jintArray)data, (jint *)ptr, relFlag);           \
         return;                                                                         \
     case RS_TYPE_SIGNED_64:                                                             \
     case RS_TYPE_UNSIGNED_64:                                                           \
@@ -96,7 +101,7 @@
         ptr = _env->GetLongArrayElements((jlongArray)data, flag);                       \
         typeBytes = 8;                                                                  \
         fnc(__VA_ARGS__);                                                               \
-        _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, JNI_ABORT);      \
+        _env->ReleaseLongArrayElements((jlongArray)data, (jlong *)ptr, relFlag);        \
         return;                                                                         \
     default:                                                                            \
         break;                                                                          \
@@ -672,6 +677,7 @@
 }
 
 
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
                   jint count, jobject data, jint sizeBytes, jint dataType)
@@ -679,9 +685,10 @@
     RsAllocation *alloc = (RsAllocation *)_alloc;
     LOG_API("nAllocation1DData, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
             (RsContext)con, (RsAllocation)alloc, offset, count, sizeBytes, dataType);
-    PER_ARRAY_TYPE(NULL, rsAllocation1DData, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
+    PER_ARRAY_TYPE(NULL, rsAllocation1DData, true, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
+// Copies from the Java array data into the Allocation pointed to by alloc.
 static void
 //    native void rsnAllocationElementData1D(long con, long id, int xoff, int compIdx, byte[] d, int sizeBytes);
 nAllocationElementData1D(JNIEnv *_env, jobject _this, jlong con, jlong alloc, jint offset, jint lod, jint compIdx, jbyteArray data, jint sizeBytes)
@@ -693,6 +700,7 @@
     _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
 }
 
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
                   jint w, jint h, jobject data, jint sizeBytes, jint dataType)
@@ -701,9 +709,11 @@
     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
     LOG_API("nAllocation2DData, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) type(%i)",
             (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
-    PER_ARRAY_TYPE(NULL, rsAllocation2DData, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
+    PER_ARRAY_TYPE(NULL, rsAllocation2DData, true, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
 }
 
+// Copies from the Allocation pointed to by srcAlloc into the Allocation
+// pointed to by dstAlloc.
 static void
 nAllocationData2D_alloc(JNIEnv *_env, jobject _this, jlong con,
                         jlong dstAlloc, jint dstXoff, jint dstYoff,
@@ -728,6 +738,7 @@
                             srcMip, srcFace);
 }
 
+// Copies from the Java object data into the Allocation pointed to by _alloc.
 static void
 nAllocationData3D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint zoff, jint lod,
                     jint w, jint h, jint d, jobject data, int sizeBytes, int dataType)
@@ -735,9 +746,11 @@
     RsAllocation *alloc = (RsAllocation *)_alloc;
     LOG_API("nAllocation3DData, con(%p), alloc(%p), xoff(%i), yoff(%i), zoff(%i), lod(%i), w(%i), h(%i), d(%i), sizeBytes(%i)",
             (RsContext)con, (RsAllocation)alloc, xoff, yoff, zoff, lod, w, h, d, sizeBytes);
-    PER_ARRAY_TYPE(NULL, rsAllocation3DData, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
+    PER_ARRAY_TYPE(NULL, rsAllocation3DData, true, (RsContext)con, alloc, xoff, yoff, zoff, lod, w, h, d, ptr, sizeBytes, 0);
 }
 
+// Copies from the Allocation pointed to by srcAlloc into the Allocation
+// pointed to by dstAlloc.
 static void
 nAllocationData3D_alloc(JNIEnv *_env, jobject _this, jlong con,
                         jlong dstAlloc, jint dstXoff, jint dstYoff, jint dstZoff,
@@ -761,14 +774,16 @@
 }
 
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jobject data, int dataType)
 {
     RsAllocation *alloc = (RsAllocation *)_alloc;
     LOG_API("nAllocationRead, con(%p), alloc(%p)", (RsContext)con, (RsAllocation)alloc);
-    PER_ARRAY_TYPE(0, rsAllocationRead, (RsContext)con, alloc, ptr, len * typeBytes);
+    PER_ARRAY_TYPE(0, rsAllocationRead, false, (RsContext)con, alloc, ptr, len * typeBytes);
 }
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead1D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint offset, jint lod,
                   jint count, jobject data, int sizeBytes, int dataType)
@@ -776,9 +791,10 @@
     RsAllocation *alloc = (RsAllocation *)_alloc;
     LOG_API("nAllocation1DRead, con(%p), adapter(%p), offset(%i), count(%i), sizeBytes(%i), dataType(%i)",
             (RsContext)con, alloc, offset, count, sizeBytes, dataType);
-    PER_ARRAY_TYPE(0, rsAllocation1DRead, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
+    PER_ARRAY_TYPE(0, rsAllocation1DRead, false, (RsContext)con, alloc, offset, lod, count, ptr, sizeBytes);
 }
 
+// Copies from the Allocation pointed to by _alloc into the Java object data.
 static void
 nAllocationRead2D(JNIEnv *_env, jobject _this, jlong con, jlong _alloc, jint xoff, jint yoff, jint lod, jint _face,
                   jint w, jint h, jobject data, int sizeBytes, int dataType)
@@ -787,7 +803,7 @@
     RsAllocationCubemapFace face = (RsAllocationCubemapFace)_face;
     LOG_API("nAllocation2DRead, con(%p), adapter(%p), xoff(%i), yoff(%i), w(%i), h(%i), len(%i) type(%i)",
             (RsContext)con, alloc, xoff, yoff, w, h, sizeBytes, dataType);
-    PER_ARRAY_TYPE(0, rsAllocation2DRead, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
+    PER_ARRAY_TYPE(0, rsAllocation2DRead, false, (RsContext)con, alloc, xoff, yoff, lod, face, w, h, ptr, sizeBytes, 0);
 }
 
 static jlong
@@ -1023,7 +1039,7 @@
     jint len = _env->GetArrayLength(data);
     jbyte *ptr = _env->GetByteArrayElements(data, NULL);
     rsScriptGetVarV((RsContext)con, (RsScript)script, slot, ptr, len);
-    _env->ReleaseByteArrayElements(data, ptr, JNI_ABORT);
+    _env->ReleaseByteArrayElements(data, ptr, 0);
 }
 
 static void
diff --git a/services/Android.mk b/services/Android.mk
index 165f456..5fcef64 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -25,7 +25,8 @@
     backup \
     devicepolicy \
     print \
-    usb
+    usb \
+    voiceinteraction
 
 # The convention is to name each service module 'services.$(module_name)'
 LOCAL_STATIC_JAVA_LIBRARIES := $(addprefix services.,$(services))
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 35f873e..3619112 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -132,6 +132,8 @@
     private static final String TEMPORARY_ENABLE_ACCESSIBILITY_UNTIL_KEYGUARD_REMOVED =
             "temporaryEnableAccessibilityStateUntilKeyguardRemoved";
 
+    private static final String GET_WINDOW_TOKEN = "getWindowToken";
+
     private static final ComponentName sFakeAccessibilityServiceComponentName =
             new ComponentName("foo.bar", "FakeService");
 
@@ -164,8 +166,6 @@
 
     private final Point mTempPoint = new Point();
 
-    private final Display mDefaultDisplay;
-
     private final PackageManager mPackageManager;
 
     private final WindowManagerInternal mWindowManagerService;
@@ -174,7 +174,7 @@
 
     private final MainHandler mMainHandler;
 
-    private Service mQueryBridge;
+    private InteractionBridge mInteractionBridge;
 
     private AlertDialog mEnableTouchExplorationDialog;
 
@@ -230,10 +230,6 @@
         mWindowManagerService = LocalServices.getService(WindowManagerInternal.class);
         mSecurityPolicy = new SecurityPolicy();
         mMainHandler = new MainHandler(mContext.getMainLooper());
-        //TODO: (multi-display) We need to support multiple displays.
-        DisplayManager displayManager = (DisplayManager)
-                mContext.getSystemService(Context.DISPLAY_SERVICE);
-        mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
         registerBroadcastReceivers();
         new AccessibilityContentObserver(mMainHandler).register(
                 context.getContentResolver());
@@ -360,6 +356,7 @@
         }, UserHandle.ALL, intentFilter, null, null);
     }
 
+    @Override
     public int addClient(IAccessibilityManagerClient client, int userId) {
         synchronized (mLock) {
             final int resolvedUserId = mSecurityPolicy
@@ -388,6 +385,7 @@
         }
     }
 
+    @Override
     public boolean sendAccessibilityEvent(AccessibilityEvent event, int userId) {
         synchronized (mLock) {
             final int resolvedUserId = mSecurityPolicy
@@ -397,7 +395,8 @@
                 return true; // yes, recycle the event
             }
             if (mSecurityPolicy.canDispatchAccessibilityEventLocked(event)) {
-                mSecurityPolicy.updateActiveWindowLocked(event.getWindowId(), event.getEventType());
+                mSecurityPolicy.updateActiveAndAccessibilityFocusedWindowLocked(event.getWindowId(),
+                        event.getSourceNodeId(), event.getEventType());
                 mSecurityPolicy.updateEventSourceLocked(event);
                 notifyAccessibilityServicesDelayedLocked(event, false);
                 notifyAccessibilityServicesDelayedLocked(event, true);
@@ -412,6 +411,7 @@
         return (OWN_PROCESS_ID != Binder.getCallingPid());
     }
 
+    @Override
     public List<AccessibilityServiceInfo> getInstalledAccessibilityServiceList(int userId) {
         synchronized (mLock) {
             final int resolvedUserId = mSecurityPolicy
@@ -430,6 +430,7 @@
         }
     }
 
+    @Override
     public List<AccessibilityServiceInfo> getEnabledAccessibilityServiceList(int feedbackType,
             int userId) {
         List<AccessibilityServiceInfo> result = null;
@@ -463,6 +464,7 @@
         return result;
     }
 
+    @Override
     public void interrupt(int userId) {
         CopyOnWriteArrayList<Service> services;
         synchronized (mLock) {
@@ -485,6 +487,7 @@
         }
     }
 
+    @Override
     public int addAccessibilityInteractionConnection(IWindow windowToken,
             IAccessibilityInteractionConnection connection, int userId) throws RemoteException {
         synchronized (mLock) {
@@ -521,6 +524,7 @@
         }
     }
 
+    @Override
     public void removeAccessibilityInteractionConnection(IWindow window) {
         synchronized (mLock) {
             mSecurityPolicy.resolveCallingUserIdEnforcingPermissionsLocked(
@@ -570,6 +574,7 @@
         return -1;
     }
 
+    @Override
     public void registerUiTestAutomationService(IBinder owner,
             IAccessibilityServiceClient serviceClient,
             AccessibilityServiceInfo accessibilityServiceInfo) {
@@ -612,6 +617,7 @@
         }
     }
 
+    @Override
     public void unregisterUiTestAutomationService(IAccessibilityServiceClient serviceClient) {
         synchronized (mLock) {
             UserState userState = getCurrentUserStateLocked();
@@ -630,6 +636,7 @@
         }
     }
 
+    @Override
     public void temporaryEnableAccessibilityStateUntilKeyguardRemoved(
             ComponentName service, boolean touchExplorationEnabled) {
         mSecurityPolicy.enforceCallingPermission(
@@ -662,6 +669,29 @@
         }
     }
 
+    @Override
+    public IBinder getWindowToken(int windowId) {
+        mSecurityPolicy.enforceCallingPermission(
+                Manifest.permission.RETRIEVE_WINDOW_TOKEN,
+                GET_WINDOW_TOKEN);
+        synchronized (mLock) {
+            final int resolvedUserId = mSecurityPolicy
+                    .resolveCallingUserIdEnforcingPermissionsLocked(
+                            UserHandle.getCallingUserId());
+            if (resolvedUserId != mCurrentUserId) {
+                return null;
+            }
+            if (mSecurityPolicy.findWindowById(windowId) == null) {
+                return null;
+            }
+            IBinder token = mGlobalWindowTokens.get(windowId);
+            if (token != null) {
+                return token;
+            }
+            return getCurrentUserStateLocked().mWindowTokens.get(windowId);
+        }
+    }
+
     boolean onGesture(int gestureId) {
         synchronized (mLock) {
             boolean handled = notifyGestureLocked(gestureId, false);
@@ -689,47 +719,9 @@
      * @param outBounds The output to which to write the focus bounds.
      * @return Whether accessibility focus was found and the bounds are populated.
      */
-    // TODO: (multi-display) Make sure this works for multiple displays. 
-    boolean getAccessibilityFocusBoundsInActiveWindow(Rect outBounds) {
-        // Instead of keeping track of accessibility focus events per
-        // window to be able to find the focus in the active window,
-        // we take a stateless approach and look it up. This is fine
-        // since we do this only when the user clicks/long presses.
-        Service service = getQueryBridge();
-        final int connectionId = service.mId;
-        AccessibilityInteractionClient client = AccessibilityInteractionClient.getInstance();
-        client.addConnection(connectionId, service);
-        try {
-            AccessibilityNodeInfo root = AccessibilityInteractionClient.getInstance()
-                    .getRootInActiveWindow(connectionId);
-            if (root == null) {
-                return false;
-            }
-            AccessibilityNodeInfo focus = root.findFocus(
-                    AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
-            if (focus == null) {
-                return false;
-            }
-            focus.getBoundsInScreen(outBounds);
-
-            MagnificationSpec spec = service.getCompatibleMagnificationSpec(focus.getWindowId());
-            if (spec != null && !spec.isNop()) {
-                outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
-                outBounds.scale(1 / spec.scale);
-            }
-
-            // Clip to the window rectangle.
-            Rect windowBounds = mTempRect;
-            getActiveWindowBounds(windowBounds);
-            outBounds.intersect(windowBounds);
-            // Clip to the screen rectangle.
-            mDefaultDisplay.getRealSize(mTempPoint);
-            outBounds.intersect(0,  0,  mTempPoint.x, mTempPoint.y);
-
-            return true;
-        } finally {
-            client.removeConnection(connectionId);
-        }
+    // TODO: (multi-display) Make sure this works for multiple displays.
+    boolean getAccessibilityFocusBounds(Rect outBounds) {
+        return getInteractionBridgeLocked().getAccessibilityFocusBoundsNotLocked(outBounds);
     }
 
     /**
@@ -820,14 +812,11 @@
         }
     }
 
-    private Service getQueryBridge() {
-        if (mQueryBridge == null) {
-            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
-            info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
-            mQueryBridge = new Service(UserHandle.USER_NULL,
-                    sFakeAccessibilityServiceComponentName, info);
+    private InteractionBridge getInteractionBridgeLocked() {
+        if (mInteractionBridge == null) {
+            mInteractionBridge = new InteractionBridge();
         }
-        return mQueryBridge;
+        return mInteractionBridge;
     }
 
     private boolean notifyGestureLocked(int gestureId, boolean isDefault) {
@@ -1298,9 +1287,10 @@
     private void onUserStateChangedLocked(UserState userState) {
         // TODO: Remove this hack
         mInitialized = true;
-        updateLegacyCapabilities(userState);
+        updateLegacyCapabilitiesLocked(userState);
         updateServicesLocked(userState);
-        updateWindowsForAccessibilityCallback(userState);
+        updateWindowsForAccessibilityCallbackLocked(userState);
+        updateAccessibilityFocusBehaviorLocked(userState);
         updateFilterKeyEventsLocked(userState);
         updateTouchExplorationLocked(userState);
         updateEnhancedWebAccessibilityLocked(userState);
@@ -1309,7 +1299,29 @@
         scheduleUpdateClientsIfNeededLocked(userState);
     }
 
-    private void updateWindowsForAccessibilityCallback(UserState userState) {
+    private void updateAccessibilityFocusBehaviorLocked(UserState userState) {
+        // If there is no service that can operate with interactive windows
+        // then we keep the old behavior where a window loses accessibility
+        // focus if it is no longer active. This still changes the behavior
+        // for services that do not operate with interactive windows and run
+        // at the same time as the one(s) which does. In practice however,
+        // there is only one service that uses accessibility focus and it
+        // is typically the one that operates with interactive windows, So,
+        // this is fine. Note that to allow a service to work across windows
+        // we have to allow accessibility focus stay in any of them. Sigh...
+        List<Service> boundServices = userState.mBoundServices;
+        final int boundServiceCount = boundServices.size();
+        for (int i = 0; i < boundServiceCount; i++) {
+            Service boundService = boundServices.get(i);
+            if (boundService.canRetrieveInteractiveWindowsLocked()) {
+                userState.mAccessibilityFocusOnlyInActiveWindow = false;
+                return;
+            }
+        }
+        userState.mAccessibilityFocusOnlyInActiveWindow = true;
+    }
+
+    private void updateWindowsForAccessibilityCallbackLocked(UserState userState) {
         if (userState.mIsAccessibilityEnabled) {
             // We observe windows for accessibility only if there is at least
             // one bound service that can retrieve window content that specified
@@ -1322,8 +1334,7 @@
             final int boundServiceCount = boundServices.size();
             for (int i = 0; i < boundServiceCount; i++) {
                 Service boundService = boundServices.get(i);
-                if (mSecurityPolicy.canRetrieveWindowContentLocked(boundService)
-                        && boundService.mRetrieveInteractiveWindows) {
+                if (boundService.canRetrieveInteractiveWindowsLocked()) {
                     boundServiceCanRetrieveInteractiveWindows = true;
                     break;
                 }
@@ -1346,7 +1357,7 @@
         }
     }
 
-    private void updateLegacyCapabilities(UserState userState) {
+    private void updateLegacyCapabilitiesLocked(UserState userState) {
         // Up to JB-MR1 we had a white list with services that can enable touch
         // exploration. When a service is first started we show a dialog to the
         // use to get a permission to white list the service.
@@ -1547,6 +1558,18 @@
         DisplayAdjustmentUtils.applyAdjustments(mContext, userState.mUserId);
     }
 
+    private MagnificationSpec getCompatibleMagnificationSpecLocked(int windowId) {
+        IBinder windowToken = mGlobalWindowTokens.get(windowId);
+        if (windowToken == null) {
+            windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+        }
+        if (windowToken != null) {
+            return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
+                    windowToken);
+        }
+        return null;
+    }
+
     @Override
     public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
         mSecurityPolicy.enforceCallingPermission(Manifest.permission.DUMP, FUNCTION_DUMP);
@@ -1623,6 +1646,7 @@
         public static final int MSG_UPDATE_INPUT_FILTER = 6;
         public static final int MSG_SHOW_ENABLED_TOUCH_EXPLORATION_DIALOG = 7;
         public static final int MSG_SEND_KEY_EVENT_TO_INPUT_FILTER = 8;
+        public static final int MSG_CLEAR_ACCESSIBILITY_FOCUS = 9;
 
         public MainHandler(Looper looper) {
             super(looper);
@@ -1678,6 +1702,15 @@
                     Service service = (Service) msg.obj;
                     showEnableTouchExplorationDialog(service);
                 } break;
+
+                case MSG_CLEAR_ACCESSIBILITY_FOCUS: {
+                    final int windowId = msg.arg1;
+                    InteractionBridge bridge;
+                    synchronized (mLock) {
+                        bridge = getInteractionBridgeLocked();
+                    }
+                    bridge.clearAccessibilityFocusNotLocked(windowId);
+                } break;
             }
         }
 
@@ -1946,6 +1979,11 @@
             }
         }
 
+        public boolean canRetrieveInteractiveWindowsLocked() {
+            return mSecurityPolicy.canRetrieveWindowContentLocked(this)
+                    && mRetrieveInteractiveWindows;
+        }
+
         @Override
         public void setServiceInfo(AccessibilityServiceInfo info) {
             final long identity = Binder.clearCallingIdentity();
@@ -2074,7 +2112,7 @@
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfosByViewId(accessibilityNodeId,
                         viewIdResName, interactionId, callback, mFetchFlags, interrogatingPid,
@@ -2118,7 +2156,7 @@
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfosByText(accessibilityNodeId, text,
                         interactionId, callback, mFetchFlags, interrogatingPid, interrogatingTid,
@@ -2162,7 +2200,7 @@
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findAccessibilityNodeInfoByAccessibilityId(accessibilityNodeId,
                         interactionId, callback, mFetchFlags | flags, interrogatingPid,
@@ -2192,7 +2230,8 @@
                 if (resolvedUserId != mCurrentUserId) {
                     return false;
                 }
-                resolvedWindowId = resolveAccessibilityWindowIdLocked(accessibilityWindowId);
+                resolvedWindowId = resolveAccessibilityWindowIdForFindFocusLocked(
+                        accessibilityWindowId, focusType);
                 final boolean permissionGranted =
                     mSecurityPolicy.canGetAccessibilityNodeInfoLocked(this, resolvedWindowId);
                 if (!permissionGranted) {
@@ -2206,14 +2245,14 @@
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.findFocus(accessibilityNodeId, focusType, interactionId, callback,
                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
                 return true;
             } catch (RemoteException re) {
                 if (DEBUG) {
-                    Slog.e(LOG_TAG, "Error calling findAccessibilityFocus()");
+                    Slog.e(LOG_TAG, "Error calling findFocus()");
                 }
             } finally {
                 Binder.restoreCallingIdentity(identityToken);
@@ -2249,7 +2288,7 @@
             }
             final int interrogatingPid = Binder.getCallingPid();
             final long identityToken = Binder.clearCallingIdentity();
-            MagnificationSpec spec = getCompatibleMagnificationSpec(resolvedWindowId);
+            MagnificationSpec spec = getCompatibleMagnificationSpecLocked(resolvedWindowId);
             try {
                 connection.focusSearch(accessibilityNodeId, direction, interactionId, callback,
                         mFetchFlags, interrogatingPid, interrogatingTid, spec);
@@ -2694,16 +2733,18 @@
             return accessibilityWindowId;
         }
 
-        private MagnificationSpec getCompatibleMagnificationSpec(int windowId) {
-            IBinder windowToken = mGlobalWindowTokens.get(windowId);
-            if (windowToken == null) {
-                windowToken = getCurrentUserStateLocked().mWindowTokens.get(windowId);
+        private int resolveAccessibilityWindowIdForFindFocusLocked(int windowId, int focusType) {
+            if (windowId == AccessibilityNodeInfo.ACTIVE_WINDOW_ID) {
+                return mSecurityPolicy.mActiveWindowId;
             }
-            if (windowToken != null) {
-                return mWindowManagerService.getCompatibleMagnificationSpecForWindow(
-                        windowToken);
+            if (windowId == AccessibilityNodeInfo.ANY_WINDOW_ID) {
+                if (focusType == AccessibilityNodeInfo.FOCUS_INPUT) {
+                    return mSecurityPolicy.mFocusedWindowId;
+                } else if (focusType == AccessibilityNodeInfo.FOCUS_ACCESSIBILITY) {
+                    return mSecurityPolicy.mAccessibilityFocusedWindowId;
+                }
             }
-            return null;
+            return windowId;
         }
 
         private final class InvocationHandler extends Handler {
@@ -2972,7 +3013,6 @@
                     return AccessibilityWindowInfo.TYPE_INPUT_METHOD;
                 }
 
-                case WindowManager.LayoutParams.TYPE_KEYGUARD:
                 case WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG:
                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR:
                 case WindowManager.LayoutParams.TYPE_NAVIGATION_BAR_PANEL:
@@ -2996,7 +3036,86 @@
         }
     }
 
+    private final class InteractionBridge {
+        private final Display mDefaultDisplay;
+        private final int mConnectionId;
+        private final AccessibilityInteractionClient mClient;
+
+        public InteractionBridge() {
+            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
+            info.setCapabilities(AccessibilityServiceInfo.CAPABILITY_CAN_RETRIEVE_WINDOW_CONTENT);
+            info.flags |= AccessibilityServiceInfo.FLAG_RETRIEVE_INTERACTIVE_WINDOWS;
+            info.flags |= AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
+            Service service = new Service(UserHandle.USER_NULL,
+                    sFakeAccessibilityServiceComponentName, info);
+
+            mConnectionId = service.mId;
+
+            mClient = AccessibilityInteractionClient.getInstance();
+            mClient.addConnection(mConnectionId, service);
+
+            //TODO: (multi-display) We need to support multiple displays.
+            DisplayManager displayManager = (DisplayManager)
+                    mContext.getSystemService(Context.DISPLAY_SERVICE);
+            mDefaultDisplay = displayManager.getDisplay(Display.DEFAULT_DISPLAY);
+        }
+
+        public void clearAccessibilityFocusNotLocked(int windowId) {
+            AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked(windowId);
+            if (focus != null) {
+                focus.performAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
+            }
+        }
+
+        public boolean getAccessibilityFocusBoundsNotLocked(Rect outBounds) {
+            AccessibilityNodeInfo focus = getAccessibilityFocusNotLocked();
+            if (focus == null) {
+                return false;
+            }
+
+            synchronized (mLock) {
+                focus.getBoundsInScreen(outBounds);
+
+                MagnificationSpec spec = getCompatibleMagnificationSpecLocked(focus.getWindowId());
+                if (spec != null && !spec.isNop()) {
+                    outBounds.offset((int) -spec.offsetX, (int) -spec.offsetY);
+                    outBounds.scale(1 / spec.scale);
+                }
+
+                // Clip to the window rectangle.
+                Rect windowBounds = mTempRect;
+                getActiveWindowBounds(windowBounds);
+                outBounds.intersect(windowBounds);
+
+                // Clip to the screen rectangle.
+                mDefaultDisplay.getRealSize(mTempPoint);
+                outBounds.intersect(0, 0, mTempPoint.x, mTempPoint.y);
+
+                return true;
+            }
+        }
+
+        private AccessibilityNodeInfo getAccessibilityFocusNotLocked() {
+            final int focusedWindowId;
+            synchronized (mLock) {
+                focusedWindowId = mSecurityPolicy.mAccessibilityFocusedWindowId;
+                if (focusedWindowId == SecurityPolicy.INVALID_WINDOW_ID) {
+                    return null;
+                }
+            }
+            return getAccessibilityFocusNotLocked(focusedWindowId);
+        }
+
+        private AccessibilityNodeInfo getAccessibilityFocusNotLocked(int windowId) {
+            return mClient.findFocus(mConnectionId,
+                    windowId, AccessibilityNodeInfo.ROOT_NODE_ID,
+                    AccessibilityNodeInfo.FOCUS_ACCESSIBILITY);
+        }
+    }
+
     final class SecurityPolicy {
+        public static final int INVALID_WINDOW_ID = -1;
+
         private static final int VALID_ACTIONS =
             AccessibilityNodeInfo.ACTION_CLICK
             | AccessibilityNodeInfo.ACTION_LONG_CLICK
@@ -3040,8 +3159,11 @@
         public final List<AccessibilityWindowInfo> mWindows =
                 new ArrayList<AccessibilityWindowInfo>();
 
-        public int mActiveWindowId;
-        public int mFocusedWindowId;
+        public int mActiveWindowId = INVALID_WINDOW_ID;
+        public int mFocusedWindowId = INVALID_WINDOW_ID;
+        public int mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
+        public long mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+
         public AccessibilityEvent mShowingFocusedWindowEvent;
 
         private boolean mTouchInteractionInProgress;
@@ -3094,9 +3216,9 @@
                 mWindows.remove(i).recycle();
             }
 
-            mFocusedWindowId = -1;
+            mFocusedWindowId = INVALID_WINDOW_ID;
             if (!mTouchInteractionInProgress) {
-                mActiveWindowId = -1;
+                mActiveWindowId = INVALID_WINDOW_ID;
             }
 
             // If the active window goes away while the user is touch exploring we
@@ -3124,7 +3246,7 @@
                 }
 
                 if (mTouchInteractionInProgress && activeWindowGone) {
-                    mActiveWindowId = -1;
+                    mActiveWindowId = INVALID_WINDOW_ID;
                 }
 
                 // Focused window may change the active one, so set the
@@ -3158,7 +3280,8 @@
             }
         }
 
-        public void updateActiveWindowLocked(int windowId, int eventType) {
+        public void updateActiveAndAccessibilityFocusedWindowLocked(int windowId, long nodeId,
+                int eventType) {
             // The active window is either the window that has input focus or
             // the window that the user is currently touching. If the user is
             // touching a window that does not have input focus as soon as the
@@ -3176,8 +3299,9 @@
                     // The active window also determined events from which
                     // windows are delivered.
                     synchronized (mLock) {
+                        mFocusedWindowId = getFocusedWindowId();
                         if (mWindowsForAccessibilityCallback == null
-                                && windowId == getFocusedWindowId()) {
+                                && windowId == mFocusedWindowId) {
                             mActiveWindowId = windowId;
                         }
                     }
@@ -3192,6 +3316,29 @@
                         }
                     }
                 } break;
+
+                case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
+                    synchronized (mLock) {
+                        if (mAccessibilityFocusedWindowId != windowId) {
+                            mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
+                                    mAccessibilityFocusedWindowId, 0).sendToTarget();
+                            mAccessibilityFocusedWindowId = windowId;
+                            mAccessibilityFocusNodeId = nodeId;
+                        }
+                    }
+                } break;
+
+                case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
+                    synchronized (mLock) {
+                        if (mAccessibilityFocusNodeId == nodeId) {
+                            mAccessibilityFocusNodeId = AccessibilityNodeInfo.UNDEFINED_ITEM_ID;
+                        }
+                        if (mAccessibilityFocusNodeId == AccessibilityNodeInfo.UNDEFINED_ITEM_ID
+                                && mAccessibilityFocusedWindowId == windowId) {
+                            mAccessibilityFocusedWindowId = INVALID_WINDOW_ID;
+                        }
+                    }
+                } break;
             }
         }
 
@@ -3212,7 +3359,19 @@
                 // (they are a result of user touching the screen) so change of
                 // the active window before all hover accessibility events from
                 // the touched window are delivered is fine.
+                final int oldActiveWindow = mSecurityPolicy.mActiveWindowId;
                 setActiveWindowLocked(mFocusedWindowId);
+
+                // If there is no service that can operate with active windows
+                // we keep accessibility focus behavior to constrain it only in
+                // the active window. Look at updateAccessibilityFocusBehaviorLocked
+                // for details.
+                if (oldActiveWindow != mSecurityPolicy.mActiveWindowId
+                        && mAccessibilityFocusedWindowId == oldActiveWindow
+                        && getCurrentUserStateLocked().mAccessibilityFocusOnlyInActiveWindow) {
+                    mMainHandler.obtainMessage(MainHandler.MSG_CLEAR_ACCESSIBILITY_FOCUS,
+                            oldActiveWindow, 0).sendToTarget();
+                }
             }
         }
 
@@ -3367,6 +3526,7 @@
         public boolean mIsDisplayMagnificationEnabled;
         public boolean mIsFilterKeyEventsEnabled;
         public boolean mHasDisplayColorAdjustment;
+        public boolean mAccessibilityFocusOnlyInActiveWindow;
 
         private Service mUiAutomationService;
         private IAccessibilityServiceClient mUiAutomationServiceClient;
diff --git a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
index 43f12eb..ac0ca0a 100644
--- a/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
+++ b/services/accessibility/java/com/android/server/accessibility/TouchExplorer.java
@@ -1159,7 +1159,7 @@
                 // No last touch explored event but there is accessibility focus in
                 // the active window. We click in the middle of the focus bounds.
                 Rect focusBounds = mTempRect;
-                if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                if (mAms.getAccessibilityFocusBounds(focusBounds)) {
                     clickLocationX = focusBounds.centerX();
                     clickLocationY = focusBounds.centerY();
                 } else {
@@ -1177,7 +1177,7 @@
                     mAms.getActiveWindowBounds(activeWindowBounds);
                     if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
                         Rect focusBounds = mTempRect;
-                        if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                        if (mAms.getAccessibilityFocusBounds(focusBounds)) {
                             if (!focusBounds.contains(clickLocationX, clickLocationY)) {
                                 clickLocationX = focusBounds.centerX();
                                 clickLocationY = focusBounds.centerY();
@@ -1332,7 +1332,7 @@
                 // No last touch explored event but there is accessibility focus in
                 // the active window. We click in the middle of the focus bounds.
                 Rect focusBounds = mTempRect;
-                if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                if (mAms.getAccessibilityFocusBounds(focusBounds)) {
                     clickLocationX = focusBounds.centerX();
                     clickLocationY = focusBounds.centerY();
                 } else {
@@ -1350,7 +1350,7 @@
                     mAms.getActiveWindowBounds(activeWindowBounds);
                     if (activeWindowBounds.contains(clickLocationX, clickLocationY)) {
                         Rect focusBounds = mTempRect;
-                        if (mAms.getAccessibilityFocusBoundsInActiveWindow(focusBounds)) {
+                        if (mAms.getAccessibilityFocusBounds(focusBounds)) {
                             if (!focusBounds.contains(clickLocationX, clickLocationY)) {
                                 clickLocationX = focusBounds.centerX();
                                 clickLocationY = focusBounds.centerY();
diff --git a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
index 2f56e62..87b1d32 100644
--- a/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
+++ b/services/appwidget/java/com/android/server/appwidget/AppWidgetServiceImpl.java
@@ -50,6 +50,7 @@
 import android.os.UserHandle;
 import android.util.AtomicFile;
 import android.util.AttributeSet;
+import android.util.MutableInt;
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -86,8 +87,6 @@
 import java.util.Map.Entry;
 import java.util.Set;
 
-import libcore.util.MutableInt;
-
 class AppWidgetServiceImpl {
 
     private static final String KEYGUARD_HOST_PACKAGE = "com.android.keyguard";
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index 0b688b6..0082b1e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -74,6 +74,8 @@
 import android.os.Environment.UserEnvironment;
 import android.os.storage.IMountService;
 import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.EventLog;
 import android.util.Log;
 import android.util.Slog;
@@ -142,9 +144,6 @@
 import javax.crypto.spec.PBEKeySpec;
 import javax.crypto.spec.SecretKeySpec;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-
 public class BackupManagerService extends IBackupManager.Stub {
 
     private static final String TAG = "BackupManagerService";
@@ -2471,7 +2470,7 @@
                 // operations any more during this pass).
                 Slog.w(TAG, "Unable to save widget state for " + pkgName);
                 try {
-                    Libcore.os.ftruncate(fd, filepos);
+                    Os.ftruncate(fd, filepos);
                 } catch (ErrnoException ee) {
                     Slog.w(TAG, "Unable to roll back!");
                 }
diff --git a/services/core/java/com/android/server/BootReceiver.java b/services/core/java/com/android/server/BootReceiver.java
index bce85ce..7249985 100644
--- a/services/core/java/com/android/server/BootReceiver.java
+++ b/services/core/java/com/android/server/BootReceiver.java
@@ -106,22 +106,33 @@
             .append("Kernel: ")
             .append(FileUtils.readTextFile(new File("/proc/version"), 1024, "...\n"))
             .append("\n").toString();
+        final String bootReason = SystemProperties.get("ro.boot.bootreason", null);
 
         String recovery = RecoverySystem.handleAftermath();
         if (recovery != null && db != null) {
             db.addText("SYSTEM_RECOVERY_LOG", headers + recovery);
         }
 
+        String lastKmsgFooter = "";
+        if (bootReason != null) {
+            lastKmsgFooter = new StringBuilder(512)
+                .append("\n")
+                .append("Boot info:\n")
+                .append("Last boot reason: ").append(bootReason).append("\n")
+                .toString();
+        }
+
         if (SystemProperties.getLong("ro.runtime.firstboot", 0) == 0) {
             String now = Long.toString(System.currentTimeMillis());
             SystemProperties.set("ro.runtime.firstboot", now);
             if (db != null) db.addText("SYSTEM_BOOT", headers);
 
             // Negative sizes mean to take the *tail* of the file (see FileUtils.readTextFile())
-            addFileToDropBox(db, prefs, headers, "/proc/last_kmsg",
-                    -LOG_SIZE, "SYSTEM_LAST_KMSG");
-            addFileToDropBox(db, prefs, headers, "/sys/fs/pstore/console-ramoops",
-                    -LOG_SIZE, "SYSTEM_LAST_KMSG");
+            addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter,
+                    "/proc/last_kmsg", -LOG_SIZE, "SYSTEM_LAST_KMSG");
+            addFileWithFootersToDropBox(db, prefs, headers, lastKmsgFooter,
+                    "/sys/fs/pstore/console-ramoops", -LOG_SIZE,
+                    "SYSTEM_LAST_KMSG");
             addFileToDropBox(db, prefs, headers, "/cache/recovery/log",
                     -LOG_SIZE, "SYSTEM_RECOVERY_LOG");
             addFileToDropBox(db, prefs, headers, "/data/dontpanic/apanic_console",
@@ -161,6 +172,14 @@
     private static void addFileToDropBox(
             DropBoxManager db, SharedPreferences prefs,
             String headers, String filename, int maxSize, String tag) throws IOException {
+        addFileWithFootersToDropBox(db, prefs, headers, "", filename, maxSize,
+                tag);
+    }
+
+    private static void addFileWithFootersToDropBox(
+            DropBoxManager db, SharedPreferences prefs,
+            String headers, String footers, String filename, int maxSize,
+            String tag) throws IOException {
         if (db == null || !db.isTagEnabled(tag)) return;  // Logging disabled
 
         File file = new File(filename);
@@ -176,7 +195,7 @@
         }
 
         Slog.i(TAG, "Copying " + filename + " to DropBox (" + tag + ")");
-        db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n"));
+        db.addText(tag, headers + FileUtils.readTextFile(file, maxSize, "[[TRUNCATED]]\n") + footers);
     }
 
     private static void addAuditErrorsToDropBox(DropBoxManager db,  SharedPreferences prefs,
diff --git a/services/core/java/com/android/server/EventLogTags.logtags b/services/core/java/com/android/server/EventLogTags.logtags
index 9768934..5083d44 100644
--- a/services/core/java/com/android/server/EventLogTags.logtags
+++ b/services/core/java/com/android/server/EventLogTags.logtags
@@ -63,6 +63,8 @@
 27500 notification_panel_revealed
 # when the notification panel is hidden
 27501 notification_panel_hidden
+# when notifications are newly displayed on screen, or disappear from screen
+27510 notification_visibility_changed (newlyVisibleKeys|3),(noLongerVisibleKeys|3)
 
 # ---------------------------
 # Watchdog.java
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e6163bd..d6ecb46 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -426,29 +426,54 @@
             Slog.e(TAG,  "no geocoder provider found");
         }
 
-        // bind to fused provider
-        FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
-        FusedProxy fusedProxy = FusedProxy.createAndBind(
-                mContext,
-                mLocationHandler,
-                flpHardwareProvider.getLocationHardware(),
-                com.android.internal.R.bool.config_enableFusedLocationOverlay,
-                com.android.internal.R.string.config_fusedLocationProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames);
-        if(fusedProxy == null) {
-            Slog.e(TAG, "No FusedProvider found.");
+        // bind to fused provider if supported
+        if (FlpHardwareProvider.isSupported()) {
+          FlpHardwareProvider flpHardwareProvider = FlpHardwareProvider.getInstance(mContext);
+          FusedProxy fusedProxy = FusedProxy.createAndBind(
+                  mContext,
+                  mLocationHandler,
+                  flpHardwareProvider.getLocationHardware(),
+                  com.android.internal.R.bool.config_enableFusedLocationOverlay,
+                  com.android.internal.R.string.config_fusedLocationProviderPackageName,
+                  com.android.internal.R.array.config_locationProviderPackageNames);
+          if(fusedProxy == null) {
+              Slog.e(TAG, "Unable to bind FusedProxy.");
+          }
+
+          // bind to geofence provider
+          GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
+                  com.android.internal.R.bool.config_enableGeofenceOverlay,
+                  com.android.internal.R.string.config_geofenceProviderPackageName,
+                  com.android.internal.R.array.config_locationProviderPackageNames,
+                  mLocationHandler,
+                  gpsProvider.getGpsGeofenceProxy(),
+                  flpHardwareProvider.getGeofenceHardware());
+          if (provider == null) {
+              Slog.e(TAG,  "Unable to bind FLP Geofence proxy.");
+          }
+        } else {
+          Slog.e(TAG, "FLP HAL not supported.");
         }
 
-        // bind to geofence provider
-        GeofenceProxy provider = GeofenceProxy.createAndBind(mContext,
-                com.android.internal.R.bool.config_enableGeofenceOverlay,
-                com.android.internal.R.string.config_geofenceProviderPackageName,
-                com.android.internal.R.array.config_locationProviderPackageNames,
-                mLocationHandler,
-                gpsProvider.getGpsGeofenceProxy(),
-                flpHardwareProvider.getGeofenceHardware());
-        if (provider == null) {
-            Slog.e(TAG,  "no geofence provider found");
+        String[] testProviderStrings = resources.getStringArray(
+                com.android.internal.R.array.config_testLocationProviders);
+        for (String testProviderString : testProviderStrings) {
+            String fragments[] = testProviderString.split(",");
+            String name = fragments[0].trim();
+            if (mProvidersByName.get(name) != null) {
+                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
+            }
+            ProviderProperties properties = new ProviderProperties(
+                    Boolean.parseBoolean(fragments[1]) /* requiresNetwork */,
+                    Boolean.parseBoolean(fragments[2]) /* requiresSatellite */,
+                    Boolean.parseBoolean(fragments[3]) /* requiresCell */,
+                    Boolean.parseBoolean(fragments[4]) /* hasMonetaryCost */,
+                    Boolean.parseBoolean(fragments[5]) /* supportsAltitude */,
+                    Boolean.parseBoolean(fragments[6]) /* supportsSpeed */,
+                    Boolean.parseBoolean(fragments[7]) /* supportsBearing */,
+                    Integer.parseInt(fragments[8]) /* powerRequirement */,
+                    Integer.parseInt(fragments[9]) /* accuracy */);
+            addTestProviderLocked(name, properties);
         }
     }
 
@@ -2204,7 +2229,6 @@
 
         long identity = Binder.clearCallingIdentity();
         synchronized (mLock) {
-            MockProvider provider = new MockProvider(name, this, properties);
             // remove the real provider if we are replacing GPS or network provider
             if (LocationManager.GPS_PROVIDER.equals(name)
                     || LocationManager.NETWORK_PROVIDER.equals(name)
@@ -2214,18 +2238,23 @@
                     removeProviderLocked(p);
                 }
             }
-            if (mProvidersByName.get(name) != null) {
-                throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
-            }
-            addProviderLocked(provider);
-            mMockProviders.put(name, provider);
-            mLastLocation.put(name, null);
-            mLastLocationCoarseInterval.put(name, null);
+            addTestProviderLocked(name, properties);
             updateProvidersLocked();
         }
         Binder.restoreCallingIdentity(identity);
     }
 
+    private void addTestProviderLocked(String name, ProviderProperties properties) {
+        if (mProvidersByName.get(name) != null) {
+            throw new IllegalArgumentException("Provider \"" + name + "\" already exists");
+        }
+        MockProvider provider = new MockProvider(name, this, properties);
+        addProviderLocked(provider);
+        mMockProviders.put(name, provider);
+        mLastLocation.put(name, null);
+        mLastLocationCoarseInterval.put(name, null);
+    }
+
     @Override
     public void removeTestProvider(String provider) {
         checkMockPermissionsSafe();
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index b6e761c..7ec9b82 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -52,6 +52,7 @@
 import android.os.storage.IMountShutdownObserver;
 import android.os.storage.IObbActionListener;
 import android.os.storage.OnObbStateChangeListener;
+import android.os.storage.StorageManager;
 import android.os.storage.StorageResultCode;
 import android.os.storage.StorageVolume;
 import android.text.TextUtils;
@@ -2145,8 +2146,8 @@
         }
     }
 
-    public int encryptStorage(String password) {
-        if (TextUtils.isEmpty(password)) {
+    public int encryptStorage(int type, String password) {
+        if (TextUtils.isEmpty(password) && type != StorageManager.CRYPT_TYPE_DEFAULT) {
             throw new IllegalArgumentException("password cannot be empty");
         }
 
@@ -2160,7 +2161,7 @@
         }
 
         try {
-            mConnector.execute("cryptfs", "enablecrypto", "inplace",
+            mConnector.execute("cryptfs", "enablecrypto", "inplace", CRYPTO_TYPES[type],
                                new SensitiveArg(toHex(password)));
         } catch (NativeDaemonConnectorException e) {
             // Encryption failed
diff --git a/services/core/java/com/android/server/NativeDaemonConnector.java b/services/core/java/com/android/server/NativeDaemonConnector.java
index 62eb663..0d1e122 100644
--- a/services/core/java/com/android/server/NativeDaemonConnector.java
+++ b/services/core/java/com/android/server/NativeDaemonConnector.java
@@ -20,6 +20,7 @@
 import android.net.LocalSocketAddress;
 import android.os.Build;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.os.PowerManager;
 import android.os.SystemClock;
@@ -59,6 +60,8 @@
 
     private final PowerManager.WakeLock mWakeLock;
 
+    private final Looper mLooper;
+
     private INativeDaemonConnectorCallbacks mCallbacks;
     private Handler mCallbackHandler;
 
@@ -74,6 +77,13 @@
 
     NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
             int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl) {
+        this(callbacks, socket, responseQueueSize, logTag, maxLogSize, wl,
+                FgThread.get().getLooper());
+    }
+
+    NativeDaemonConnector(INativeDaemonConnectorCallbacks callbacks, String socket,
+            int responseQueueSize, String logTag, int maxLogSize, PowerManager.WakeLock wl,
+            Looper looper) {
         mCallbacks = callbacks;
         mSocket = socket;
         mResponseQueue = new ResponseQueue(responseQueueSize);
@@ -81,6 +91,7 @@
         if (mWakeLock != null) {
             mWakeLock.setReferenceCounted(true);
         }
+        mLooper = looper;
         mSequenceNumber = new AtomicInteger(0);
         TAG = logTag != null ? logTag : "NativeDaemonConnector";
         mLocalLog = new LocalLog(maxLogSize);
@@ -88,7 +99,7 @@
 
     @Override
     public void run() {
-        mCallbackHandler = new Handler(FgThread.get().getLooper(), this);
+        mCallbackHandler = new Handler(mLooper, this);
 
         while (true) {
             try {
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 9629bd1..7ce45f7 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -58,6 +58,8 @@
 import android.os.ServiceManager;
 import android.os.SystemClock;
 import android.os.SystemProperties;
+import android.telephony.DataConnectionRealTimeInfo;
+import android.telephony.PhoneStateListener;
 import android.util.Log;
 import android.util.Slog;
 import android.util.SparseBooleanArray;
@@ -143,21 +145,25 @@
         public static final int InterfaceDnsServerInfo    = 615;
     }
 
+    static final int DAEMON_MSG_MOBILE_CONN_REAL_TIME_INFO = 1;
+
     /**
      * Binder context for this service
      */
-    private Context mContext;
+    private final Context mContext;
 
     /**
      * connector object for communicating with netd
      */
-    private NativeDaemonConnector mConnector;
+    private final NativeDaemonConnector mConnector;
 
-    private final Handler mMainHandler = new Handler();
+    private final Handler mFgHandler;
+    private final Handler mDaemonHandler;
+    private final PhoneStateListener mPhoneStateListener;
 
     private IBatteryStats mBatteryStats;
 
-    private Thread mThread;
+    private final Thread mThread;
     private CountDownLatch mConnectedSignal = new CountDownLatch(1);
 
     private final RemoteCallbackList<INetworkManagementEventObserver> mObservers =
@@ -191,6 +197,9 @@
     private volatile boolean mBandwidthControlEnabled;
     private volatile boolean mFirewallEnabled;
 
+    private boolean mMobileActivityFromRadio = false;
+    private int mLastPowerStateFromRadio = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
+
     private final RemoteCallbackList<INetworkActivityListener> mNetworkActivityListeners =
             new RemoteCallbackList<INetworkActivityListener>();
     private boolean mNetworkActive;
@@ -203,21 +212,39 @@
     private NetworkManagementService(Context context, String socket) {
         mContext = context;
 
+        // make sure this is on the same looper as our NativeDaemonConnector for sync purposes
+        mFgHandler = new Handler(FgThread.get().getLooper());
+
         if ("simulator".equals(SystemProperties.get("ro.product.device"))) {
+            mConnector = null;
+            mThread = null;
+            mDaemonHandler = null;
+            mPhoneStateListener = null;
             return;
         }
 
-        PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         // Don't need this wake lock, since we now have a time stamp for when
         // the network actually went inactive.  (It might be nice to still do this,
         // but I don't want to do it through the power manager because that pollutes the
         // battery stats history with pointless noise.)
+        //PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
         PowerManager.WakeLock wl = null; //pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, NETD_TAG);
 
         mConnector = new NativeDaemonConnector(
-                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl);
+                new NetdCallbackReceiver(), socket, 10, NETD_TAG, 160, wl,
+                FgThread.get().getLooper());
         mThread = new Thread(mConnector, NETD_TAG);
 
+        mDaemonHandler = new Handler(FgThread.get().getLooper());
+        mPhoneStateListener = new PhoneStateListener(mDaemonHandler.getLooper()) {
+            public void onDataConnectionRealTimeInfoChanged(
+                    DataConnectionRealTimeInfo dcRtInfo) {
+                // Disabled for now, until we are getting good data.
+                //notifyInterfaceClassActivity(ConnectivityManager.TYPE_MOBILE,
+                //        dcRtInfo.getDcPowerState(), dcRtInfo.getTime(), true);
+            }
+        };
+
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
     }
@@ -271,14 +298,17 @@
      */
     private void notifyInterfaceStatusChanged(String iface, boolean up) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).interfaceStatusChanged(iface, up);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -287,14 +317,17 @@
      */
     private void notifyInterfaceLinkStateChanged(String iface, boolean up) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).interfaceLinkStateChanged(iface, up);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -302,14 +335,17 @@
      */
     private void notifyInterfaceAdded(String iface) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceAdded(iface);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).interfaceAdded(iface);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -322,14 +358,17 @@
         mActiveQuotas.remove(iface);
 
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceRemoved(iface);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).interfaceRemoved(iface);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -337,46 +376,78 @@
      */
     private void notifyLimitReached(String limitName, String iface) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).limitReached(limitName, iface);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).limitReached(limitName, iface);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
      * Notify our observers of a change in the data activity state of the interface
      */
-    private void notifyInterfaceClassActivity(int type, boolean active, long tsNanos) {
-        try {
-            getBatteryStats().noteDataConnectionActive(type, active, tsNanos);
-        } catch (RemoteException e) {
-        }
-
-        final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
-                        Integer.toString(type), active, tsNanos);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+    private void notifyInterfaceClassActivity(int type, int powerState, long tsNanos,
+            boolean fromRadio) {
+        final boolean isMobile = ConnectivityManager.isNetworkTypeMobile(type);
+        if (isMobile) {
+            if (!fromRadio) {
+                if (mMobileActivityFromRadio) {
+                    // If this call is not coming from a report from the radio itself, but we
+                    // have previously received reports from the radio, then we will take the
+                    // power state to just be whatever the radio last reported.
+                    powerState = mLastPowerStateFromRadio;
+                }
+            } else {
+                mMobileActivityFromRadio = true;
+            }
+            if (mLastPowerStateFromRadio != powerState) {
+                mLastPowerStateFromRadio = powerState;
+                try {
+                    getBatteryStats().noteMobileRadioPowerState(powerState, tsNanos);
+                } catch (RemoteException e) {
+                }
             }
         }
-        mObservers.finishBroadcast();
+
+        boolean isActive = powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_MEDIUM
+                || powerState == DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH;
+
+        if (!isMobile || fromRadio || !mMobileActivityFromRadio) {
+            // Report the change in data activity.  We don't do this if this is a change
+            // on the mobile network, that is not coming from the radio itself, and we
+            // have previously seen change reports from the radio.  In that case only
+            // the radio is the authority for the current state.
+            final int length = mObservers.beginBroadcast();
+            try {
+                for (int i = 0; i < length; i++) {
+                    try {
+                        mObservers.getBroadcastItem(i).interfaceClassDataActivityChanged(
+                                Integer.toString(type), isActive, tsNanos);
+                    } catch (RemoteException e) {
+                    } catch (RuntimeException e) {
+                    }
+                }
+            } finally {
+                mObservers.finishBroadcast();
+            }
+        }
 
         boolean report = false;
         synchronized (mIdleTimerLock) {
             if (mActiveIdleTimers.isEmpty()) {
-                // If there are no idle times, we are not monitoring activity, so we
+                // If there are no idle timers, we are not monitoring activity, so we
                 // are always considered active.
-                active = true;
+                isActive = true;
             }
-            if (mNetworkActive != active) {
-                mNetworkActive = active;
-                report = active;
+            if (mNetworkActive != isActive) {
+                mNetworkActive = isActive;
+                report = isActive;
             }
         }
         if (report) {
@@ -456,14 +527,17 @@
      */
     private void notifyAddressUpdated(String iface, LinkAddress address) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).addressUpdated(iface, address);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).addressUpdated(iface, address);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -471,14 +545,17 @@
      */
     private void notifyAddressRemoved(String iface, LinkAddress address) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).addressRemoved(iface, address);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).addressRemoved(iface, address);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     /**
@@ -486,14 +563,18 @@
      */
     private void notifyInterfaceDnsServerInfo(String iface, long lifetime, String[] addresses) {
         final int length = mObservers.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime, addresses);
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mObservers.getBroadcastItem(i).interfaceDnsServerInfo(iface, lifetime,
+                        addresses);
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mObservers.finishBroadcast();
         }
-        mObservers.finishBroadcast();
     }
 
     //
@@ -509,7 +590,7 @@
                 mConnectedSignal.countDown();
                 mConnectedSignal = null;
             } else {
-                mMainHandler.post(new Runnable() {
+                mFgHandler.post(new Runnable() {
                     @Override
                     public void run() {
                         prepareNativeDaemon();
@@ -580,10 +661,13 @@
                         try {
                             timestampNanos = Long.parseLong(cooked[4]);
                         } catch(NumberFormatException ne) {}
+                    } else {
+                        timestampNanos = SystemClock.elapsedRealtimeNanos();
                     }
                     boolean isActive = cooked[2].equals("active");
                     notifyInterfaceClassActivity(Integer.parseInt(cooked[3]),
-                            isActive, timestampNanos);
+                            isActive ? DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH
+                            : DataConnectionRealTimeInfo.DC_POWER_STATE_LOW, timestampNanos, false);
                     return true;
                     // break;
             case NetdResponseCode.InterfaceAddressChange:
@@ -1270,9 +1354,11 @@
             if (ConnectivityManager.isNetworkTypeMobile(type)) {
                 mNetworkActive = false;
             }
-            mMainHandler.post(new Runnable() {
+            mDaemonHandler.post(new Runnable() {
                 @Override public void run() {
-                    notifyInterfaceClassActivity(type, true, SystemClock.elapsedRealtimeNanos());
+                    notifyInterfaceClassActivity(type,
+                            DataConnectionRealTimeInfo.DC_POWER_STATE_HIGH,
+                            SystemClock.elapsedRealtimeNanos(), false);
                 }
             });
         }
@@ -1297,10 +1383,11 @@
                 throw e.rethrowAsParcelableException();
             }
             mActiveIdleTimers.remove(iface);
-            mMainHandler.post(new Runnable() {
+            mDaemonHandler.post(new Runnable() {
                 @Override public void run() {
-                    notifyInterfaceClassActivity(params.type, false,
-                            SystemClock.elapsedRealtimeNanos());
+                    notifyInterfaceClassActivity(params.type,
+                            DataConnectionRealTimeInfo.DC_POWER_STATE_LOW,
+                            SystemClock.elapsedRealtimeNanos(), false);
                 }
             });
         }
@@ -1880,14 +1967,17 @@
 
     private void reportNetworkActive() {
         final int length = mNetworkActivityListeners.beginBroadcast();
-        for (int i = 0; i < length; i++) {
-            try {
-                mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
-            } catch (RemoteException e) {
-            } catch (RuntimeException e) {
+        try {
+            for (int i = 0; i < length; i++) {
+                try {
+                    mNetworkActivityListeners.getBroadcastItem(i).onNetworkActive();
+                } catch (RemoteException e) {
+                } catch (RuntimeException e) {
+                }
             }
+        } finally {
+            mNetworkActivityListeners.finishBroadcast();
         }
-        mNetworkActivityListeners.finishBroadcast();
     }
 
     /** {@inheritDoc} */
@@ -1907,6 +1997,9 @@
         pw.println();
 
         pw.print("Bandwidth control enabled: "); pw.println(mBandwidthControlEnabled);
+        pw.print("mMobileActivityFromRadio="); pw.print(mMobileActivityFromRadio);
+                pw.print(" mLastPowerStateFromRadio="); pw.println(mLastPowerStateFromRadio);
+        pw.print("mNetworkActive="); pw.println(mNetworkActive);
 
         synchronized (mQuotaLock) {
             pw.print("Active quota ifaces: "); pw.println(mActiveQuotas.toString());
diff --git a/services/core/java/com/android/server/NetworkScoreService.java b/services/core/java/com/android/server/NetworkScoreService.java
new file mode 100644
index 0000000..8a30e50
--- /dev/null
+++ b/services/core/java/com/android/server/NetworkScoreService.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.server;
+
+import android.Manifest.permission;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
+import android.net.INetworkScoreService;
+import android.net.NetworkKey;
+import android.net.NetworkScorerAppManager;
+import android.net.RssiCurve;
+import android.net.ScoredNetwork;
+import android.text.TextUtils;
+
+import com.android.internal.R;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Backing service for {@link android.net.NetworkScoreManager}.
+ * @hide
+ */
+public class NetworkScoreService extends INetworkScoreService.Stub {
+    private static final String TAG = "NetworkScoreService";
+
+    /** SharedPreference bit set to true after the service is first initialized. */
+    private static final String PREF_SCORING_PROVISIONED = "is_provisioned";
+
+    private final Context mContext;
+
+    // TODO: Delete this temporary class once we have a real place for scores.
+    private final Map<NetworkKey, RssiCurve> mScoredNetworks;
+
+    public NetworkScoreService(Context context) {
+        mContext = context;
+        mScoredNetworks = new HashMap<>();
+    }
+
+    /** Called when the system is ready to run third-party code but before it actually does so. */
+    void systemReady() {
+        SharedPreferences prefs = mContext.getSharedPreferences(TAG, Context.MODE_PRIVATE);
+        if (!prefs.getBoolean(PREF_SCORING_PROVISIONED, false)) {
+            // On first run, we try to initialize the scorer to the one configured at build time.
+            // This will be a no-op if the scorer isn't actually valid.
+            String defaultPackage = mContext.getResources().getString(
+                    R.string.config_defaultNetworkScorerPackageName);
+            if (!TextUtils.isEmpty(defaultPackage)) {
+                NetworkScorerAppManager.setActiveScorer(mContext, defaultPackage);
+            }
+            prefs.edit().putBoolean(PREF_SCORING_PROVISIONED, true).apply();
+        }
+    }
+
+    @Override
+    public boolean updateScores(ScoredNetwork[] networks) {
+        if (!NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid())) {
+            throw new SecurityException("Caller with UID " + getCallingUid() +
+                    " is not the active scorer.");
+        }
+
+        // TODO: Propagate these scores down to the network subsystem layer instead of just holding
+        // them in memory.
+        for (ScoredNetwork network : networks) {
+            mScoredNetworks.put(network.networkKey, network.rssiCurve);
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean clearScores() {
+        // Only the active scorer or the system (who can broadcast BROADCAST_SCORE_NETWORKS) should
+        // be allowed to flush all scores.
+        if (NetworkScorerAppManager.isCallerActiveScorer(mContext, getCallingUid()) ||
+                mContext.checkCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS) ==
+                        PackageManager.PERMISSION_GRANTED) {
+            clearInternal();
+            return true;
+        } else {
+            throw new SecurityException(
+                    "Caller is neither the active scorer nor the scorer manager.");
+        }
+    }
+
+    @Override
+    public boolean setActiveScorer(String packageName) {
+        mContext.enforceCallingOrSelfPermission(permission.BROADCAST_SCORE_NETWORKS, TAG);
+        // Preemptively clear scores even though the set operation could fail. We do this for safety
+        // as scores should never be compared across apps; in practice, Settings should only be
+        // allowing valid apps to be set as scorers, so failure here should be rare.
+        clearInternal();
+        return NetworkScorerAppManager.setActiveScorer(mContext, packageName);
+    }
+
+    /** Clear scores. Callers are responsible for checking permissions as appropriate. */
+    private void clearInternal() {
+        // TODO: Propagate the flush down to the network subsystem layer.
+        mScoredNetworks.clear();
+    }
+
+    @Override
+    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
+        mContext.enforceCallingOrSelfPermission(permission.DUMP, TAG);
+        String currentScorer = NetworkScorerAppManager.getActiveScorer(mContext);
+        if (currentScorer == null) {
+            writer.println("Scoring is disabled.");
+            return;
+        }
+        writer.println("Current scorer: " + currentScorer);
+        if (mScoredNetworks.isEmpty()) {
+            writer.println("No networks scored.");
+        } else {
+            for (Map.Entry<NetworkKey, RssiCurve> entry : mScoredNetworks.entrySet()) {
+                writer.println(entry.getKey() + ": " + entry.getValue());
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/NsdService.java b/services/core/java/com/android/server/NsdService.java
index 1ed943c..fe97c71 100644
--- a/services/core/java/com/android/server/NsdService.java
+++ b/services/core/java/com/android/server/NsdService.java
@@ -35,14 +35,19 @@
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
+import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.CountDownLatch;
 
 import com.android.internal.util.AsyncChannel;
 import com.android.internal.util.Protocol;
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
+import com.android.server.NativeDaemonConnector.Command;
 
 /**
  * Network Service Discovery Service handles remote service discovery operation requests by
@@ -416,11 +421,8 @@
                 }
 
                 /* This goes in response as msg.arg2 */
-                int clientId = -1;
-                int keyId = clientInfo.mClientIds.indexOfValue(id);
-                if (keyId != -1) {
-                    clientId = clientInfo.mClientIds.keyAt(keyId);
-                } else {
+                int clientId = clientInfo.getClientId(id);
+                if (clientId < 0) {
                     // This can happen because of race conditions. For example,
                     // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
                     // and we may get in this situation.
@@ -433,14 +435,14 @@
                     case NativeResponseCode.SERVICE_FOUND:
                         /* NNN uniqueId serviceName regType domain */
                         if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
                                 clientId, servInfo);
                         break;
                     case NativeResponseCode.SERVICE_LOST:
                         /* NNN uniqueId serviceName regType domain */
                         if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], cooked[3], null);
+                        servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
                         clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
                                 clientId, servInfo);
                         break;
@@ -453,7 +455,7 @@
                     case NativeResponseCode.SERVICE_REGISTERED:
                         /* NNN regId serviceName regType */
                         if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
-                        servInfo = new NsdServiceInfo(cooked[2], null, null);
+                        servInfo = new NsdServiceInfo(cooked[2], null);
                         clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
                                 id, clientId, servInfo);
                         break;
@@ -673,9 +675,22 @@
     private boolean registerService(int regId, NsdServiceInfo service) {
         if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
         try {
-            //Add txtlen and txtdata
-            mNativeConnector.execute("mdnssd", "register", regId, service.getServiceName(),
+            Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(),
                     service.getServiceType(), service.getPort());
+
+            // Add TXT records as additional arguments.
+            Map<String, byte[]> txtRecords = service.getAttributes();
+            for (String key : txtRecords.keySet()) {
+                try {
+                    // TODO: Send encoded TXT record as bytes once NDC/netd supports binary data.
+                    cmd.appendArg(String.format(Locale.US, "%s=%s", key,
+                            new String(txtRecords.get(key), "UTF_8")));
+                } catch (UnsupportedEncodingException e) {
+                    Slog.e(TAG, "Failed to encode txtRecord " + e);
+                }
+            }
+
+            mNativeConnector.execute(cmd);
         } catch(NativeDaemonConnectorException e) {
             Slog.e(TAG, "Failed to execute registerService " + e);
             return false;
@@ -886,5 +901,18 @@
             mClientRequests.clear();
         }
 
+        // mClientIds is a sparse array of listener id -> mDnsClient id.  For a given mDnsClient id,
+        // return the corresponding listener id.  mDnsClient id is also called a global id.
+        private int getClientId(final int globalId) {
+            // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals)
+            // while also coercing the int primitives to Integer objects.
+            for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) {
+                int mDnsId = mClientIds.valueAt(i);
+                if (globalId == mDnsId) {
+                    return mClientIds.keyAt(i);
+                }
+            }
+            return -1;
+        }
     }
 }
diff --git a/services/core/java/com/android/server/TelephonyRegistry.java b/services/core/java/com/android/server/TelephonyRegistry.java
index 77f5182..d4565b6 100644
--- a/services/core/java/com/android/server/TelephonyRegistry.java
+++ b/services/core/java/com/android/server/TelephonyRegistry.java
@@ -32,6 +32,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.telephony.CellLocation;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -129,6 +130,8 @@
 
     private List<CellInfo> mCellInfo = null;
 
+    private DataConnectionRealTimeInfo mDcRtInfo = new DataConnectionRealTimeInfo();
+
     private int mRingingCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
 
     private int mForegroundCallState = PreciseCallState.PRECISE_CALL_STATE_IDLE;
@@ -324,6 +327,13 @@
                             remove(r.binder);
                         }
                     }
+                    if ((events & PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO) != 0) {
+                        try {
+                            r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
+                        } catch (RemoteException ex) {
+                            remove(r.binder);
+                        }
+                    }
                     if ((events & PhoneStateListener.LISTEN_PRECISE_CALL_STATE) != 0) {
                         try {
                             r.callback.onPreciseCallStateChanged(mPreciseCallState);
@@ -383,6 +393,14 @@
         if (!checkNotifyPermission("notifyServiceState()")){
             return;
         }
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.notePhoneState(state.getState());
+        } catch (RemoteException re) {
+            // Can't do much
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
         synchronized (mRecords) {
             mServiceState = state;
             for (Record r : mRecords) {
@@ -451,6 +469,31 @@
         }
     }
 
+    public void notifyDataConnectionRealTimeInfo(DataConnectionRealTimeInfo dcRtInfo) {
+        if (!checkNotifyPermission("notifyDataConnectionRealTimeInfo()")) {
+            return;
+        }
+
+        synchronized (mRecords) {
+            mDcRtInfo = dcRtInfo;
+            for (Record r : mRecords) {
+                if (validateEventsAndUserLocked(r,
+                        PhoneStateListener.LISTEN_DATA_CONNECTION_REAL_TIME_INFO)) {
+                    try {
+                        if (DBG_LOC) {
+                            Slog.d(TAG, "notifyDataConnectionRealTimeInfo: mDcRtInfo="
+                                    + mDcRtInfo + " r=" + r);
+                        }
+                        r.callback.onDataConnectionRealTimeInfoChanged(mDcRtInfo);
+                    } catch (RemoteException ex) {
+                        mRemoveList.add(r.binder);
+                    }
+                }
+            }
+            handleRemoveListLocked();
+        }
+    }
+
     public void notifyMessageWaitingChanged(boolean mwi) {
         if (!checkNotifyPermission("notifyMessageWaitingChanged()")) {
             return;
@@ -754,6 +797,7 @@
             pw.println("  mDataConnectionLinkCapabilities=" + mDataConnectionLinkCapabilities);
             pw.println("  mCellLocation=" + mCellLocation);
             pw.println("  mCellInfo=" + mCellInfo);
+            pw.println("  mDcRtInfo=" + mDcRtInfo);
             pw.println("registrations: count=" + recordCount);
             for (Record r : mRecords) {
                 pw.println("  " + r.pkgForDebug + " 0x" + Integer.toHexString(r.events));
@@ -766,15 +810,6 @@
     //
 
     private void broadcastServiceStateChanged(ServiceState state) {
-        long ident = Binder.clearCallingIdentity();
-        try {
-            mBatteryStats.notePhoneState(state.getState());
-        } catch (RemoteException re) {
-            // Can't do much
-        } finally {
-            Binder.restoreCallingIdentity(ident);
-        }
-
         Intent intent = new Intent(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
         Bundle data = new Bundle();
         state.fillInNotifierBundle(data);
diff --git a/services/core/java/com/android/server/VibratorService.java b/services/core/java/com/android/server/VibratorService.java
index aa756a1..132ca00 100644
--- a/services/core/java/com/android/server/VibratorService.java
+++ b/services/core/java/com/android/server/VibratorService.java
@@ -86,19 +86,19 @@
         private final int     mRepeat;
         private final int     mStreamHint;
         private final int     mUid;
-        private final String  mPackageName;
+        private final String  mOpPkg;
 
-        Vibration(IBinder token, long millis, int streamHint, int uid, String packageName) {
-            this(token, millis, null, 0, streamHint, uid, packageName);
+        Vibration(IBinder token, long millis, int streamHint, int uid, String opPkg) {
+            this(token, millis, null, 0, streamHint, uid, opPkg);
         }
 
         Vibration(IBinder token, long[] pattern, int repeat, int streamHint, int uid,
-                String packageName) {
-            this(token, 0, pattern, repeat, streamHint, uid, packageName);
+                String opPkg) {
+            this(token, 0, pattern, repeat, streamHint, uid, opPkg);
         }
 
         private Vibration(IBinder token, long millis, long[] pattern,
-                int repeat, int streamHint, int uid, String packageName) {
+                int repeat, int streamHint, int uid, String opPkg) {
             mToken = token;
             mTimeout = millis;
             mStartTime = SystemClock.uptimeMillis();
@@ -106,7 +106,7 @@
             mRepeat = repeat;
             mStreamHint = streamHint;
             mUid = uid;
-            mPackageName = packageName;
+            mOpPkg = opPkg;
         }
 
         public void binderDied() {
@@ -194,7 +194,7 @@
                 Binder.getCallingPid(), Binder.getCallingUid(), null);
     }
 
-    public void vibrate(int uid, String packageName, long milliseconds, int streamHint,
+    public void vibrate(int uid, String opPkg, long milliseconds, int streamHint,
             IBinder token) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
                 != PackageManager.PERMISSION_GRANTED) {
@@ -211,7 +211,7 @@
             return;
         }
 
-        Vibration vib = new Vibration(token, milliseconds, streamHint, uid, packageName);
+        Vibration vib = new Vibration(token, milliseconds, streamHint, uid, opPkg);
 
         final long ident = Binder.clearCallingIdentity();
         try {
@@ -347,10 +347,10 @@
     private void startVibrationLocked(final Vibration vib) {
         try {
             int mode = mAppOpsService.checkAudioOperation(AppOpsManager.OP_VIBRATE,
-                    vib.mStreamHint, vib.mUid, vib.mPackageName);
+                    vib.mStreamHint, vib.mUid, vib.mOpPkg);
             if (mode == AppOpsManager.MODE_ALLOWED) {
                 mode = mAppOpsService.startOperation(AppOpsManager.getToken(mAppOpsService),
-                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mPackageName);
+                    AppOpsManager.OP_VIBRATE, vib.mUid, vib.mOpPkg);
             }
             if (mode != AppOpsManager.MODE_ALLOWED) {
                 if (mode == AppOpsManager.MODE_ERRORED) {
@@ -377,7 +377,7 @@
             try {
                 mAppOpsService.finishOperation(AppOpsManager.getToken(mAppOpsService),
                         AppOpsManager.OP_VIBRATE, mCurrentVibration.mUid,
-                        mCurrentVibration.mPackageName);
+                        mCurrentVibration.mOpPkg);
             } catch (RemoteException e) {
             }
             mCurrentVibration = null;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5bfb3fb..9eaddbd 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -17,8 +17,10 @@
 package com.android.server.am;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
+import static com.android.internal.util.XmlUtils.readBooleanAttribute;
 import static com.android.internal.util.XmlUtils.readIntAttribute;
 import static com.android.internal.util.XmlUtils.readLongAttribute;
+import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
 import static com.android.internal.util.XmlUtils.writeIntAttribute;
 import static com.android.internal.util.XmlUtils.writeLongAttribute;
 import static com.android.server.Watchdog.NATIVE_STACKS_OF_INTEREST;
@@ -26,19 +28,23 @@
 import static org.xmlpull.v1.XmlPullParser.START_TAG;
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 
+import android.Manifest;
 import android.app.AppOpsManager;
 import android.app.IActivityContainer;
 import android.app.IActivityContainerCallback;
 import android.appwidget.AppWidgetManager;
 import android.graphics.Rect;
 import android.os.BatteryStats;
+import android.service.voice.IVoiceInteractionSession;
 import android.util.ArrayMap;
 
 import com.android.internal.R;
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.app.IAppOpsService;
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.app.ProcessMap;
 import com.android.internal.app.ProcessStats;
+import com.android.internal.content.PackageMonitor;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.internal.os.ProcessCpuTracker;
@@ -54,6 +60,7 @@
 import com.android.server.LocalServices;
 import com.android.server.ServiceThread;
 import com.android.server.SystemService;
+import com.android.server.SystemServiceManager;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityStack.ActivityState;
 import com.android.server.firewall.IntentFirewall;
@@ -331,6 +338,9 @@
     // How many bytes to write into the dropbox log before truncating
     static final int DROPBOX_MAX_SIZE = 256 * 1024;
 
+    /** All system services */
+    SystemServiceManager mSystemServiceManager;
+
     /** Run all ActivityStacks through this */
     ActivityStackSupervisor mStackSupervisor;
 
@@ -397,7 +407,7 @@
     /**
      * List of intents that were used to start the most recent tasks.
      */
-    private final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
+    final ArrayList<TaskRecord> mRecentTasks = new ArrayList<TaskRecord>();
 
     public class PendingAssistExtras extends Binder implements Runnable {
         public final ActivityRecord activity;
@@ -724,6 +734,7 @@
     private static final String ATTR_URI = "uri";
     private static final String ATTR_MODE_FLAGS = "modeFlags";
     private static final String ATTR_CREATED_TIME = "createdTime";
+    private static final String ATTR_PREFIX = "prefix";
 
     /**
      * Global set of specific {@link Uri} permissions that have been granted.
@@ -731,8 +742,41 @@
      * to {@link UriPermission#uri} to {@link UriPermission}.
      */
     @GuardedBy("this")
-    private final SparseArray<ArrayMap<Uri, UriPermission>>
-            mGrantedUriPermissions = new SparseArray<ArrayMap<Uri, UriPermission>>();
+    private final SparseArray<ArrayMap<GrantUri, UriPermission>>
+            mGrantedUriPermissions = new SparseArray<ArrayMap<GrantUri, UriPermission>>();
+
+    public static class GrantUri {
+        public final Uri uri;
+        public final boolean prefix;
+
+        public GrantUri(Uri uri, boolean prefix) {
+            this.uri = uri;
+            this.prefix = prefix;
+        }
+
+        @Override
+        public int hashCode() {
+            return toString().hashCode();
+        }
+
+        @Override
+        public boolean equals(Object o) {
+            if (o instanceof GrantUri) {
+                GrantUri other = (GrantUri) o;
+                return uri.equals(other.uri) && prefix == other.prefix;
+            }
+            return false;
+        }
+
+        @Override
+        public String toString() {
+            if (prefix) {
+                return uri.toString() + " [prefix]";
+            } else {
+                return uri.toString();
+            }
+        }
+    }
 
     CoreSettingsObserver mCoreSettingsObserver;
 
@@ -843,17 +887,23 @@
      * Set while we are wanting to sleep, to prevent any
      * activities from being started/resumed.
      */
-    boolean mSleeping = false;
+    private boolean mSleeping = false;
+
+    /**
+     * Set while we are running a voice interaction.  This overrides
+     * sleeping while it is active.
+     */
+    private boolean mRunningVoice = false;
 
     /**
      * State of external calls telling us if the device is asleep.
      */
-    boolean mWentToSleep = false;
+    private boolean mWentToSleep = false;
 
     /**
      * State of external call telling us if the lock screen is shown.
      */
-    boolean mLockScreenShown = false;
+    private boolean mLockScreenShown = false;
 
     /**
      * Set if we are shutting down the system, similar to sleeping.
@@ -967,11 +1017,11 @@
 
     static class ProcessChangeItem {
         static final int CHANGE_ACTIVITIES = 1<<0;
-        static final int CHANGE_IMPORTANCE= 1<<1;
+        static final int CHANGE_PROCESS_STATE = 1<<1;
         int changes;
         int uid;
         int pid;
-        int importance;
+        int processState;
         boolean foregroundActivities;
     }
 
@@ -1081,6 +1131,8 @@
     static final int REQUEST_ALL_PSS_MSG = 39;
     static final int START_PROFILES_MSG = 40;
     static final int UPDATE_TIME = 41;
+    static final int SYSTEM_USER_START_MSG = 42;
+    static final int SYSTEM_USER_CURRENT_MSG = 43;
 
     static final int FIRST_ACTIVITY_STACK_MSG = 100;
     static final int FIRST_BROADCAST_QUEUE_MSG = 200;
@@ -1660,15 +1712,15 @@
                 break;
             }
             case REPORT_USER_SWITCH_MSG: {
-                dispatchUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                dispatchUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2);
                 break;
             }
             case CONTINUE_USER_SWITCH_MSG: {
-                continueUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                continueUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2);
                 break;
             }
             case USER_SWITCH_TIMEOUT_MSG: {
-                timeoutUserSwitch((UserStartedState)msg.obj, msg.arg1, msg.arg2);
+                timeoutUserSwitch((UserStartedState) msg.obj, msg.arg1, msg.arg2);
                 break;
             }
             case IMMERSIVE_MODE_LOCK_MSG: {
@@ -1715,6 +1767,14 @@
                 }
                 break;
             }
+            case SYSTEM_USER_START_MSG: {
+                mSystemServiceManager.startUser(msg.arg1);
+                break;
+            }
+            case SYSTEM_USER_CURRENT_MSG: {
+                mSystemServiceManager.switchUser(msg.arg1);
+                break;
+            }
             }
         }
     };
@@ -1777,6 +1837,82 @@
         }
     };
 
+    /**
+     * Monitor for package changes and update our internal state.
+     */
+    private final PackageMonitor mPackageMonitor = new PackageMonitor() {
+        @Override
+        public void onPackageRemoved(String packageName, int uid) {
+            // Remove all tasks with activities in the specified package from the list of recent tasks
+            synchronized (ActivityManagerService.this) {
+                for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+                    TaskRecord tr = mRecentTasks.get(i);
+                    ComponentName cn = tr.intent.getComponent();
+                    if (cn != null && cn.getPackageName().equals(packageName)) {
+                        // If the package name matches, remove the task and kill the process
+                        removeTaskByIdLocked(tr.taskId, ActivityManager.REMOVE_TASK_KILL_PROCESS);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public boolean onPackageChanged(String packageName, int uid, String[] components) {
+            final PackageManager pm = mContext.getPackageManager();
+            final ArrayList<Pair<Intent, Integer>> recentTaskIntents =
+                    new ArrayList<Pair<Intent, Integer>>();
+            final ArrayList<Integer> tasksToRemove = new ArrayList<Integer>();
+            // Copy the list of recent tasks so that we don't hold onto the lock on
+            // ActivityManagerService for long periods while checking if components exist.
+            synchronized (ActivityManagerService.this) {
+                for (int i = mRecentTasks.size() - 1; i >= 0; i--) {
+                    TaskRecord tr = mRecentTasks.get(i);
+                    recentTaskIntents.add(new Pair<Intent, Integer>(tr.intent, tr.taskId));
+                }
+            }
+            // Check the recent tasks and filter out all tasks with components that no longer exist.
+            Intent tmpI = new Intent();
+            for (int i = recentTaskIntents.size() - 1; i >= 0; i--) {
+                Pair<Intent, Integer> p = recentTaskIntents.get(i);
+                ComponentName cn = p.first.getComponent();
+                if (cn != null && cn.getPackageName().equals(packageName)) {
+                    try {
+                        // Add the task to the list to remove if the component no longer exists
+                        tmpI.setComponent(cn);
+                        if (pm.queryIntentActivities(tmpI, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) {
+                            tasksToRemove.add(p.second);
+                        }
+                    } catch (Exception e) {}
+                }
+            }
+            // Prune all the tasks with removed components from the list of recent tasks
+            synchronized (ActivityManagerService.this) {
+                for (int i = tasksToRemove.size() - 1; i >= 0; i--) {
+                    // Remove the task but don't kill the process (since other components in that
+                    // package may still be running and in the background)
+                    removeTaskByIdLocked(tasksToRemove.get(i), 0);
+                }
+            }
+            return true;
+        }
+
+        @Override
+        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+            // Force stop the specified packages
+            if (packages != null) {
+                for (String pkg : packages) {
+                    synchronized (ActivityManagerService.this) {
+                        if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, 0,
+                                "finished booting")) {
+                            return true;
+                        }
+                    }
+                }
+            }
+            return false;
+        }
+    };
+
     public void setSystemProcess() {
         try {
             ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
@@ -2023,6 +2159,10 @@
         Watchdog.getInstance().addThread(mHandler);
     }
 
+    public void setSystemServiceManager(SystemServiceManager mgr) {
+        mSystemServiceManager = mgr;
+    }
+
     private void start() {
         mProcessCpuThread.start();
 
@@ -2218,6 +2358,11 @@
         if (mFocusedActivity != r) {
             if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedActivityLocked: r=" + r);
             mFocusedActivity = r;
+            if (r.task != null && r.task.voiceInteractor != null) {
+                startRunningVoiceLocked();
+            } else {
+                finishRunningVoiceLocked();
+            }
             mStackSupervisor.setFocusedStack(r);
             if (r != null) {
                 mWindowManager.setFocusedApp(r.appToken, true);
@@ -2226,6 +2371,12 @@
         }
     }
 
+    final void clearFocusedActivity(ActivityRecord r) {
+        if (mFocusedActivity == r) {
+            mFocusedActivity = null;
+        }
+    }
+
     @Override
     public void setFocusedStack(int stackId) {
         if (DEBUG_FOCUS) Slog.d(TAG, "setFocusedStack: stackId=" + stackId);
@@ -2756,11 +2907,16 @@
                 debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
             }
 
+            String requiredAbi = app.info.requiredCpuAbi;
+            if (requiredAbi == null) {
+                requiredAbi = Build.SUPPORTED_ABIS[0];
+            }
+
             // Start the process.  It will either succeed and return a result containing
             // the PID of the new process, or else throw a RuntimeException.
             Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
                     app.processName, uid, uid, gids, debugFlags, mountExternal,
-                    app.info.targetSdkVersion, app.info.seinfo, null);
+                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, null);
 
             BatteryStatsImpl bs = mBatteryStatsService.getActiveStatistics();
             synchronized (bs) {
@@ -2949,7 +3105,7 @@
                     intent.setComponent(new ComponentName(
                             ri.activityInfo.packageName, ri.activityInfo.name));
                     mStackSupervisor.startActivityLocked(null, intent, null, ri.activityInfo,
-                            null, null, 0, 0, 0, null, 0, null, false, null, null);
+                            null, null, null, null, 0, 0, 0, null, 0, null, false, null, null);
                 }
             }
         }
@@ -3044,11 +3200,10 @@
                             observer.onForegroundActivitiesChanged(item.pid, item.uid,
                                     item.foregroundActivities);
                         }
-                        if ((item.changes&ProcessChangeItem.CHANGE_IMPORTANCE) != 0) {
-                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "IMPORTANCE CHANGED pid="
-                                    + item.pid + " uid=" + item.uid + ": " + item.importance);
-                            observer.onImportanceChanged(item.pid, item.uid,
-                                    item.importance);
+                        if ((item.changes&ProcessChangeItem.CHANGE_PROCESS_STATE) != 0) {
+                            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "PROCSTATE CHANGED pid="
+                                    + item.pid + " uid=" + item.uid + ": " + item.processState);
+                            observer.onProcessStateChanged(item.pid, item.uid, item.processState);
                         }
                     }
                 } catch (RemoteException e) {
@@ -3080,7 +3235,7 @@
         }
         for (int i=0; i<N; i++) {
             PendingActivityLaunch pal = mPendingActivityLaunches.get(i);
-            mStackSupervisor.startActivityUncheckedLocked(pal.r, pal.sourceRecord, pal.startFlags,
+            mStackSupervisor.startActivityUncheckedLocked(pal.r, pal.sourceRecord, null, null, pal.startFlags,
                     doResume && i == (N-1), null);
         }
         mPendingActivityLaunches.clear();
@@ -3106,7 +3261,7 @@
                 false, true, "startActivity", null);
         // TODO: Switch to user app stacks here.
         return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
-                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
+                null, null, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                 null, null, options, userId, null);
     }
 
@@ -3121,7 +3276,7 @@
         WaitResult res = new WaitResult();
         // TODO: Switch to user app stacks here.
         mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
-                resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
+                null, null, resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
                 res, null, options, UserHandle.getCallingUserId(), null);
         return res;
     }
@@ -3136,7 +3291,7 @@
                 false, true, "startActivityWithConfig", null);
         // TODO: Switch to user app stacks here.
         int ret = mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
-                resolvedType, resultTo, resultWho, requestCode, startFlags,
+                resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
                 null, null, null, config, options, userId, null);
         return ret;
     }
@@ -3174,6 +3329,31 @@
     }
 
     @Override
+    public int startVoiceActivity(String callingPackage, int callingPid, int callingUid,
+            Intent intent, String resolvedType, IVoiceInteractionSession session,
+            IVoiceInteractor interactor, int startFlags, String profileFile,
+            ParcelFileDescriptor profileFd, Bundle options, int userId) {
+        if (checkCallingPermission(Manifest.permission.BIND_VOICE_INTERACTION)
+                != PackageManager.PERMISSION_GRANTED) {
+            String msg = "Permission Denial: startVoiceActivity() from pid="
+                    + Binder.getCallingPid()
+                    + ", uid=" + Binder.getCallingUid()
+                    + " requires " + android.Manifest.permission.BIND_VOICE_INTERACTION;
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+        if (session == null || interactor == null) {
+            throw new NullPointerException("null session or interactor");
+        }
+        userId = handleIncomingUser(callingPid, callingUid, userId,
+                false, true, "startVoiceActivity", null);
+        // TODO: Switch to user app stacks here.
+        return mStackSupervisor.startActivityMayWait(null, callingUid, callingPackage, intent,
+                resolvedType, session, interactor, null, null, 0, startFlags,
+                profileFile, profileFd, null, null, options, userId, null);
+    }
+
+    @Override
     public boolean startNextMatchingActivity(IBinder callingActivity,
             Intent intent, Bundle options) {
         // Refuse possible leaked file descriptors
@@ -3266,7 +3446,7 @@
 
             final long origId = Binder.clearCallingIdentity();
             int res = mStackSupervisor.startActivityLocked(r.app.thread, intent,
-                    r.resolvedType, aInfo, resultTo != null ? resultTo.appToken : null,
+                    r.resolvedType, aInfo, null, null, resultTo != null ? resultTo.appToken : null,
                     resultWho, requestCode, -1, r.launchedFromUid, r.launchedFromPackage, 0,
                     options, false, null, null);
             Binder.restoreCallingIdentity(origId);
@@ -3289,7 +3469,7 @@
 
         // TODO: Switch to user app stacks here.
         int ret = mStackSupervisor.startActivityMayWait(null, uid, callingPackage, intent, resolvedType,
-                resultTo, resultWho, requestCode, startFlags,
+                null, null, resultTo, resultWho, requestCode, startFlags,
                 null, null, null, null, options, userId, container);
         return ret;
     }
@@ -3325,6 +3505,10 @@
         if (N > 0 && mRecentTasks.get(0) == task) {
             return;
         }
+        // Another quick case: never add voice sessions.
+        if (task.voiceSession != null) {
+            return;
+        }
         // Remove any existing entries that are the same kind of task.
         final Intent intent = task.intent;
         final boolean document = intent != null && intent.isDocument();
@@ -3412,11 +3596,14 @@
      * @param token The Binder token referencing the Activity we want to finish.
      * @param resultCode Result code, if any, from this Activity.
      * @param resultData Result data (Intent), if any, from this Activity.
+     * @param finishTask Whether to finish the task associated with this Activity.  Only applies to
+     *            the root Activity in the task.
      *
      * @return Returns true if the activity successfully finished, or false if it is still running.
      */
     @Override
-    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData) {
+    public final boolean finishActivity(IBinder token, int resultCode, Intent resultData,
+            boolean finishTask) {
         // Refuse possible leaked file descriptors
         if (resultData != null && resultData.hasFileDescriptors() == true) {
             throw new IllegalArgumentException("File descriptors passed in Intent");
@@ -3427,6 +3614,9 @@
             if (r == null) {
                 return true;
             }
+            // Keep track of the root activity of the task before we finish it
+            TaskRecord tr = r.task;
+            ActivityRecord rootR = tr.getRootActivity();
             if (mController != null) {
                 // Find the first activity that is not finishing.
                 ActivityRecord next = r.task.stack.topRunningActivityLocked(token, 0);
@@ -3446,10 +3636,21 @@
                 }
             }
             final long origId = Binder.clearCallingIdentity();
-            boolean res = r.task.stack.requestFinishActivityLocked(token, resultCode,
-                    resultData, "app-request", true);
-            Binder.restoreCallingIdentity(origId);
-            return res;
+            try {
+                boolean res;
+                if (finishTask && r == rootR) {
+                    // If requested, remove the task that is associated to this activity only if it
+                    // was the root activity in the task.  The result code and data is ignored because
+                    // we don't support returning them across task boundaries.
+                    res = removeTaskByIdLocked(tr.taskId, 0);
+                } else {
+                    res = tr.stack.requestFinishActivityLocked(token, resultCode,
+                            resultData, "app-request", true);
+                }
+                return res;
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
         }
     }
 
@@ -5142,26 +5343,8 @@
     }
 
     final void finishBooting() {
-        IntentFilter pkgFilter = new IntentFilter();
-        pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART);
-        pkgFilter.addDataScheme("package");
-        mContext.registerReceiver(new BroadcastReceiver() {
-            @Override
-            public void onReceive(Context context, Intent intent) {
-                String[] pkgs = intent.getStringArrayExtra(Intent.EXTRA_PACKAGES);
-                if (pkgs != null) {
-                    for (String pkg : pkgs) {
-                        synchronized (ActivityManagerService.this) {
-                            if (forceStopPackageLocked(pkg, -1, false, false, false, false, false, 0,
-                                    "finished booting")) {
-                                setResultCode(Activity.RESULT_OK);
-                                return;
-                            }
-                        }
-                    }
-                }
-            }
-        }, pkgFilter);
+        // Register receivers to handle package update events
+        mPackageMonitor.register(mContext, Looper.getMainLooper(), false);
 
         synchronized (this) {
             // Ensure that any processes we had put on hold are now started
@@ -5817,7 +6000,7 @@
      * in {@link ContentProvider}.
      */
     private final boolean checkHoldingPermissionsLocked(
-            IPackageManager pm, ProviderInfo pi, Uri uri, int uid, int modeFlags) {
+            IPackageManager pm, ProviderInfo pi, Uri uri, int uid, final int modeFlags) {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG,
                 "checkHoldingPermissionsLocked: uri=" + uri + " uid=" + uid);
 
@@ -5913,18 +6096,17 @@
         return pi;
     }
 
-    private UriPermission findUriPermissionLocked(int targetUid, Uri uri) {
-        ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+    private UriPermission findUriPermissionLocked(int targetUid, GrantUri uri) {
+        final ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
         if (targetUris != null) {
             return targetUris.get(uri);
-        } else {
-            return null;
         }
+        return null;
     }
 
-    private UriPermission findOrCreateUriPermissionLocked(
-            String sourcePkg, String targetPkg, int targetUid, Uri uri) {
-        ArrayMap<Uri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
+    private UriPermission findOrCreateUriPermissionLocked(String sourcePkg,
+            String targetPkg, int targetUid, GrantUri uri) {
+        ArrayMap<GrantUri, UriPermission> targetUris = mGrantedUriPermissions.get(targetUid);
         if (targetUris == null) {
             targetUris = Maps.newArrayMap();
             mGrantedUriPermissions.put(targetUid, targetUris);
@@ -5939,21 +6121,40 @@
         return perm;
     }
 
-    private final boolean checkUriPermissionLocked(
-            Uri uri, int uid, int modeFlags, int minStrength) {
+    private final boolean checkUriPermissionLocked(Uri uri, int uid, final int modeFlags) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
+                : UriPermission.STRENGTH_OWNED;
+
         // Root gets to do everything.
         if (uid == 0) {
             return true;
         }
-        ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
         if (perms == null) return false;
-        UriPermission perm = perms.get(uri);
-        if (perm == null) return false;
-        return perm.getStrength(modeFlags) >= minStrength;
+
+        // First look for exact match
+        final UriPermission exactPerm = perms.get(new GrantUri(uri, false));
+        if (exactPerm != null && exactPerm.getStrength(modeFlags) >= minStrength) {
+            return true;
+        }
+
+        // No exact match, look for prefixes
+        final int N = perms.size();
+        for (int i = 0; i < N; i++) {
+            final UriPermission perm = perms.valueAt(i);
+            if (perm.uri.prefix && uri.isPathPrefixMatch(perm.uri.uri)
+                    && perm.getStrength(modeFlags) >= minStrength) {
+                return true;
+            }
+        }
+
+        return false;
     }
 
     @Override
-    public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) {
+    public int checkUriPermission(Uri uri, int pid, int uid, final int modeFlags) {
         enforceNotIsolatedCaller("checkUriPermission");
 
         // Another redirected-binder-call permissions check as in
@@ -5968,8 +6169,8 @@
         if (pid == MY_PID) {
             return PackageManager.PERMISSION_GRANTED;
         }
-        synchronized(this) {
-            return checkUriPermissionLocked(uri, uid, modeFlags, UriPermission.STRENGTH_OWNED)
+        synchronized (this) {
+            return checkUriPermissionLocked(uri, uid, modeFlags)
                     ? PackageManager.PERMISSION_GRANTED
                     : PackageManager.PERMISSION_DENIED;
         }
@@ -5985,11 +6186,8 @@
      * lastTargetUid else set that to -1.
      */
     int checkGrantUriPermissionLocked(int callingUid, String targetPkg,
-            Uri uri, int modeFlags, int lastTargetUid) {
-        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
+            Uri uri, final int modeFlags, int lastTargetUid) {
+        if (!Intent.isAccessUriMode(modeFlags)) {
             return -1;
         }
 
@@ -6084,9 +6282,7 @@
         if (callingUid != Process.myUid()) {
             if (!checkHoldingPermissionsLocked(pm, pi, uri, callingUid, modeFlags)) {
                 // Require they hold a strong enough Uri permission
-                final int minStrength = persistable ? UriPermission.STRENGTH_PERSISTABLE
-                        : UriPermission.STRENGTH_OWNED;
-                if (!checkUriPermissionLocked(uri, callingUid, modeFlags, minStrength)) {
+                if (!checkUriPermissionLocked(uri, callingUid, modeFlags)) {
                     throw new SecurityException("Uid " + callingUid
                             + " does not have permission to uri " + uri);
                 }
@@ -6098,19 +6294,16 @@
 
     @Override
     public int checkGrantUriPermission(int callingUid, String targetPkg,
-            Uri uri, int modeFlags) {
+            Uri uri, final int modeFlags) {
         enforceNotIsolatedCaller("checkGrantUriPermission");
         synchronized(this) {
             return checkGrantUriPermissionLocked(callingUid, targetPkg, uri, modeFlags, -1);
         }
     }
 
-    void grantUriPermissionUncheckedLocked(
-            int targetUid, String targetPkg, Uri uri, int modeFlags, UriPermissionOwner owner) {
-        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
-        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-        if (modeFlags == 0) {
+    void grantUriPermissionUncheckedLocked(int targetUid, String targetPkg, Uri uri,
+            final int modeFlags, UriPermissionOwner owner) {
+        if (!Intent.isAccessUriMode(modeFlags)) {
             return;
         }
 
@@ -6128,13 +6321,14 @@
             return;
         }
 
+        final boolean prefix = (modeFlags & Intent.FLAG_GRANT_PREFIX_URI_PERMISSION) != 0;
         final UriPermission perm = findOrCreateUriPermissionLocked(
-                pi.packageName, targetPkg, targetUid, uri);
-        perm.grantModes(modeFlags, persistable, owner);
+                pi.packageName, targetPkg, targetUid, new GrantUri(uri, prefix));
+        perm.grantModes(modeFlags, owner);
     }
 
     void grantUriPermissionLocked(int callingUid, String targetPkg, Uri uri,
-            int modeFlags, UriPermissionOwner owner) {
+            final int modeFlags, UriPermissionOwner owner) {
         if (targetPkg == null) {
             throw new NullPointerException("targetPkg");
         }
@@ -6248,7 +6442,7 @@
 
     @Override
     public void grantUriPermission(IApplicationThread caller, String targetPkg,
-            Uri uri, int modeFlags) {
+            Uri uri, final int modeFlags) {
         enforceNotIsolatedCaller("grantUriPermission");
         synchronized(this) {
             final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6264,32 +6458,32 @@
                 throw new IllegalArgumentException("null uri");
             }
 
-            // Persistable only supported through Intents
-            Preconditions.checkFlagsArgument(modeFlags,
-                    Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+            Preconditions.checkFlagsArgument(modeFlags, Intent.FLAG_GRANT_READ_URI_PERMISSION
+                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION
+                    | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION
+                    | Intent.FLAG_GRANT_PREFIX_URI_PERMISSION);
 
-            grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags,
-                    null);
+            grantUriPermissionLocked(r.uid, targetPkg, uri, modeFlags, null);
         }
     }
 
     void removeUriPermissionIfNeededLocked(UriPermission perm) {
-        if ((perm.modeFlags&(Intent.FLAG_GRANT_READ_URI_PERMISSION
-                |Intent.FLAG_GRANT_WRITE_URI_PERMISSION)) == 0) {
-            ArrayMap<Uri, UriPermission> perms
-                    = mGrantedUriPermissions.get(perm.targetUid);
+        if (perm.modeFlags == 0) {
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+                    perm.targetUid);
             if (perms != null) {
                 if (DEBUG_URI_PERMISSION) Slog.v(TAG, 
                         "Removing " + perm.targetUid + " permission to " + perm.uri);
+
                 perms.remove(perm.uri);
-                if (perms.size() == 0) {
+                if (perms.isEmpty()) {
                     mGrantedUriPermissions.remove(perm.targetUid);
                 }
             }
         }
     }
 
-    private void revokeUriPermissionLocked(int callingUid, Uri uri, int modeFlags) {
+    private void revokeUriPermissionLocked(int callingUid, Uri uri, final int modeFlags) {
         if (DEBUG_URI_PERMISSION) Slog.v(TAG, "Revoking all granted permissions to " + uri);
 
         final IPackageManager pm = AppGlobals.getPackageManager();
@@ -6313,46 +6507,29 @@
         boolean persistChanged = false;
 
         // Go through all of the permissions and remove any that match.
-        final List<String> SEGMENTS = uri.getPathSegments();
-        if (SEGMENTS != null) {
-            final int NS = SEGMENTS.size();
-            int N = mGrantedUriPermissions.size();
-            for (int i=0; i<N; i++) {
-                ArrayMap<Uri, UriPermission> perms
-                        = mGrantedUriPermissions.valueAt(i);
-                Iterator<UriPermission> it = perms.values().iterator();
-            toploop:
-                while (it.hasNext()) {
-                    UriPermission perm = it.next();
-                    Uri targetUri = perm.uri;
-                    if (!authority.equals(targetUri.getAuthority())) {
-                        continue;
-                    }
-                    List<String> targetSegments = targetUri.getPathSegments();
-                    if (targetSegments == null) {
-                        continue;
-                    }
-                    if (targetSegments.size() < NS) {
-                        continue;
-                    }
-                    for (int j=0; j<NS; j++) {
-                        if (!SEGMENTS.get(j).equals(targetSegments.get(j))) {
-                            continue toploop;
-                        }
-                    }
-                    if (DEBUG_URI_PERMISSION) Slog.v(TAG, 
-                            "Revoking " + perm.targetUid + " permission to " + perm.uri);
-                    persistChanged |= perm.clearModes(modeFlags, true);
+        int N = mGrantedUriPermissions.size();
+        for (int i = 0; i < N; i++) {
+            final int targetUid = mGrantedUriPermissions.keyAt(i);
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
+            for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
+                final UriPermission perm = it.next();
+                if (perm.uri.uri.isPathPrefixMatch(uri)) {
+                    if (DEBUG_URI_PERMISSION)
+                        Slog.v(TAG,
+                                "Revoking " + perm.targetUid + " permission to " + perm.uri);
+                    persistChanged |= perm.revokeModes(
+                            modeFlags | Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
                     if (perm.modeFlags == 0) {
                         it.remove();
                     }
                 }
-                if (perms.size() == 0) {
-                    mGrantedUriPermissions.remove(
-                            mGrantedUriPermissions.keyAt(i));
-                    N--;
-                    i--;
-                }
+            }
+
+            if (perms.isEmpty()) {
+                mGrantedUriPermissions.remove(targetUid);
+                N--;
+                i--;
             }
         }
 
@@ -6363,7 +6540,7 @@
 
     @Override
     public void revokeUriPermission(IApplicationThread caller, Uri uri,
-            int modeFlags) {
+            final int modeFlags) {
         enforceNotIsolatedCaller("revokeUriPermission");
         synchronized(this) {
             final ProcessRecord r = getRecordForAppLocked(caller);
@@ -6377,9 +6554,7 @@
                 return;
             }
 
-            modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
-                    | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
-            if (modeFlags == 0) {
+            if (!Intent.isAccessUriMode(modeFlags)) {
                 return;
             }
 
@@ -6414,20 +6589,22 @@
 
         boolean persistChanged = false;
 
-        final int size = mGrantedUriPermissions.size();
-        for (int i = 0; i < size; i++) {
+        int N = mGrantedUriPermissions.size();
+        for (int i = 0; i < N; i++) {
+            final int targetUid = mGrantedUriPermissions.keyAt(i);
+            final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+
             // Only inspect grants matching user
             if (userHandle == UserHandle.USER_ALL
-                    || userHandle == UserHandle.getUserId(mGrantedUriPermissions.keyAt(i))) {
-                final Iterator<UriPermission> it = mGrantedUriPermissions.valueAt(i)
-                        .values().iterator();
-                while (it.hasNext()) {
+                    || userHandle == UserHandle.getUserId(targetUid)) {
+                for (Iterator<UriPermission> it = perms.values().iterator(); it.hasNext();) {
                     final UriPermission perm = it.next();
 
                     // Only inspect grants matching package
                     if (packageName == null || perm.sourcePkg.equals(packageName)
                             || perm.targetPkg.equals(packageName)) {
-                        persistChanged |= perm.clearModes(~0, persistable);
+                        persistChanged |= perm.revokeModes(
+                                persistable ? ~0 : ~Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION);
 
                         // Only remove when no modes remain; any persisted grants
                         // will keep this alive.
@@ -6436,6 +6613,12 @@
                         }
                     }
                 }
+
+                if (perms.isEmpty()) {
+                    mGrantedUriPermissions.remove(targetUid);
+                    N--;
+                    i--;
+                }
             }
         }
 
@@ -6455,7 +6638,7 @@
 
     @Override
     public void grantUriPermissionFromOwner(IBinder token, int fromUid, String targetPkg,
-            Uri uri, int modeFlags) {
+            Uri uri, final int modeFlags) {
         synchronized(this) {
             UriPermissionOwner owner = UriPermissionOwner.fromExternalToken(token);
             if (owner == null) {
@@ -6509,8 +6692,9 @@
         ArrayList<UriPermission.Snapshot> persist = Lists.newArrayList();
         synchronized (this) {
             final int size = mGrantedUriPermissions.size();
-            for (int i = 0 ; i < size; i++) {
-                for (UriPermission perm : mGrantedUriPermissions.valueAt(i).values()) {
+            for (int i = 0; i < size; i++) {
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
+                for (UriPermission perm : perms.values()) {
                     if (perm.persistedModeFlags != 0) {
                         persist.add(perm.snapshot());
                     }
@@ -6531,7 +6715,8 @@
                 writeIntAttribute(out, ATTR_USER_HANDLE, perm.userHandle);
                 out.attribute(null, ATTR_SOURCE_PKG, perm.sourcePkg);
                 out.attribute(null, ATTR_TARGET_PKG, perm.targetPkg);
-                out.attribute(null, ATTR_URI, String.valueOf(perm.uri));
+                out.attribute(null, ATTR_URI, String.valueOf(perm.uri.uri));
+                writeBooleanAttribute(out, ATTR_PREFIX, perm.uri.prefix);
                 writeIntAttribute(out, ATTR_MODE_FLAGS, perm.persistedModeFlags);
                 writeLongAttribute(out, ATTR_CREATED_TIME, perm.persistedCreateTime);
                 out.endTag(null, TAG_URI_GRANT);
@@ -6567,6 +6752,7 @@
                         final String sourcePkg = in.getAttributeValue(null, ATTR_SOURCE_PKG);
                         final String targetPkg = in.getAttributeValue(null, ATTR_TARGET_PKG);
                         final Uri uri = Uri.parse(in.getAttributeValue(null, ATTR_URI));
+                        final boolean prefix = readBooleanAttribute(in, ATTR_PREFIX);
                         final int modeFlags = readIntAttribute(in, ATTR_MODE_FLAGS);
                         final long createdTime = readLongAttribute(in, ATTR_CREATED_TIME, now);
 
@@ -6582,7 +6768,7 @@
                             }
                             if (targetUid != -1) {
                                 final UriPermission perm = findOrCreateUriPermissionLocked(
-                                        sourcePkg, targetPkg, targetUid, uri);
+                                        sourcePkg, targetPkg, targetUid, new GrantUri(uri, prefix));
                                 perm.initPersistedModes(modeFlags, createdTime);
                             }
                         } else {
@@ -6604,7 +6790,7 @@
     }
 
     @Override
-    public void takePersistableUriPermission(Uri uri, int modeFlags) {
+    public void takePersistableUriPermission(Uri uri, final int modeFlags) {
         enforceNotIsolatedCaller("takePersistableUriPermission");
 
         Preconditions.checkFlagsArgument(modeFlags,
@@ -6612,13 +6798,28 @@
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
-            final UriPermission perm = findUriPermissionLocked(callingUid, uri);
-            if (perm == null) {
-                throw new SecurityException("No permission grant found for UID " + callingUid
-                        + " and Uri " + uri.toSafeString());
+            boolean persistChanged = false;
+
+            UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+            UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+
+            final boolean exactValid = (exactPerm != null)
+                    && ((modeFlags & exactPerm.persistableModeFlags) == modeFlags);
+            final boolean prefixValid = (prefixPerm != null)
+                    && ((modeFlags & prefixPerm.persistableModeFlags) == modeFlags);
+
+            if (!(exactValid || prefixValid)) {
+                throw new SecurityException("No persistable permission grants found for UID "
+                        + callingUid + " and Uri " + uri.toSafeString());
             }
 
-            boolean persistChanged = perm.takePersistableModes(modeFlags);
+            if (exactValid) {
+                persistChanged |= exactPerm.takePersistableModes(modeFlags);
+            }
+            if (prefixValid) {
+                persistChanged |= prefixPerm.takePersistableModes(modeFlags);
+            }
+
             persistChanged |= maybePrunePersistedUriGrantsLocked(callingUid);
 
             if (persistChanged) {
@@ -6628,7 +6829,7 @@
     }
 
     @Override
-    public void releasePersistableUriPermission(Uri uri, int modeFlags) {
+    public void releasePersistableUriPermission(Uri uri, final int modeFlags) {
         enforceNotIsolatedCaller("releasePersistableUriPermission");
 
         Preconditions.checkFlagsArgument(modeFlags,
@@ -6636,16 +6837,24 @@
 
         synchronized (this) {
             final int callingUid = Binder.getCallingUid();
+            boolean persistChanged = false;
 
-            final UriPermission perm = findUriPermissionLocked(callingUid, uri);
-            if (perm == null) {
-                Slog.w(TAG, "No permission grant found for UID " + callingUid + " and Uri "
-                        + uri.toSafeString());
-                return;
+            UriPermission exactPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, false));
+            UriPermission prefixPerm = findUriPermissionLocked(callingUid, new GrantUri(uri, true));
+            if (exactPerm == null && prefixPerm == null) {
+                throw new SecurityException("No permission grants found for UID " + callingUid
+                        + " and Uri " + uri.toSafeString());
             }
 
-            final boolean persistChanged = perm.releasePersistableModes(modeFlags);
-            removeUriPermissionIfNeededLocked(perm);
+            if (exactPerm != null) {
+                persistChanged |= exactPerm.releasePersistableModes(modeFlags);
+                removeUriPermissionIfNeededLocked(exactPerm);
+            }
+            if (prefixPerm != null) {
+                persistChanged |= prefixPerm.releasePersistableModes(modeFlags);
+                removeUriPermissionIfNeededLocked(prefixPerm);
+            }
+
             if (persistChanged) {
                 schedulePersistUriGrants();
             }
@@ -6659,7 +6868,7 @@
      * @return if any mutations occured that require persisting.
      */
     private boolean maybePrunePersistedUriGrantsLocked(int uid) {
-        final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(uid);
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(uid);
         if (perms == null) return false;
         if (perms.size() < MAX_PERSISTED_URI_GRANTS) return false;
 
@@ -6709,13 +6918,12 @@
         final ArrayList<android.content.UriPermission> result = Lists.newArrayList();
         synchronized (this) {
             if (incoming) {
-                final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(
+                        callingUid);
                 if (perms == null) {
                     Slog.w(TAG, "No permission grants found for " + packageName);
                 } else {
-                    final int size = perms.size();
-                    for (int i = 0; i < size; i++) {
-                        final UriPermission perm = perms.valueAt(i);
+                    for (UriPermission perm : perms.values()) {
                         if (packageName.equals(perm.targetPkg) && perm.persistedModeFlags != 0) {
                             result.add(perm.buildPersistedPublicApiObject());
                         }
@@ -6724,10 +6932,9 @@
             } else {
                 final int size = mGrantedUriPermissions.size();
                 for (int i = 0; i < size; i++) {
-                    final ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
-                    final int permsSize = perms.size();
-                    for (int j = 0; j < permsSize; j++) {
-                        final UriPermission perm = perms.valueAt(j);
+                    final ArrayMap<GrantUri, UriPermission> perms =
+                            mGrantedUriPermissions.valueAt(i);
+                    for (UriPermission perm : perms.values()) {
                         if (packageName.equals(perm.sourcePkg) && perm.persistedModeFlags != 0) {
                             result.add(perm.buildPersistedPublicApiObject());
                         }
@@ -7079,6 +7286,24 @@
         }
     }
 
+    /**
+     * Removes the task with the specified task id.
+     *
+     * @param taskId Identifier of the task to be removed.
+     * @param flags Additional operational flags.  May be 0 or
+     * {@link ActivityManager#REMOVE_TASK_KILL_PROCESS}.
+     * @return Returns true if the given task was found and removed.
+     */
+    private boolean removeTaskByIdLocked(int taskId, int flags) {
+        TaskRecord tr = recentTaskForIdLocked(taskId);
+        if (tr != null) {
+            tr.removeTaskActivitiesLocked(-1, false);
+            cleanUpRemovedTaskLocked(tr, flags);
+            return true;
+        }
+        return false;
+    }
+
     @Override
     public boolean removeTask(int taskId, int flags) {
         synchronized (this) {
@@ -7086,29 +7311,11 @@
                     "removeTask()");
             long ident = Binder.clearCallingIdentity();
             try {
-                TaskRecord tr = recentTaskForIdLocked(taskId);
-                if (tr != null) {
-                    ActivityRecord r = tr.removeTaskActivitiesLocked(-1, false);
-                    if (r != null) {
-                        cleanUpRemovedTaskLocked(tr, flags);
-                        return true;
-                    }
-                    if (tr.mActivities.size() == 0) {
-                        // Caller is just removing a recent task that is
-                        // not actively running.  That is easy!
-                        cleanUpRemovedTaskLocked(tr, flags);
-                        return true;
-                    }
-                    Slog.w(TAG, "removeTask: task " + taskId
-                            + " does not have activities to remove, "
-                            + " but numActivities=" + tr.numActivities
-                            + ": " + tr);
-                }
+                return removeTaskByIdLocked(taskId, flags);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
         }
-        return false;
     }
     
     /**
@@ -7235,6 +7442,9 @@
             if (r == null) {
                 return null;
             }
+            if (callback == null) {
+                throw new IllegalArgumentException("callback must not be null");
+            }
             return mStackSupervisor.createActivityContainer(r, callback);
         }
     }
@@ -7594,11 +7804,11 @@
                 }
             }
         }
-        
-        ArrayMap<Uri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
+
+        final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.get(callingUid);
         if (perms != null) {
-            for (Map.Entry<Uri, UriPermission> uri : perms.entrySet()) {
-                if (uri.getKey().getAuthority().equals(cpi.authority)) {
+            for (GrantUri uri : perms.keySet()) {
+                if (uri.uri.getAuthority().equals(cpi.authority)) {
                     return null;
                 }
             }
@@ -8424,11 +8634,27 @@
         return mSleeping || mShuttingDown;
     }
 
+    public boolean isSleeping() {
+        return mSleeping;
+    }
+
     void goingToSleep() {
         synchronized(this) {
             mWentToSleep = true;
             updateEventDispatchingLocked();
+            goToSleepIfNeededLocked();
+        }
+    }
 
+    void finishRunningVoiceLocked() {
+        if (mRunningVoice) {
+            mRunningVoice = false;
+            goToSleepIfNeededLocked();
+        }
+    }
+
+    void goToSleepIfNeededLocked() {
+        if (mWentToSleep && !mRunningVoice) {
             if (!mSleeping) {
                 mSleeping = true;
                 mStackSupervisor.goingToSleepLocked();
@@ -8491,7 +8717,7 @@
     }
 
     private void comeOutOfSleepIfNeededLocked() {
-        if (!mWentToSleep && !mLockScreenShown) {
+        if ((!mWentToSleep && !mLockScreenShown) || mRunningVoice) {
             if (mSleeping) {
                 mSleeping = false;
                 mStackSupervisor.comeOutOfSleepIfNeededLocked();
@@ -8507,6 +8733,13 @@
         }
     }
 
+    void startRunningVoiceLocked() {
+        if (!mRunningVoice) {
+            mRunningVoice = true;
+            comeOutOfSleepIfNeededLocked();
+        }
+    }
+
     private void updateEventDispatchingLocked() {
         mWindowManager.setEventDispatching(mBooted && !mWentToSleep && !mShuttingDown);
     }
@@ -9213,7 +9446,7 @@
                     proc.notCachedSinceIdle = true;
                     proc.initialIdlePss = 0;
                     proc.nextPssTime = ProcessList.computeNextPssTime(proc.curProcState, true,
-                            mSleeping, now);
+                            isSleeping(), now);
                 }
             }
 
@@ -9512,6 +9745,8 @@
 
         if (goingCallback != null) goingCallback.run();
         
+        mSystemServiceManager.startUser(mCurrentUserId);
+
         synchronized (this) {
             if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
                 try {
@@ -9568,6 +9803,8 @@
                         }, 0, null, null,
                         android.Manifest.permission.INTERACT_ACROSS_USERS, AppOpsManager.OP_NONE,
                         true, false, MY_PID, Process.SYSTEM_UID, UserHandle.USER_ALL);
+            } catch (Throwable t) {
+                Slog.wtf(TAG, "Failed sending first user broadcasts", t);
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
@@ -10397,6 +10634,7 @@
         int adj = app.curAdj;
         outInfo.importance = oomAdjToImportance(adj, outInfo);
         outInfo.importanceReasonCode = app.adjTypeCode;
+        outInfo.processState = app.curProcState;
     }
 
     public List<ActivityManager.RunningAppProcessInfo> getRunningAppProcesses() {
@@ -11067,8 +11305,8 @@
                 pw.println("  mSleeping=" + mSleeping + " mWentToSleep=" + mWentToSleep
                         + " mLockScreenShown " + mLockScreenShown);
             }
-            if (mShuttingDown) {
-                pw.println("  mShuttingDown=" + mShuttingDown);
+            if (mShuttingDown || mRunningVoice) {
+                pw.print("  mShuttingDown=" + mShuttingDown + " mRunningVoice=" + mRunningVoice);
             }
         }
         if (mDebugApp != null || mOrigDebugApp != null || mDebugTransient
@@ -11565,8 +11803,7 @@
                 if (dumpUid >= -1 && UserHandle.getAppId(uid) != dumpUid) {
                     continue;
                 }
-                ArrayMap<Uri, UriPermission> perms
-                        = mGrantedUriPermissions.valueAt(i);
+                final ArrayMap<GrantUri, UriPermission> perms = mGrantedUriPermissions.valueAt(i);
                 if (!printed) {
                     if (needSep) pw.println();
                     needSep = true;
@@ -11574,8 +11811,7 @@
                     printed = true;
                     printedAnything = true;
                 }
-                pw.print("  * UID "); pw.print(uid);
-                        pw.println(" holds:");
+                pw.print("  * UID "); pw.print(uid); pw.println(" holds:");
                 for (UriPermission perm : perms.values()) {
                     pw.print("    "); pw.println(perm);
                     if (dumpAll) {
@@ -14454,7 +14690,7 @@
             app.keeping = true;
             app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
             app.curProcState = ActivityManager.PROCESS_STATE_PERSISTENT;
-            // System process can do UI, and when they do we want to have
+            // System processes can do UI, and when they do we want to have
             // them trim their memory after the user leaves the UI.  To
             // facilitate this, here we need to determine whether or not it
             // is currently showing UI.
@@ -15072,86 +15308,7 @@
         adj = app.modifyRawOomAdj(adj);
 
         app.curProcState = procState;
-
-        int importance = app.memImportance;
-        if (importance == 0 || adj != app.curAdj || schedGroup != app.curSchedGroup) {
-            app.curAdj = adj;
-            app.curSchedGroup = schedGroup;
-            if (!interesting) {
-                // For this reporting, if there is not something explicitly
-                // interesting in this process then we will push it to the
-                // background importance.
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.CACHED_APP_MIN_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.SERVICE_B_ADJ) {
-                importance =  ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-            } else if (adj >= ProcessList.HOME_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_BACKGROUND;
-            } else if (adj >= ProcessList.SERVICE_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE;
-            } else if (adj >= ProcessList.HEAVY_WEIGHT_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE;
-            } else if (adj >= ProcessList.PERCEPTIBLE_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE;
-            } else if (adj >= ProcessList.VISIBLE_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE;
-            } else if (adj >= ProcessList.FOREGROUND_APP_ADJ) {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
-            } else {
-                importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERSISTENT;
-            }
-        }
-
-        int changes = importance != app.memImportance ? ProcessChangeItem.CHANGE_IMPORTANCE : 0;
-        if (foregroundActivities != app.foregroundActivities) {
-            changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
-        }
-        if (changes != 0) {
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
-            app.memImportance = importance;
-            app.foregroundActivities = foregroundActivities;
-            int i = mPendingProcessChanges.size()-1;
-            ProcessChangeItem item = null;
-            while (i >= 0) {
-                item = mPendingProcessChanges.get(i);
-                if (item.pid == app.pid) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
-                    break;
-                }
-                i--;
-            }
-            if (i < 0) {
-                // No existing item in pending changes; need a new one.
-                final int NA = mAvailProcessChanges.size();
-                if (NA > 0) {
-                    item = mAvailProcessChanges.remove(NA-1);
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
-                } else {
-                    item = new ProcessChangeItem();
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
-                }
-                item.changes = 0;
-                item.pid = app.pid;
-                item.uid = app.info.uid;
-                if (mPendingProcessChanges.size() == 0) {
-                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
-                            "*** Enqueueing dispatch processes changed!");
-                    mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
-                }
-                mPendingProcessChanges.add(item);
-            }
-            item.changes |= changes;
-            item.importance = importance;
-            item.foregroundActivities = foregroundActivities;
-            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
-                    + Integer.toHexString(System.identityHashCode(item))
-                    + " " + app.toShortString() + ": changes=" + item.changes
-                    + " importance=" + item.importance
-                    + " foreground=" + item.foregroundActivities
-                    + " type=" + app.adjType + " source=" + app.adjSource
-                    + " target=" + app.adjTarget);
-        }
+        app.foregroundActivities = foregroundActivities;
 
         return app.curRawAdj;
     }
@@ -15190,7 +15347,7 @@
             if (memLowered || now > (app.lastStateTime+ProcessList.PSS_ALL_INTERVAL)) {
                 app.pssProcState = app.setProcState;
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                        mSleeping, now);
+                        isSleeping(), now);
                 mPendingPssProcesses.add(app);
             }
         }
@@ -15227,7 +15384,7 @@
             }
         }
         return !processingBroadcasts
-                && (mSleeping || mStackSupervisor.allResumedActivitiesIdle());
+                && (isSleeping() || mStackSupervisor.allResumedActivitiesIdle());
     }
     
     /**
@@ -15424,7 +15581,7 @@
     }
 
     private final boolean applyOomAdjLocked(ProcessRecord app, boolean wasKeeping,
-            ProcessRecord TOP_APP, boolean doingAll, boolean reportingProcessState, long now) {
+            ProcessRecord TOP_APP, boolean doingAll, long now) {
         boolean success = true;
 
         if (app.curRawAdj != app.setRawAdj) {
@@ -15443,6 +15600,8 @@
             app.setRawAdj = app.curRawAdj;
         }
 
+        int changes = 0;
+
         if (app.curAdj != app.setAdj) {
             ProcessList.setOomAdj(app.pid, app.curAdj);
             if (DEBUG_SWITCH || DEBUG_OOM_ADJ) Slog.v(
@@ -15484,9 +15643,14 @@
                         app.curSchedGroup <= Process.THREAD_GROUP_BG_NONINTERACTIVE);
             }
         }
+        if (app.repForegroundActivities != app.foregroundActivities) {
+            app.repForegroundActivities = app.foregroundActivities;
+            changes |= ProcessChangeItem.CHANGE_ACTIVITIES;
+        }
         if (app.repProcState != app.curProcState) {
             app.repProcState = app.curProcState;
-            if (!reportingProcessState && app.thread != null) {
+            changes |= ProcessChangeItem.CHANGE_PROCESS_STATE;
+            if (app.thread != null) {
                 try {
                     if (false) {
                         //RuntimeException h = new RuntimeException("here");
@@ -15502,7 +15666,7 @@
                 app.setProcState)) {
             app.lastStateTime = now;
             app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, true,
-                    mSleeping, now);
+                    isSleeping(), now);
             if (DEBUG_PSS) Slog.d(TAG, "Process state change from "
                     + ProcessList.makeProcStateString(app.setProcState) + " to "
                     + ProcessList.makeProcStateString(app.curProcState) + " next pss in "
@@ -15512,7 +15676,7 @@
                     && now > (app.lastStateTime+ProcessList.PSS_MIN_TIME_FROM_STATE_CHANGE))) {
                 requestPssLocked(app, app.setProcState);
                 app.nextPssTime = ProcessList.computeNextPssTime(app.curProcState, false,
-                        mSleeping, now);
+                        isSleeping(), now);
             } else if (false && DEBUG_PSS) {
                 Slog.d(TAG, "Not requesting PSS of " + app + ": next=" + (app.nextPssTime-now));
             }
@@ -15531,6 +15695,51 @@
                 app.procStateChanged = true;
             }
         }
+
+        if (changes != 0) {
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Changes in " + app + ": " + changes);
+            int i = mPendingProcessChanges.size()-1;
+            ProcessChangeItem item = null;
+            while (i >= 0) {
+                item = mPendingProcessChanges.get(i);
+                if (item.pid == app.pid) {
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Re-using existing item: " + item);
+                    break;
+                }
+                i--;
+            }
+            if (i < 0) {
+                // No existing item in pending changes; need a new one.
+                final int NA = mAvailProcessChanges.size();
+                if (NA > 0) {
+                    item = mAvailProcessChanges.remove(NA-1);
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Retreiving available item: " + item);
+                } else {
+                    item = new ProcessChangeItem();
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Allocating new item: " + item);
+                }
+                item.changes = 0;
+                item.pid = app.pid;
+                item.uid = app.info.uid;
+                if (mPendingProcessChanges.size() == 0) {
+                    if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG,
+                            "*** Enqueueing dispatch processes changed!");
+                    mHandler.obtainMessage(DISPATCH_PROCESSES_CHANGED).sendToTarget();
+                }
+                mPendingProcessChanges.add(item);
+            }
+            item.changes |= changes;
+            item.processState = app.repProcState;
+            item.foregroundActivities = app.repForegroundActivities;
+            if (DEBUG_PROCESS_OBSERVERS) Slog.i(TAG, "Item "
+                    + Integer.toHexString(System.identityHashCode(item))
+                    + " " + app.toShortString() + ": changes=" + item.changes
+                    + " procState=" + item.processState
+                    + " foreground=" + item.foregroundActivities
+                    + " type=" + app.adjType + " source=" + app.adjSource
+                    + " target=" + app.adjTarget);
+        }
+
         return success;
     }
 
@@ -15541,7 +15750,7 @@
     }
 
     private final boolean updateOomAdjLocked(ProcessRecord app, int cachedAdj,
-            ProcessRecord TOP_APP, boolean doingAll, boolean reportingProcessState, long now) {
+            ProcessRecord TOP_APP, boolean doingAll, long now) {
         if (app.thread == null) {
             return false;
         }
@@ -15550,8 +15759,7 @@
 
         computeOomAdjLocked(app, cachedAdj, TOP_APP, doingAll, now);
 
-        return applyOomAdjLocked(app, wasKeeping, TOP_APP, doingAll,
-                reportingProcessState, now);
+        return applyOomAdjLocked(app, wasKeeping, TOP_APP, doingAll, now);
     }
 
     final void updateProcessForegroundLocked(ProcessRecord proc, boolean isForeground,
@@ -15617,10 +15825,6 @@
     }
 
     final boolean updateOomAdjLocked(ProcessRecord app) {
-        return updateOomAdjLocked(app, false);
-    }
-
-    final boolean updateOomAdjLocked(ProcessRecord app, boolean doingProcessState) {
         final ActivityRecord TOP_ACT = resumedAppLocked();
         final ProcessRecord TOP_APP = TOP_ACT != null ? TOP_ACT.app : null;
         final boolean wasCached = app.cached;
@@ -15633,7 +15837,7 @@
         // need to do a complete oom adj.
         final int cachedAdj = app.curRawAdj >= ProcessList.CACHED_APP_MIN_ADJ
                 ? app.curRawAdj : ProcessList.UNKNOWN_ADJ;
-        boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false, doingProcessState,
+        boolean success = updateOomAdjLocked(app, cachedAdj, TOP_APP, false,
                 SystemClock.uptimeMillis());
         if (wasCached != app.cached || app.curRawAdj == ProcessList.UNKNOWN_ADJ) {
             // Changed to/from cached state, so apps after it in the LRU
@@ -15766,7 +15970,7 @@
                     }
                 }
 
-                applyOomAdjLocked(app, wasKeeping, TOP_APP, true, false, now);
+                applyOomAdjLocked(app, wasKeeping, TOP_APP, true, now);
 
                 // Count the number of process types.
                 switch (app.curProcState) {
@@ -15849,7 +16053,7 @@
         }
         mLastMemoryLevel = memFactor;
         mLastNumProcesses = mLruProcesses.size();
-        boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !mSleeping, now);
+        boolean allChanged = mProcessStats.setMemFactorLocked(memFactor, !isSleeping(), now);
         final int trackerMemFactor = mProcessStats.getMemFactorLocked();
         if (memFactor != ProcessStats.ADJ_MEM_FACTOR_NORMAL) {
             if (mLowRamStartTime == 0) {
@@ -16286,7 +16490,8 @@
      * background.
      */
     private void updateCurrentProfileIdsLocked() {
-        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+                mCurrentUserId, false /* enabledOnly */);
         int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
         for (int i = 0; i < currentProfileIds.length; i++) {
             currentProfileIds[i] = profiles.get(i).id;
@@ -16296,7 +16501,8 @@
 
     private Set getProfileIdsLocked(int userId) {
         Set userIds = new HashSet<Integer>();
-        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(userId);
+        final List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+                userId, false /* enabledOnly */);
         for (UserInfo user : profiles) {
             userIds.add(Integer.valueOf(user.id));
         }
@@ -16390,7 +16596,15 @@
                     needStart = true;
                 }
 
+                if (uss.mState == UserStartedState.STATE_BOOTING) {
+                    // Booting up a new user, need to tell system services about it.
+                    // Note that this is on the same handler as scheduling of broadcasts,
+                    // which is important because it needs to go first.
+                    mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_START_MSG, userId));
+                }
+
                 if (foreground) {
+                    mHandler.sendMessage(mHandler.obtainMessage(SYSTEM_USER_CURRENT_MSG, userId));
                     mHandler.removeMessages(REPORT_USER_SWITCH_MSG);
                     mHandler.removeMessages(USER_SWITCH_TIMEOUT_MSG);
                     mHandler.sendMessage(mHandler.obtainMessage(REPORT_USER_SWITCH_MSG,
@@ -16595,7 +16809,8 @@
 
     void startProfilesLocked() {
         if (DEBUG_MU) Slog.i(TAG_MU, "startProfilesLocked");
-        List<UserInfo> profiles = getUserManagerLocked().getProfiles(mCurrentUserId);
+        List<UserInfo> profiles = getUserManagerLocked().getProfiles(
+                mCurrentUserId, false /* enabledOnly */);
         List<UserInfo> toStart = new ArrayList<UserInfo>(profiles.size());
         for (UserInfo user : profiles) {
             if ((user.flags & UserInfo.FLAG_INITIALIZED) == UserInfo.FLAG_INITIALIZED
@@ -16744,6 +16959,7 @@
                             }
                             uss.mState = UserStartedState.STATE_SHUTDOWN;
                         }
+                        mSystemServiceManager.stopUser(userId);
                         broadcastIntentLocked(null, null, shutdownIntent,
                                 null, shutdownReceiver, 0, null, null, null, AppOpsManager.OP_NONE,
                                 true, false, MY_PID, Process.SYSTEM_UID, userId);
@@ -16793,7 +17009,12 @@
             }
         }
 
-        mStackSupervisor.removeUserLocked(userId);
+        if (stopped) {
+            mSystemServiceManager.cleanupUser(userId);
+            synchronized (this) {
+                mStackSupervisor.removeUserLocked(userId);
+            }
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/am/ActivityRecord.java b/services/core/java/com/android/server/am/ActivityRecord.java
index d596472..7a44473 100755
--- a/services/core/java/com/android/server/am/ActivityRecord.java
+++ b/services/core/java/com/android/server/am/ActivityRecord.java
@@ -139,7 +139,7 @@
     boolean forceNewConfig; // force re-create with new config next time
     int launchCount;        // count of launches since last state
     long lastLaunchTime;    // time of last lauch of this activity
-    ArrayList<ActivityStack> mChildContainers = new ArrayList<ActivityStack>();
+    ArrayList<ActivityContainer> mChildContainers = new ArrayList<ActivityContainer>();
 
     String stringName;      // for caching of toString().
 
@@ -215,14 +215,7 @@
             pw.print(prefix); pw.print("pendingOptions="); pw.println(pendingOptions);
         }
         if (uriPermissions != null) {
-            if (uriPermissions.readUriPermissions != null) {
-                pw.print(prefix); pw.print("readUriPermissions=");
-                        pw.println(uriPermissions.readUriPermissions);
-            }
-            if (uriPermissions.writeUriPermissions != null) {
-                pw.print(prefix); pw.print("writeUriPermissions=");
-                        pw.println(uriPermissions.writeUriPermissions);
-            }
+            uriPermissions.dump(pw, prefix);
         }
         pw.print(prefix); pw.print("launchFailed="); pw.print(launchFailed);
                 pw.print(" launchCount="); pw.print(launchCount);
@@ -640,7 +633,7 @@
         // case we will deliver it if this is the current top activity on its
         // stack.
         boolean unsent = true;
-        if ((state == ActivityState.RESUMED || (service.mSleeping
+        if ((state == ActivityState.RESUMED || (service.isSleeping()
                         && task.stack.topRunningActivityLocked(null) == this))
                 && app != null && app.thread != null) {
             try {
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index b894724..6769c9c 100755
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -36,6 +36,10 @@
 import static com.android.server.am.ActivityStackSupervisor.DEBUG_STATES;
 import static com.android.server.am.ActivityStackSupervisor.HOME_STACK_ID;
 
+import static com.android.server.am.ActivityStackSupervisor.ActivityContainer.CONTAINER_STATE_HAS_SURFACE;
+
+import android.service.voice.IVoiceInteractionSession;
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.BatteryStatsImpl;
 import com.android.server.Watchdog;
 import com.android.server.am.ActivityManagerService.ItemMatcher;
@@ -499,6 +503,11 @@
         if (DEBUG_TASKS) Slog.d(TAG, "Looking for task of " + target + " in " + this);
         for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
             final TaskRecord task = mTaskHistory.get(taskNdx);
+            if (task.voiceSession != null) {
+                // We never match voice sessions; those always run independently.
+                if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": voice session");
+                continue;
+            }
             if (task.userId != userId) {
                 // Looking for a different task.
                 if (DEBUG_TASKS) Slog.d(TAG, "Skipping " + task + ": different user");
@@ -733,7 +742,9 @@
         int w = mThumbnailWidth;
         int h = mThumbnailHeight;
         if (w < 0) {
-            if (SystemProperties.getBoolean("persist.recents.use_alternate", false)) {
+            Configuration config = res.getConfiguration();
+            boolean useAlternateRecents = (config.smallestScreenWidthDp < 600);
+            if (useAlternateRecents) {
                 mThumbnailWidth = w =
                    res.getDimensionPixelSize(com.android.internal.R.dimen.recents_thumbnail_width);
                 mThumbnailHeight = h =
@@ -791,7 +802,7 @@
         prev.task.touchActiveTime();
         clearLaunchTime(prev);
         final ActivityRecord next = mStackSupervisor.topRunningActivityLocked();
-        if (next == null || next.task != prev.task) {
+        if (next == null || next.noDisplay || next.task != prev.task) {
             prev.updateThumbnail(screenshotActivities(prev), null);
         }
         stopFullyDrawnTraceIfNeeded();
@@ -1063,6 +1074,16 @@
         return mStackSupervisor.isFrontStack(this);
     }
 
+    private void setVisibile(ActivityRecord r, boolean visible) {
+        r.visible = visible;
+        mWindowManager.setAppVisibility(r.appToken, visible);
+        final ArrayList<ActivityContainer> containers = r.mChildContainers;
+        for (int containerNdx = containers.size() - 1; containerNdx >= 0; --containerNdx) {
+            ActivityContainer container = containers.get(containerNdx);
+            container.setVisible(visible);
+        }
+    }
+
     /**
      * Version of ensureActivitiesVisible that can easily be called anywhere.
      */
@@ -1141,8 +1162,7 @@
                             if (!r.visible) {
                                 if (DEBUG_VISBILITY) Slog.v(
                                         TAG, "Starting and making visible: " + r);
-                                r.visible = true;
-                                mWindowManager.setAppVisibility(r.appToken, true);
+                                setVisibile(r, true);
                             }
                             if (r != starting) {
                                 mStackSupervisor.startSpecificActivityLocked(r, false, false);
@@ -1168,7 +1188,7 @@
                                 if (mTranslucentActivityWaiting != null) {
                                     mUndrawnActivitiesBelowTopTranslucent.add(r);
                                 }
-                                mWindowManager.setAppVisibility(r.appToken, true);
+                                setVisibile(r, true);
                                 r.sleeping = false;
                                 r.app.pendingUiClean = true;
                                 r.app.thread.scheduleWindowVisibility(r.appToken, true);
@@ -1204,9 +1224,8 @@
                     // sure they no longer are keeping the screen frozen.
                     if (r.visible) {
                         if (DEBUG_VISBILITY) Slog.v(TAG, "Making invisible: " + r);
-                        r.visible = false;
                         try {
-                            mWindowManager.setAppVisibility(r.appToken, false);
+                            setVisibile(r, false);
                             switch (r.state) {
                                 case STOPPING:
                                 case STOPPED:
@@ -1262,6 +1281,7 @@
      * occurred and the activity will be notified immediately.
      */
     void notifyActivityDrawnLocked(ActivityRecord r) {
+        mActivityContainer.setDrawn();
         if ((r == null)
                 || (mUndrawnActivitiesBelowTopTranslucent.remove(r) &&
                         mUndrawnActivitiesBelowTopTranslucent.isEmpty())) {
@@ -1328,7 +1348,8 @@
         if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen("");
 
         ActivityRecord parent = mActivityContainer.mParentActivity;
-        if (parent != null && parent.state != ActivityState.RESUMED) {
+        if ((parent != null && parent.state != ActivityState.RESUMED) ||
+                !mActivityContainer.isAttached()) {
             // Do not resume this stack if its parent is not resumed.
             // TODO: If in a loop, make sure that parent stack resumeTopActivity is called 1st.
             return false;
@@ -1489,7 +1510,7 @@
         // If the most recent activity was noHistory but was only stopped rather
         // than stopped+finished because the device went to sleep, we need to make
         // sure to finish it as we're making a new activity topmost.
-        if (mService.mSleeping && mLastNoHistoryActivity != null &&
+        if (mService.isSleeping() && mLastNoHistoryActivity != null &&
                 !mLastNoHistoryActivity.finishing) {
             if (DEBUG_STATES) Slog.d(TAG, "no-history finish of " + mLastNoHistoryActivity +
                     " on new resume");
@@ -2020,7 +2041,7 @@
                             + " out to bottom task " + bottom.task);
                 } else {
                     targetTask = createTaskRecord(mStackSupervisor.getNextTaskId(), target.info,
-                            null, false);
+                            null, null, null, false);
                     newThumbHolder = targetTask;
                     targetTask.affinityIntent = target.intent;
                     if (DEBUG_TASKS) Slog.v(TAG, "Start pushing activity " + target
@@ -2308,7 +2329,10 @@
                     mStackSupervisor.moveHomeToTop();
                 }
             }
-            mService.setFocusedActivityLocked(mStackSupervisor.topRunningActivityLocked());
+            ActivityRecord top = mStackSupervisor.topRunningActivityLocked();
+            if (top != null) {
+                mService.setFocusedActivityLocked(top);
+            }
         }
     }
 
@@ -2317,7 +2341,7 @@
         if ((r.intent.getFlags()&Intent.FLAG_ACTIVITY_NO_HISTORY) != 0
                 || (r.info.flags&ActivityInfo.FLAG_NO_HISTORY) != 0) {
             if (!r.finishing) {
-                if (!mService.mSleeping) {
+                if (!mService.isSleeping()) {
                     if (DEBUG_STATES) {
                         Slog.d(TAG, "no-history finish of " + r);
                     }
@@ -2616,6 +2640,20 @@
         return r;
     }
 
+    void finishAllActivitiesLocked() {
+        for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
+            final ArrayList<ActivityRecord> activities = mTaskHistory.get(taskNdx).mActivities;
+            for (int activityNdx = activities.size() - 1; activityNdx >= 0; --activityNdx) {
+                final ActivityRecord r = activities.get(activityNdx);
+                if (r.finishing) {
+                    continue;
+                }
+                Slog.d(TAG, "finishAllActivitiesLocked: finishing " + r);
+                finishCurrentActivityLocked(r, FINISH_IMMEDIATELY, false);
+            }
+        }
+    }
+
     final boolean navigateUpToLocked(IBinder token, Intent destIntent, int resultCode,
             Intent resultData) {
         final ActivityRecord srec = ActivityRecord.forToken(token);
@@ -2682,7 +2720,7 @@
                     ActivityInfo aInfo = AppGlobals.getPackageManager().getActivityInfo(
                             destIntent.getComponent(), 0, srec.userId);
                     int res = mStackSupervisor.startActivityLocked(srec.app.thread, destIntent,
-                            null, aInfo, parent.appToken, null,
+                            null, aInfo, null, null, parent.appToken, null,
                             0, -1, parent.launchedFromUid, parent.launchedFromPackage,
                             0, null, true, null, null);
                     foundParentInTask = res == ActivityManager.START_SUCCESS;
@@ -2711,9 +2749,7 @@
         if (mPausingActivity == r) {
             mPausingActivity = null;
         }
-        if (mService.mFocusedActivity == r) {
-            mService.mFocusedActivity = null;
-        }
+        mService.clearFocusedActivity(r);
 
         r.configDestroy = false;
         r.frozenBeforeDestroy = false;
@@ -2854,7 +2890,6 @@
         }
         if (activityRemoved) {
             mStackSupervisor.resumeTopActivitiesLocked();
-
         }
     }
 
@@ -3696,6 +3731,11 @@
             mTaskHistory.get(taskNdx + 1).mOnTopOfHome = true;
         }
         mTaskHistory.remove(task);
+        if (task.voiceInteractor != null) {
+            // This task was a voice interaction, so it should not remain on the
+            // recent tasks list.
+            mService.mRecentTasks.remove(task);
+        }
 
         if (mTaskHistory.isEmpty()) {
             if (DEBUG_STACK) Slog.i(TAG, "removeTask: moving to back stack=" + this);
@@ -3709,8 +3749,10 @@
         }
     }
 
-    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent, boolean toTop) {
-        TaskRecord task = new TaskRecord(taskId, info, intent);
+    TaskRecord createTaskRecord(int taskId, ActivityInfo info, Intent intent,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+            boolean toTop) {
+        TaskRecord task = new TaskRecord(taskId, info, intent, voiceSession, voiceInteractor);
         addTask(task, toTop);
         return task;
     }
diff --git a/services/core/java/com/android/server/am/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 47b4d0a..3770a07 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -17,7 +17,6 @@
 package com.android.server.am;
 
 import static android.Manifest.permission.START_ANY_ACTIVITY;
-import static android.content.Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
 import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
 import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -77,6 +76,7 @@
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.service.voice.IVoiceInteractionSession;
 import android.util.EventLog;
 import android.util.Slog;
 import android.util.SparseArray;
@@ -87,6 +87,7 @@
 import android.view.InputEvent;
 import android.view.Surface;
 import com.android.internal.app.HeavyWeightSwitcherActivity;
+import com.android.internal.app.IVoiceInteractor;
 import com.android.internal.os.TransferPipe;
 import com.android.server.LocalServices;
 import com.android.server.am.ActivityManagerService.PendingActivityLaunch;
@@ -96,7 +97,6 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -127,6 +127,7 @@
     static final int HANDLE_DISPLAY_ADDED = FIRST_SUPERVISOR_STACK_MSG + 5;
     static final int HANDLE_DISPLAY_CHANGED = FIRST_SUPERVISOR_STACK_MSG + 6;
     static final int HANDLE_DISPLAY_REMOVED = FIRST_SUPERVISOR_STACK_MSG + 7;
+    static final int CONTAINER_CALLBACK_VISIBILITY = FIRST_SUPERVISOR_STACK_MSG + 8;
 
     private final static String VIRTUAL_DISPLAY_BASE_NAME = "ActivityViewVirtualDisplay";
 
@@ -224,11 +225,11 @@
 
     // TODO: Add listener for removal of references.
     /** Mapping from (ActivityStack/TaskStack).mStackId to their current state */
-    SparseArray<WeakReference<ActivityContainer>> mActivityContainers =
-            new SparseArray<WeakReference<ActivityContainer>>();
+    SparseArray<ActivityContainer> mActivityContainers = new SparseArray<ActivityContainer>();
 
     /** Mapping from displayId to display current state */
-    private SparseArray<ActivityDisplay> mActivityDisplays = new SparseArray<ActivityDisplay>();
+    private final SparseArray<ActivityDisplay> mActivityDisplays =
+            new SparseArray<ActivityDisplay>();
 
     InputManagerInternal mInputManagerInternal;
 
@@ -264,7 +265,7 @@
                 mActivityDisplays.put(displayId, activityDisplay);
             }
 
-            createStackOnDisplay(null, HOME_STACK_ID, Display.DEFAULT_DISPLAY);
+            createStackOnDisplay(HOME_STACK_ID, Display.DEFAULT_DISPLAY);
             mHomeStack = mFocusedStack = mLastFocusedStack = getStack(HOME_STACK_ID);
 
             mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
@@ -687,13 +688,14 @@
 
     void startHomeActivity(Intent intent, ActivityInfo aInfo) {
         moveHomeToTop();
-        startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0,
+        startActivityLocked(null, intent, null, aInfo, null, null, null, null, 0, 0, 0, null, 0,
                 null, false, null, null);
     }
 
     final int startActivityMayWait(IApplicationThread caller, int callingUid,
-            String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
-            String resultWho, int requestCode, int startFlags, String profileFile,
+            String callingPackage, Intent intent, String resolvedType,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+            IBinder resultTo, String resultWho, int requestCode, int startFlags, String profileFile,
             ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
             Bundle options, int userId, IActivityContainer iContainer) {
         // Refuse possible leaked file descriptors
@@ -802,7 +804,8 @@
                 }
             }
 
-            int res = startActivityLocked(caller, intent, resolvedType, aInfo, resultTo, resultWho,
+            int res = startActivityLocked(caller, intent, resolvedType, aInfo,
+                    voiceSession, voiceInteractor, resultTo, resultWho,
                     requestCode, callingPid, callingUid, callingPackage, startFlags, options,
                     componentSpecified, null, container);
 
@@ -918,7 +921,7 @@
                         theseOptions = null;
                     }
                     int res = startActivityLocked(caller, intent, resolvedTypes[i],
-                            aInfo, resultTo, null, -1, callingPid, callingUid, callingPackage,
+                            aInfo, null, null, resultTo, null, -1, callingPid, callingUid, callingPackage,
                             0, theseOptions, componentSpecified, outActivity, null);
                     if (res < 0) {
                         return res;
@@ -1034,8 +1037,8 @@
             app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
                     System.identityHashCode(r), r.info,
                     new Configuration(mService.mConfiguration), r.compat,
-                    app.repProcState, r.icicle, results, newIntents, !andResume,
-                    mService.isNextTransitionForward(), profileFile, profileFd,
+                    r.task.voiceInteractor, app.repProcState, r.icicle, results, newIntents,
+                    !andResume, mService.isNextTransitionForward(), profileFile, profileFd,
                     profileAutoStop, options);
 
             if ((app.info.flags&ApplicationInfo.FLAG_CANT_SAVE_STATE) != 0) {
@@ -1143,8 +1146,9 @@
     }
 
     final int startActivityLocked(IApplicationThread caller,
-            Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
-            String resultWho, int requestCode,
+            Intent intent, String resolvedType, ActivityInfo aInfo,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
+            IBinder resultTo, String resultWho, int requestCode,
             int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
             boolean componentSpecified, ActivityRecord[] outActivity, ActivityContainer container) {
         int err = ActivityManager.START_SUCCESS;
@@ -1187,7 +1191,7 @@
         }
         ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack;
 
-        int launchFlags = intent.getFlags();
+        final int launchFlags = intent.getFlags();
 
         if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0
                 && sourceRecord != null) {
@@ -1232,6 +1236,38 @@
             err = ActivityManager.START_CLASS_NOT_FOUND;
         }
 
+        if (err == ActivityManager.START_SUCCESS && sourceRecord != null
+                && sourceRecord.task.voiceSession != null) {
+            // If this activity is being launched as part of a voice session, we need
+            // to ensure that it is safe to do so.  If the upcoming activity will also
+            // be part of the voice session, we can only launch it if it has explicitly
+            // said it supports the VOICE category, or it is a part of the calling app.
+            if ((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) == 0
+                    && sourceRecord.info.applicationInfo.uid != aInfo.applicationInfo.uid) {
+                try {
+                    if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
+                            intent, resolvedType)) {
+                        err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
+                    }
+                } catch (RemoteException e) {
+                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
+                }
+            }
+        }
+
+        if (err == ActivityManager.START_SUCCESS && voiceSession != null) {
+            // If the caller is starting a new voice session, just make sure the target
+            // is actually allowing it to run this way.
+            try {
+                if (!AppGlobals.getPackageManager().activitySupportsIntent(intent.getComponent(),
+                        intent, resolvedType)) {
+                    err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
+                }
+            } catch (RemoteException e) {
+                err = ActivityManager.START_NOT_VOICE_COMPATIBLE;
+            }
+        }
+
         if (err != ActivityManager.START_SUCCESS) {
             if (resultRecord != null) {
                 resultStack.sendActivityResultLocked(-1,
@@ -1305,8 +1341,8 @@
         }
 
         final ActivityStack stack = getFocusedStack();
-        if (stack.mResumedActivity == null
-                || stack.mResumedActivity.info.applicationInfo.uid != callingUid) {
+        if (voiceSession == null && (stack.mResumedActivity == null
+                || stack.mResumedActivity.info.applicationInfo.uid != callingUid)) {
             if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) {
                 PendingActivityLaunch pal =
                         new PendingActivityLaunch(r, sourceRecord, startFlags, stack);
@@ -1330,7 +1366,8 @@
 
         mService.doPendingActivityLaunchesLocked(false);
 
-        err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);
+        err = startActivityUncheckedLocked(r, sourceRecord, voiceSession, voiceInteractor,
+                startFlags, true, options);
 
         if (allPausedActivitiesComplete()) {
             // If someone asked to have the keyguard dismissed on the next
@@ -1385,7 +1422,7 @@
             }
 
             // Need to create an app stack for this user.
-            int stackId = createStackOnDisplay(null, getNextStackId(), Display.DEFAULT_DISPLAY);
+            int stackId = createStackOnDisplay(getNextStackId(), Display.DEFAULT_DISPLAY);
             if (DEBUG_FOCUS || DEBUG_STACK) Slog.d(TAG, "adjustStackFocus: New stack r=" + r +
                     " stackId=" + stackId);
             mFocusedStack = getStack(stackId);
@@ -1410,8 +1447,9 @@
     }
 
     final int startActivityUncheckedLocked(ActivityRecord r,
-            ActivityRecord sourceRecord, int startFlags, boolean doResume,
-            Bundle options) {
+            ActivityRecord sourceRecord,
+            IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, int startFlags,
+            boolean doResume, Bundle options) {
         final Intent intent = r.intent;
         final int callingUid = r.launchedFromUid;
 
@@ -1755,7 +1793,7 @@
                 r.setTask(targetStack.createTaskRecord(getNextTaskId(),
                         newTaskInfo != null ? newTaskInfo : r.info,
                         newTaskIntent != null ? newTaskIntent : intent,
-                        true), null, true);
+                        voiceSession, voiceInteractor, true), null, true);
                 if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r + " in new task " +
                         r.task);
             } else {
@@ -1833,7 +1871,7 @@
             targetStack.moveToFront();
             ActivityRecord prev = targetStack.topActivity();
             r.setTask(prev != null ? prev.task
-                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, true),
+                    : targetStack.createTaskRecord(getNextTaskId(), r.info, intent, null, null, true),
                     null, true);
             mWindowManager.moveTaskToTop(r.task.taskId);
             if (DEBUG_TASKS) Slog.v(TAG, "Starting new activity " + r
@@ -2153,14 +2191,9 @@
     }
 
     ActivityStack getStack(int stackId) {
-        WeakReference<ActivityContainer> weakReference = mActivityContainers.get(stackId);
-        if (weakReference != null) {
-            ActivityContainer activityContainer = weakReference.get();
-            if (activityContainer != null) {
-                return activityContainer.mStack;
-            } else {
-                mActivityContainers.remove(stackId);
-            }
+        ActivityContainer activityContainer = mActivityContainers.get(stackId);
+        if (activityContainer != null) {
+            return activityContainer.mStack;
         }
         return null;
     }
@@ -2190,49 +2223,26 @@
         return null;
     }
 
-    ActivityContainer createActivityContainer(ActivityRecord parentActivity, int stackId,
+    ActivityContainer createActivityContainer(ActivityRecord parentActivity,
             IActivityContainerCallback callback) {
-        ActivityContainer activityContainer = new ActivityContainer(parentActivity, stackId,
-                callback);
-        mActivityContainers.put(stackId, new WeakReference<ActivityContainer>(activityContainer));
-        if (parentActivity != null) {
-            parentActivity.mChildContainers.add(activityContainer.mStack);
-        }
+        ActivityContainer activityContainer = new VirtualActivityContainer(parentActivity, callback);
+        mActivityContainers.put(activityContainer.mStackId, activityContainer);
+        parentActivity.mChildContainers.add(activityContainer);
         return activityContainer;
     }
 
-    ActivityContainer createActivityContainer(ActivityRecord parentActivity,
-            IActivityContainerCallback callback) {
-        return createActivityContainer(parentActivity, getNextStackId(), callback);
-    }
-
     void removeChildActivityContainers(ActivityRecord parentActivity) {
-        for (int ndx = mActivityContainers.size() - 1; ndx >= 0; --ndx) {
-            final ActivityContainer container = mActivityContainers.valueAt(ndx).get();
-            if (container == null) {
-                mActivityContainers.removeAt(ndx);
-                continue;
-            }
-            if (container.mParentActivity != parentActivity) {
-                continue;
-            }
-
-            ActivityStack stack = container.mStack;
-            ActivityRecord top = stack.topRunningNonDelayedActivityLocked(null);
-            if (top != null) {
-                // TODO: Make sure the next activity doesn't start up when top is destroyed.
-                stack.destroyActivityLocked(top, true, true, "stack parent destroyed");
-            }
-            mActivityContainers.removeAt(ndx);
-            container.detachLocked();
+        final ArrayList<ActivityContainer> childStacks = parentActivity.mChildContainers;
+        for (int containerNdx = childStacks.size() - 1; containerNdx >= 0; --containerNdx) {
+            ActivityContainer container = childStacks.remove(containerNdx);
+            container.release();
         }
     }
 
     void deleteActivityContainer(IActivityContainer container) {
         ActivityContainer activityContainer = (ActivityContainer)container;
         if (activityContainer != null) {
-            activityContainer.mStack.destroyActivitiesLocked(null, true,
-                    "deleteActivityContainer");
+            activityContainer.mStack.finishAllActivitiesLocked();
             final ActivityRecord parent = activityContainer.mParentActivity;
             if (parent != null) {
                 parent.mChildContainers.remove(activityContainer);
@@ -2243,14 +2253,14 @@
         }
     }
 
-    private int createStackOnDisplay(ActivityRecord parentActivity, int stackId, int displayId) {
+    private int createStackOnDisplay(int stackId, int displayId) {
         ActivityDisplay activityDisplay = mActivityDisplays.get(displayId);
         if (activityDisplay == null) {
             return -1;
         }
 
-        ActivityContainer activityContainer =
-                createActivityContainer(parentActivity, stackId, null);
+        ActivityContainer activityContainer = new ActivityContainer(stackId);
+        mActivityContainers.put(stackId, activityContainer);
         activityContainer.attachToDisplayLocked(activityDisplay);
         return stackId;
     }
@@ -2333,9 +2343,9 @@
     }
 
     boolean shutdownLocked(int timeout) {
-        boolean timedout = false;
         goingToSleepLocked();
 
+        boolean timedout = false;
         final long endTime = System.currentTimeMillis() + timeout;
         while (true) {
             boolean cantShutdown = false;
@@ -3015,28 +3025,42 @@
                 case HANDLE_DISPLAY_REMOVED: {
                     handleDisplayRemovedLocked(msg.arg1);
                 } break;
+                case CONTAINER_CALLBACK_VISIBILITY: {
+                    final ActivityContainer container = (ActivityContainer) msg.obj;
+                    try {
+                        // We only send this message if mCallback is non-null.
+                        container.mCallback.setVisible(container.asBinder(), msg.arg1 == 1);
+                    } catch (RemoteException e) {
+                    }
+                }
             }
         }
     }
 
-    class ActivityContainer extends IActivityContainer.Stub {
+    class ActivityContainer extends android.app.IActivityContainer.Stub {
+        final static int FORCE_NEW_TASK_FLAGS = Intent.FLAG_ACTIVITY_NEW_TASK |
+                Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
         final int mStackId;
-        final IActivityContainerCallback mCallback;
+        IActivityContainerCallback mCallback = null;
         final ActivityStack mStack;
-        final ActivityRecord mParentActivity;
-        final String mIdString;
+        ActivityRecord mParentActivity = null;
+        String mIdString;
+
+        boolean mVisible = true;
 
         /** Display this ActivityStack is currently on. Null if not attached to a Display. */
         ActivityDisplay mActivityDisplay;
 
-        ActivityContainer(ActivityRecord parentActivity, int stackId,
-                IActivityContainerCallback callback) {
+        final static int CONTAINER_STATE_HAS_SURFACE = 0;
+        final static int CONTAINER_STATE_NO_SURFACE = 1;
+        final static int CONTAINER_STATE_FINISHING = 2;
+        int mContainerState = CONTAINER_STATE_HAS_SURFACE;
+
+        ActivityContainer(int stackId) {
             synchronized (mService) {
                 mStackId = stackId;
                 mStack = new ActivityStack(this);
-                mParentActivity = parentActivity;
-                mCallback = callback;
-                mIdString = "ActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+                mIdString = "ActivtyContainer{" + mStackId + "}";
                 if (DEBUG_STACK) Slog.d(TAG, "Creating " + this);
             }
         }
@@ -3086,6 +3110,14 @@
             }
         }
 
+        @Override
+        public void release() {
+            mContainerState = CONTAINER_STATE_FINISHING;
+            mStack.finishAllActivitiesLocked();
+            detachLocked();
+            mWindowManager.removeStack(mStackId);
+        }
+
         private void detachLocked() {
             if (DEBUG_STACK) Slog.d(TAG, "detachLocked: " + this + " from display="
                     + mActivityDisplay + " Callers=" + Debug.getCallers(2));
@@ -3099,24 +3131,18 @@
         }
 
         @Override
-        public void detachFromDisplay() {
-            synchronized (mService) {
-                detachLocked();
-            }
-        }
-
-        @Override
         public final int startActivity(Intent intent) {
             mService.enforceNotIsolatedCaller("ActivityContainer.startActivity");
             int userId = mService.handleIncomingUser(Binder.getCallingPid(),
                     Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
             // TODO: Switch to user app stacks here.
+            intent.addFlags(FORCE_NEW_TASK_FLAGS);
             String mimeType = intent.getType();
             if (mimeType == null && intent.getData() != null
                     && "content".equals(intent.getData().getScheme())) {
                 mimeType = mService.getProviderMimeType(intent.getData(), userId);
             }
-            return startActivityMayWait(null, -1, null, intent, mimeType, null, null, 0, 0, null,
+            return startActivityMayWait(null, -1, null, intent, mimeType, null, null, null, null, 0, 0, null,
                     null, null, null, null, userId, this);
         }
 
@@ -3129,7 +3155,41 @@
             }
 
             return ((PendingIntentRecord)intentSender).sendInner(0, null, null, null, null, null,
-                    null, 0, 0, 0, null, this);
+                    null, 0, FORCE_NEW_TASK_FLAGS, FORCE_NEW_TASK_FLAGS, null, this);
+        }
+
+        private void checkEmbeddedAllowedInner(Intent intent, String resolvedType) {
+            int userId = mService.handleIncomingUser(Binder.getCallingPid(),
+                    Binder.getCallingUid(), mCurrentUser, false, true, "ActivityContainer", null);
+            if (resolvedType == null) {
+                resolvedType = intent.getType();
+                if (resolvedType == null && intent.getData() != null
+                        && "content".equals(intent.getData().getScheme())) {
+                    resolvedType = mService.getProviderMimeType(intent.getData(), userId);
+                }
+            }
+            ActivityInfo aInfo = resolveActivity(intent, resolvedType, 0, null, null, userId);
+            if ((aInfo.flags & ActivityInfo.FLAG_ALLOW_EMBEDDED) == 0) {
+                throw new SecurityException(
+                        "Attempt to embed activity that has not set allowEmbedded=\"true\"");
+            }
+        }
+
+        /** Throw a SecurityException if allowEmbedded is not true */
+        @Override
+        public final void checkEmbeddedAllowed(Intent intent) {
+            checkEmbeddedAllowedInner(intent, null);
+        }
+
+        /** Throw a SecurityException if allowEmbedded is not true */
+        @Override
+        public final void checkEmbeddedAllowedIntentSender(IIntentSender intentSender) {
+            if (!(intentSender instanceof PendingIntentRecord)) {
+                throw new IllegalArgumentException("Bad PendingIntent object");
+            }
+            PendingIntentRecord pendingIntent = (PendingIntentRecord) intentSender;
+            checkEmbeddedAllowedInner(pendingIntent.key.requestIntent,
+                    pendingIntent.key.requestResolvedType);
         }
 
         @Override
@@ -3138,23 +3198,8 @@
         }
 
         @Override
-        public void attachToSurface(Surface surface, int width, int height, int density) {
+        public void setSurface(Surface surface, int width, int height, int density) {
             mService.enforceNotIsolatedCaller("ActivityContainer.attachToSurface");
-
-            final long origId = Binder.clearCallingIdentity();
-            try {
-                synchronized (mService) {
-                    ActivityDisplay activityDisplay =
-                            new ActivityDisplay(surface, width, height, density);
-                    mActivityDisplays.put(activityDisplay.mDisplayId, activityDisplay);
-                    attachToDisplayLocked(activityDisplay);
-                    mStack.resumeTopActivityLocked(null);
-                }
-                if (DEBUG_STACK) Slog.d(TAG, "attachToSurface: " + this + " to display="
-                        + mActivityDisplay);
-            } finally {
-                Binder.restoreCallingIdentity(origId);
-            }
         }
 
         ActivityStackSupervisor getOuter() {
@@ -3173,52 +3218,125 @@
             }
         }
 
+        // TODO: Make sure every change to ActivityRecord.visible results in a call to this.
+        void setVisible(boolean visible) {
+            if (mVisible != visible) {
+                mVisible = visible;
+                if (mCallback != null) {
+                    mHandler.obtainMessage(CONTAINER_CALLBACK_VISIBILITY, visible ? 1 : 0,
+                            0 /* unused */, this).sendToTarget();
+                }
+            }
+        }
+
+        void setDrawn() {
+        }
+
         @Override
         public String toString() {
             return mIdString + (mActivityDisplay == null ? "N" : "A");
         }
     }
 
+    private class VirtualActivityContainer extends ActivityContainer {
+        Surface mSurface;
+        boolean mDrawn = false;
+
+        VirtualActivityContainer(ActivityRecord parent, IActivityContainerCallback callback) {
+            super(getNextStackId());
+            mParentActivity = parent;
+            mCallback = callback;
+            mContainerState = CONTAINER_STATE_NO_SURFACE;
+            mIdString = "VirtualActivtyContainer{" + mStackId + ", parent=" + mParentActivity + "}";
+        }
+
+        @Override
+        public void setSurface(Surface surface, int width, int height, int density) {
+            super.setSurface(surface, width, height, density);
+
+            synchronized (mService) {
+                final long origId = Binder.clearCallingIdentity();
+                try {
+                    setSurfaceLocked(surface, width, height, density);
+                } finally {
+                    Binder.restoreCallingIdentity(origId);
+                }
+            }
+        }
+
+        private void setSurfaceLocked(Surface surface, int width, int height, int density) {
+            if (mContainerState == CONTAINER_STATE_FINISHING) {
+                return;
+            }
+            VirtualActivityDisplay virtualActivityDisplay =
+                    (VirtualActivityDisplay) mActivityDisplay;
+            if (virtualActivityDisplay == null) {
+                virtualActivityDisplay =
+                        new VirtualActivityDisplay(width, height, density);
+                mActivityDisplay = virtualActivityDisplay;
+                mActivityDisplays.put(virtualActivityDisplay.mDisplayId, virtualActivityDisplay);
+                attachToDisplayLocked(virtualActivityDisplay);
+            }
+
+            if (mSurface != null) {
+                mSurface.release();
+            }
+
+            mSurface = surface;
+            if (surface != null) {
+                mStack.resumeTopActivityLocked(null);
+            } else {
+                mContainerState = CONTAINER_STATE_NO_SURFACE;
+                ((VirtualActivityDisplay) mActivityDisplay).setSurface(null);
+//                if (mStack.mPausingActivity == null && mStack.mResumedActivity != null) {
+//                    mStack.startPausingLocked(false, true);
+//                }
+            }
+
+            setSurfaceIfReady();
+
+            if (DEBUG_STACK) Slog.d(TAG, "setSurface: " + this + " to display="
+                    + virtualActivityDisplay);
+        }
+
+        @Override
+        void setDrawn() {
+            synchronized (mService) {
+                mDrawn = true;
+                setSurfaceIfReady();
+            }
+        }
+
+        private void setSurfaceIfReady() {
+            if (DEBUG_STACK) Slog.v(TAG, "setSurfaceIfReady: mDrawn=" + mDrawn +
+                    " mContainerState=" + mContainerState + " mSurface=" + mSurface);
+            if (mDrawn && mSurface != null && mContainerState == CONTAINER_STATE_NO_SURFACE) {
+                ((VirtualActivityDisplay) mActivityDisplay).setSurface(mSurface);
+                mContainerState = CONTAINER_STATE_HAS_SURFACE;
+            }
+        }
+    }
+
     /** Exactly one of these classes per Display in the system. Capable of holding zero or more
      * attached {@link ActivityStack}s */
-    final class ActivityDisplay {
+    class ActivityDisplay {
         /** Actual Display this object tracks. */
         int mDisplayId;
         Display mDisplay;
         DisplayInfo mDisplayInfo = new DisplayInfo();
-        Surface mSurface;
 
         /** All of the stacks on this display. Order matters, topmost stack is in front of all other
          * stacks, bottommost behind. Accessed directly by ActivityManager package classes */
         final ArrayList<ActivityStack> mStacks = new ArrayList<ActivityStack>();
 
-        /** If this display is for an ActivityView then the VirtualDisplay created for it is stored
-         * here. */
-        VirtualDisplay mVirtualDisplay;
+        ActivityDisplay() {
+        }
 
         ActivityDisplay(int displayId) {
             init(mDisplayManager.getDisplay(displayId));
         }
 
-        ActivityDisplay(Surface surface, int width, int height, int density) {
-            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
-            long ident = Binder.clearCallingIdentity();
-            try {
-                mVirtualDisplay = dm.createVirtualDisplay(mService.mContext,
-                        VIRTUAL_DISPLAY_BASE_NAME, width, height, density, surface,
-                        DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
-                        DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
-            } finally {
-                Binder.restoreCallingIdentity(ident);
-            }
-
-            init(mVirtualDisplay.getDisplay());
-            mSurface = surface;
-
-            mWindowManager.handleDisplayAdded(mDisplayId);
-        }
-
-        private void init(Display display) {
+        void init(Display display) {
             mDisplay = display;
             mDisplayId = display.getDisplayId();
             mDisplay.getDisplayInfo(mDisplayInfo);
@@ -3234,11 +3352,6 @@
             if (DEBUG_STACK) Slog.v(TAG, "detachActivitiesLocked: detaching " + stack
                     + " from displayId=" + mDisplayId);
             mStacks.remove(stack);
-            if (mStacks.isEmpty() && mVirtualDisplay != null) {
-                mVirtualDisplay.release();
-                mVirtualDisplay = null;
-            }
-            mSurface.release();
         }
 
         void getBounds(Point bounds) {
@@ -3249,8 +3362,42 @@
 
         @Override
         public String toString() {
-            return "ActivityDisplay={" + mDisplayId + (mVirtualDisplay == null ? "" : "V")
-                    + " numStacks=" + mStacks.size() + "}";
+            return "ActivityDisplay={" + mDisplayId + " numStacks=" + mStacks.size() + "}";
+        }
+    }
+
+    class VirtualActivityDisplay extends ActivityDisplay {
+        VirtualDisplay mVirtualDisplay;
+
+        VirtualActivityDisplay(int width, int height, int density) {
+            DisplayManagerGlobal dm = DisplayManagerGlobal.getInstance();
+            mVirtualDisplay = dm.createVirtualDisplay(mService.mContext, VIRTUAL_DISPLAY_BASE_NAME,
+                    width, height, density, null, DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC |
+                    DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY);
+
+            init(mVirtualDisplay.getDisplay());
+
+            mWindowManager.handleDisplayAdded(mDisplayId);
+        }
+
+        void setSurface(Surface surface) {
+            if (mVirtualDisplay != null) {
+                mVirtualDisplay.setSurface(surface);
+            }
+        }
+
+        @Override
+        void detachActivitiesLocked(ActivityStack stack) {
+            super.detachActivitiesLocked(stack);
+            if (mVirtualDisplay != null) {
+                mVirtualDisplay.release();
+                mVirtualDisplay = null;
+            }
+        }
+
+        @Override
+        public String toString() {
+            return "VirtualActivityDisplay={" + mDisplayId + "}";
         }
     }
 }
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 0ddb827..83e8a4b 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -32,6 +32,7 @@
 import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.SignalStrength;
 import android.telephony.TelephonyManager;
 import android.util.Slog;
@@ -109,6 +110,20 @@
         return data;
     }
     
+    public long computeBatteryTimeRemaining() {
+        synchronized (mStats) {
+            long time = mStats.computeBatteryTimeRemaining(SystemClock.elapsedRealtime());
+            return time >= 0 ? (time/1000) : time;
+        }
+    }
+
+    public long computeChargeTimeRemaining() {
+        synchronized (mStats) {
+            long time = mStats.computeChargeTimeRemaining(SystemClock.elapsedRealtime());
+            return time >= 0 ? (time/1000) : time;
+        }
+    }
+
     public void addIsolatedUid(int isolatedUid, int appUid) {
         enforceCallingPermission();
         synchronized (mStats) {
@@ -248,10 +263,10 @@
         }
     }
 
-    public void noteDataConnectionActive(int type, boolean active, long timestampNs) {
+    public void noteMobileRadioPowerState(int powerState, long timestampNs) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.noteDataConnectionActive(type, active, timestampNs);
+            mStats.noteMobileRadioPowerState(powerState, timestampNs);
         }
     }
 
diff --git a/services/core/java/com/android/server/am/BroadcastQueue.java b/services/core/java/com/android/server/am/BroadcastQueue.java
index b15fa5d..9d6481a 100644
--- a/services/core/java/com/android/server/am/BroadcastQueue.java
+++ b/services/core/java/com/android/server/am/BroadcastQueue.java
@@ -503,7 +503,7 @@
                     // are already core system stuff so don't matter for this.
                     r.curApp = filter.receiverList.app;
                     filter.receiverList.app.curReceiver = r;
-                    mService.updateOomAdjLocked(r.curApp, true);
+                    mService.updateOomAdjLocked(r.curApp);
                 }
             }
             try {
diff --git a/services/core/java/com/android/server/am/NativeCrashListener.java b/services/core/java/com/android/server/am/NativeCrashListener.java
index b12843b..d42d415 100644
--- a/services/core/java/com/android/server/am/NativeCrashListener.java
+++ b/services/core/java/com/android/server/am/NativeCrashListener.java
@@ -17,18 +17,18 @@
 package com.android.server.am;
 
 import android.app.ApplicationErrorReport.CrashInfo;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructTimeval;
+import android.system.StructUcred;
 import android.util.Slog;
 
-import libcore.io.ErrnoException;
-import libcore.io.Libcore;
-import libcore.io.StructTimeval;
-import libcore.io.StructUcred;
-
-import static libcore.io.OsConstants.*;
+import static android.system.OsConstants.*;
 
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileDescriptor;
+import java.io.InterruptedIOException;
 import java.net.InetSocketAddress;
 import java.net.InetUnixAddress;
 
@@ -76,7 +76,7 @@
             try {
                 CrashInfo ci = new CrashInfo();
                 ci.exceptionClassName = "Native crash";
-                ci.exceptionMessage = Libcore.os.strsignal(mSignal);
+                ci.exceptionMessage = Os.strsignal(mSignal);
                 ci.throwFileName = "unknown";
                 ci.throwClassName = "unknown";
                 ci.throwMethodName = "unknown";
@@ -116,22 +116,22 @@
         }
 
         try {
-            FileDescriptor serverFd = Libcore.os.socket(AF_UNIX, SOCK_STREAM, 0);
+            FileDescriptor serverFd = Os.socket(AF_UNIX, SOCK_STREAM, 0);
             final InetUnixAddress sockAddr = new InetUnixAddress(DEBUGGERD_SOCKET_PATH);
-            Libcore.os.bind(serverFd, sockAddr, 0);
-            Libcore.os.listen(serverFd, 1);
+            Os.bind(serverFd, sockAddr, 0);
+            Os.listen(serverFd, 1);
 
             while (true) {
                 InetSocketAddress peer = new InetSocketAddress();
                 FileDescriptor peerFd = null;
                 try {
                     if (MORE_DEBUG) Slog.v(TAG, "Waiting for debuggerd connection");
-                    peerFd = Libcore.os.accept(serverFd, peer);
+                    peerFd = Os.accept(serverFd, peer);
                     if (MORE_DEBUG) Slog.v(TAG, "Got debuggerd socket " + peerFd);
                     if (peerFd != null) {
                         // Only the superuser is allowed to talk to us over this socket
                         StructUcred credentials =
-                                Libcore.os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED);
+                                Os.getsockoptUcred(peerFd, SOL_SOCKET, SO_PEERCRED);
                         if (credentials.uid == 0) {
                             // the reporting thread may take responsibility for
                             // acking the debugger; make sure we play along.
@@ -145,7 +145,7 @@
                     // byte written is irrelevant.
                     if (peerFd != null) {
                         try {
-                            Libcore.os.write(peerFd, ackSignal, 0, 1);
+                            Os.write(peerFd, ackSignal, 0, 1);
                         } catch (Exception e) {
                             /* we don't care about failures here */
                             if (MORE_DEBUG) {
@@ -153,7 +153,7 @@
                             }
                         }
                         try {
-                            Libcore.os.close(peerFd);
+                            Os.close(peerFd);
                         } catch (ErrnoException e) {
                             if (MORE_DEBUG) {
                                 Slog.d(TAG, "Exception closing socket: " + e.getMessage());
@@ -178,10 +178,10 @@
     }
 
     static int readExactly(FileDescriptor fd, byte[] buffer, int offset, int numBytes)
-            throws ErrnoException {
+            throws ErrnoException, InterruptedIOException {
         int totalRead = 0;
         while (numBytes > 0) {
-            int n = Libcore.os.read(fd, buffer, offset + totalRead, numBytes);
+            int n = Os.read(fd, buffer, offset + totalRead, numBytes);
             if (n <= 0) {
                 if (DEBUG) {
                     Slog.w(TAG, "Needed " + numBytes + " but saw " + n);
@@ -202,8 +202,8 @@
 
         try {
             StructTimeval timeout = StructTimeval.fromMillis(SOCKET_TIMEOUT_MILLIS);
-            Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout);
-            Libcore.os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout);
+            Os.setsockoptTimeval(fd, SOL_SOCKET, SO_RCVTIMEO, timeout);
+            Os.setsockoptTimeval(fd, SOL_SOCKET, SO_SNDTIMEO, timeout);
 
             // first, the pid and signal number
             int headerBytes = readExactly(fd, buf, 0, 8);
@@ -237,7 +237,7 @@
                     int bytes;
                     do {
                         // get some data
-                        bytes = Libcore.os.read(fd, buf, 0, buf.length);
+                        bytes = Os.read(fd, buf, 0, buf.length);
                         if (bytes > 0) {
                             if (MORE_DEBUG) {
                                 String s = new String(buf, 0, bytes, "UTF-8");
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index d04a6b2..8d7d300 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -77,7 +77,6 @@
     int curSchedGroup;          // Currently desired scheduling class
     int setSchedGroup;          // Last set to background scheduling class
     int trimMemoryLevel;        // Last selected memory trimming level
-    int memImportance;          // Importance constant computed from curAdj
     int curProcState = -1;      // Currently computed process state: ActivityManager.PROCESS_STATE_*
     int repProcState = -1;      // Last reported process state
     int setProcState = -1;      // Last set process state in process tracker
@@ -91,6 +90,7 @@
     boolean hasStartedServices; // Are there any started services running in this process?
     boolean foregroundServices; // Running any services that are foreground?
     boolean foregroundActivities; // Running any activities that are foreground?
+    boolean repForegroundActivities; // Last reported foreground activities.
     boolean systemNoUi;         // This is a system process, but not currently showing UI.
     boolean hasShownUi;         // Has UI been shown in this process since it was started?
     boolean pendingUiClean;     // Want to clean up resources from showing UI?
@@ -267,9 +267,10 @@
             pw.print(prefix); pw.print("persistent="); pw.print(persistent);
                     pw.print(" removed="); pw.println(removed);
         }
-        if (hasClientActivities || foregroundActivities) {
+        if (hasClientActivities || foregroundActivities || repForegroundActivities) {
             pw.print(prefix); pw.print("hasClientActivities="); pw.print(hasClientActivities);
-                    pw.print(" foregroundActivities="); pw.println(foregroundActivities);
+                    pw.print(" foregroundActivities="); pw.print(foregroundActivities);
+                    pw.print(" (rep="); pw.print(repForegroundActivities); pw.println(")");
         }
         if (hasStartedServices) {
             pw.print(prefix); pw.print("hasStartedServices="); pw.println(hasStartedServices);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 363a9b7..e54c95e 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -193,14 +193,7 @@
                         pw.println(si.neededGrants);
             }
             if (si.uriPermissions != null) {
-                if (si.uriPermissions.readUriPermissions != null) {
-                    pw.print(prefix); pw.print("  readUriPermissions=");
-                            pw.println(si.uriPermissions.readUriPermissions);
-                }
-                if (si.uriPermissions.writeUriPermissions != null) {
-                    pw.print(prefix); pw.print("  writeUriPermissions=");
-                            pw.println(si.uriPermissions.writeUriPermissions);
-                }
+                si.uriPermissions.dump(pw, prefix);
             }
         }
     }
diff --git a/services/core/java/com/android/server/am/TaskRecord.java b/services/core/java/com/android/server/am/TaskRecord.java
index 3a43521..68da54d 100644
--- a/services/core/java/com/android/server/am/TaskRecord.java
+++ b/services/core/java/com/android/server/am/TaskRecord.java
@@ -28,7 +28,9 @@
 import android.content.pm.ActivityInfo;
 import android.graphics.Bitmap;
 import android.os.UserHandle;
+import android.service.voice.IVoiceInteractionSession;
 import android.util.Slog;
+import com.android.internal.app.IVoiceInteractor;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -36,6 +38,8 @@
 final class TaskRecord extends ThumbnailHolder {
     final int taskId;       // Unique identifier for this task.
     final String affinity;  // The affinity name for this task, or null.
+    final IVoiceInteractionSession voiceSession;    // Voice interaction session driving task
+    final IVoiceInteractor voiceInteractor;         // Associated interactor to provide to app
     Intent intent;          // The original intent that started the task.
     Intent affinityIntent;  // Intent of affinity-moved activity that started this task.
     ComponentName origActivity; // The non-alias activity component of the intent.
@@ -64,9 +68,12 @@
      * Display.DEFAULT_DISPLAY. */
     boolean mOnTopOfHome = false;
 
-    TaskRecord(int _taskId, ActivityInfo info, Intent _intent) {
+    TaskRecord(int _taskId, ActivityInfo info, Intent _intent,
+            IVoiceInteractionSession _voiceSession, IVoiceInteractor _voiceInteractor) {
         taskId = _taskId;
         affinity = info.taskAffinity;
+        voiceSession = _voiceSession;
+        voiceInteractor = _voiceInteractor;
         setIntent(_intent, info);
     }
 
@@ -139,6 +146,18 @@
         }
     }
 
+    /** Returns the first non-finishing activity from the root. */
+    ActivityRecord getRootActivity() {
+        for (int i = 0; i < mActivities.size(); i++) {
+            final ActivityRecord r = mActivities.get(i);
+            if (r.finishing) {
+                continue;
+            }
+            return r;
+        }
+        return null;
+    }
+
     ActivityRecord getTopActivity() {
         for (int i = mActivities.size() - 1; i >= 0; --i) {
             final ActivityRecord r = mActivities.get(i);
@@ -305,7 +324,7 @@
     }
 
     public ActivityManager.TaskThumbnails getTaskThumbnailsLocked() {
-        TaskAccessInfo info = getTaskAccessInfoLocked(true);
+        TaskAccessInfo info = getTaskAccessInfoLocked();
         final ActivityRecord resumedActivity = stack.mResumedActivity;
         if (resumedActivity != null && resumedActivity.thumbHolder == this) {
             info.mainThumbnail = stack.screenshotActivities(resumedActivity);
@@ -325,7 +344,7 @@
         }
         // Return the information about the task, to figure out the top
         // thumbnail to return.
-        TaskAccessInfo info = getTaskAccessInfoLocked(true);
+        TaskAccessInfo info = getTaskAccessInfoLocked();
         if (info.numSubThumbbails <= 0) {
             return info.mainThumbnail != null ? info.mainThumbnail : lastThumbnail;
         }
@@ -334,7 +353,7 @@
 
     public ActivityRecord removeTaskActivitiesLocked(int subTaskIndex,
             boolean taskRequired) {
-        TaskAccessInfo info = getTaskAccessInfoLocked(false);
+        TaskAccessInfo info = getTaskAccessInfoLocked();
         if (info.root == null) {
             if (taskRequired) {
                 Slog.w(TAG, "removeTaskLocked: unknown taskId " + taskId);
@@ -369,7 +388,7 @@
         return mTaskType == ActivityRecord.APPLICATION_ACTIVITY_TYPE;
     }
 
-    public TaskAccessInfo getTaskAccessInfoLocked(boolean inclThumbs) {
+    public TaskAccessInfo getTaskAccessInfoLocked() {
         final TaskAccessInfo thumbs = new TaskAccessInfo();
         // How many different sub-thumbnails?
         final int NA = mActivities.size();
@@ -461,6 +480,12 @@
         if (affinity != null) {
             pw.print(prefix); pw.print("affinity="); pw.println(affinity);
         }
+        if (voiceSession != null || voiceInteractor != null) {
+            pw.print(prefix); pw.print("VOICE: session=0x");
+            pw.print(Integer.toHexString(System.identityHashCode(voiceSession)));
+            pw.print(" interactor=0x");
+            pw.println(Integer.toHexString(System.identityHashCode(voiceInteractor)));
+        }
         if (intent != null) {
             StringBuilder sb = new StringBuilder(128);
             sb.append(prefix); sb.append("intent={");
diff --git a/services/core/java/com/android/server/am/UriPermission.java b/services/core/java/com/android/server/am/UriPermission.java
index 1f12b74..4970b8d 100644
--- a/services/core/java/com/android/server/am/UriPermission.java
+++ b/services/core/java/com/android/server/am/UriPermission.java
@@ -17,15 +17,16 @@
 package com.android.server.am;
 
 import android.content.Intent;
-import android.net.Uri;
 import android.os.UserHandle;
+import android.util.ArraySet;
 import android.util.Log;
+import android.util.Slog;
 
+import com.android.server.am.ActivityManagerService.GrantUri;
 import com.google.android.collect.Sets;
 
 import java.io.PrintWriter;
 import java.util.Comparator;
-import java.util.HashSet;
 
 /**
  * Description of a permission granted to an app to access a particular URI.
@@ -50,7 +51,7 @@
     /** Cached UID of {@link #targetPkg}; should not be persisted */
     final int targetUid;
 
-    final Uri uri;
+    final GrantUri uri;
 
     /**
      * Allowed modes. All permission enforcement should use this field. Must
@@ -61,12 +62,13 @@
      */
     int modeFlags = 0;
 
-    /** Allowed modes with explicit owner. */
+    /** Allowed modes with active owner. */
     int ownedModeFlags = 0;
     /** Allowed modes without explicit owner. */
     int globalModeFlags = 0;
     /** Allowed modes that have been offered for possible persisting. */
     int persistableModeFlags = 0;
+
     /** Allowed modes that should be persisted across device boots. */
     int persistedModeFlags = 0;
 
@@ -78,12 +80,12 @@
 
     private static final long INVALID_TIME = Long.MIN_VALUE;
 
-    private HashSet<UriPermissionOwner> mReadOwners;
-    private HashSet<UriPermissionOwner> mWriteOwners;
+    private ArraySet<UriPermissionOwner> mReadOwners;
+    private ArraySet<UriPermissionOwner> mWriteOwners;
 
     private String stringName;
 
-    UriPermission(String sourcePkg, String targetPkg, int targetUid, Uri uri) {
+    UriPermission(String sourcePkg, String targetPkg, int targetUid, GrantUri uri) {
         this.userHandle = UserHandle.getUserId(targetUid);
         this.sourcePkg = sourcePkg;
         this.targetPkg = targetPkg;
@@ -100,6 +102,9 @@
      * global or owner grants.
      */
     void initPersistedModes(int modeFlags, long createdTime) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         persistableModeFlags = modeFlags;
         persistedModeFlags = modeFlags;
         persistedCreateTime = createdTime;
@@ -107,7 +112,11 @@
         updateModeFlags();
     }
 
-    void grantModes(int modeFlags, boolean persistable, UriPermissionOwner owner) {
+    void grantModes(int modeFlags, UriPermissionOwner owner) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         if (persistable) {
             persistableModeFlags |= modeFlags;
         }
@@ -130,10 +139,14 @@
      * @return if mode changes should trigger persisting.
      */
     boolean takePersistableModes(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         if ((modeFlags & persistableModeFlags) != modeFlags) {
-            throw new SecurityException("Requested flags 0x"
+            Slog.w(TAG, "Requested flags 0x"
                     + Integer.toHexString(modeFlags) + ", but only 0x"
                     + Integer.toHexString(persistableModeFlags) + " are allowed");
+            return false;
         }
 
         final int before = persistedModeFlags;
@@ -148,6 +161,9 @@
     }
 
     boolean releasePersistableModes(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         final int before = persistedModeFlags;
 
         persistableModeFlags &= ~modeFlags;
@@ -164,7 +180,11 @@
     /**
      * @return if mode changes should trigger persisting.
      */
-    boolean clearModes(int modeFlags, boolean persistable) {
+    boolean revokeModes(int modeFlags) {
+        final boolean persistable = (modeFlags & Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION) != 0;
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+
         final int before = persistedModeFlags;
 
         if ((modeFlags & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0) {
@@ -208,6 +228,8 @@
      * Return strength of this permission grant for the given flags.
      */
     public int getStrength(int modeFlags) {
+        modeFlags &= (Intent.FLAG_GRANT_READ_URI_PERMISSION
+                | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
         if ((persistableModeFlags & modeFlags) == modeFlags) {
             return STRENGTH_PERSISTABLE;
         } else if ((globalModeFlags & modeFlags) == modeFlags) {
@@ -221,7 +243,7 @@
 
     private void addReadOwner(UriPermissionOwner owner) {
         if (mReadOwners == null) {
-            mReadOwners = Sets.newHashSet();
+            mReadOwners = Sets.newArraySet();
             ownedModeFlags |= Intent.FLAG_GRANT_READ_URI_PERMISSION;
             updateModeFlags();
         }
@@ -246,7 +268,7 @@
 
     private void addWriteOwner(UriPermissionOwner owner) {
         if (mWriteOwners == null) {
-            mWriteOwners = Sets.newHashSet();
+            mWriteOwners = Sets.newArraySet();
             ownedModeFlags |= Intent.FLAG_GRANT_WRITE_URI_PERMISSION;
             updateModeFlags();
         }
@@ -333,7 +355,7 @@
         final int userHandle;
         final String sourcePkg;
         final String targetPkg;
-        final Uri uri;
+        final GrantUri uri;
         final int persistedModeFlags;
         final long persistedCreateTime;
 
@@ -352,6 +374,6 @@
     }
 
     public android.content.UriPermission buildPersistedPublicApiObject() {
-        return new android.content.UriPermission(uri, persistedModeFlags, persistedCreateTime);
+        return new android.content.UriPermission(uri.uri, persistedModeFlags, persistedCreateTime);
     }
 }
diff --git a/services/core/java/com/android/server/am/UriPermissionOwner.java b/services/core/java/com/android/server/am/UriPermissionOwner.java
index 7bbd3bc..65d7047 100644
--- a/services/core/java/com/android/server/am/UriPermissionOwner.java
+++ b/services/core/java/com/android/server/am/UriPermissionOwner.java
@@ -20,8 +20,11 @@
 import android.net.Uri;
 import android.os.Binder;
 import android.os.IBinder;
+import android.util.ArraySet;
 
-import java.util.HashSet;
+import com.google.android.collect.Sets;
+
+import java.io.PrintWriter;
 import java.util.Iterator;
 
 final class UriPermissionOwner {
@@ -30,8 +33,8 @@
 
     Binder externalToken;
 
-    HashSet<UriPermission> readUriPermissions; // special access to reading uris.
-    HashSet<UriPermission> writeUriPermissions; // special access to writing uris.
+    private ArraySet<UriPermission> mReadPerms;
+    private ArraySet<UriPermission> mWritePerms;
 
     class ExternalToken extends Binder {
         UriPermissionOwner getOwner() {
@@ -39,9 +42,9 @@
         }
     }
 
-    UriPermissionOwner(ActivityManagerService _service, Object _owner) {
-        service = _service;
-        owner = _owner;
+    UriPermissionOwner(ActivityManagerService service, Object owner) {
+        this.service = service;
+        this.owner = owner;
     }
 
     Binder getExternalTokenLocked() {
@@ -64,82 +67,76 @@
     }
 
     void removeUriPermissionsLocked(int mode) {
-        if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
-                && readUriPermissions != null) {
-            for (UriPermission perm : readUriPermissions) {
-                perm.removeReadOwner(this);
-                service.removeUriPermissionIfNeededLocked(perm);
-            }
-            readUriPermissions = null;
-        }
-        if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
-                && writeUriPermissions != null) {
-            for (UriPermission perm : writeUriPermissions) {
-                perm.removeWriteOwner(this);
-                service.removeUriPermissionIfNeededLocked(perm);
-            }
-            writeUriPermissions = null;
-        }
+        removeUriPermissionLocked(null, mode);
     }
 
     void removeUriPermissionLocked(Uri uri, int mode) {
-        if ((mode&Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
-                && readUriPermissions != null) {
-            Iterator<UriPermission> it = readUriPermissions.iterator();
+        if ((mode & Intent.FLAG_GRANT_READ_URI_PERMISSION) != 0
+                && mReadPerms != null) {
+            Iterator<UriPermission> it = mReadPerms.iterator();
             while (it.hasNext()) {
                 UriPermission perm = it.next();
-                if (uri.equals(perm.uri)) {
+                if (uri == null || uri.equals(perm.uri)) {
                     perm.removeReadOwner(this);
                     service.removeUriPermissionIfNeededLocked(perm);
                     it.remove();
                 }
             }
-            if (readUriPermissions.size() == 0) {
-                readUriPermissions = null;
+            if (mReadPerms.isEmpty()) {
+                mReadPerms = null;
             }
         }
-        if ((mode&Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
-                && writeUriPermissions != null) {
-            Iterator<UriPermission> it = writeUriPermissions.iterator();
+        if ((mode & Intent.FLAG_GRANT_WRITE_URI_PERMISSION) != 0
+                && mWritePerms != null) {
+            Iterator<UriPermission> it = mWritePerms.iterator();
             while (it.hasNext()) {
                 UriPermission perm = it.next();
-                if (uri.equals(perm.uri)) {
+                if (uri == null || uri.equals(perm.uri)) {
                     perm.removeWriteOwner(this);
                     service.removeUriPermissionIfNeededLocked(perm);
                     it.remove();
                 }
             }
-            if (writeUriPermissions.size() == 0) {
-                writeUriPermissions = null;
+            if (mWritePerms.isEmpty()) {
+                mWritePerms = null;
             }
         }
     }
 
     public void addReadPermission(UriPermission perm) {
-        if (readUriPermissions == null) {
-            readUriPermissions = new HashSet<UriPermission>();
+        if (mReadPerms == null) {
+            mReadPerms = Sets.newArraySet();
         }
-        readUriPermissions.add(perm);
+        mReadPerms.add(perm);
     }
 
     public void addWritePermission(UriPermission perm) {
-        if (writeUriPermissions == null) {
-            writeUriPermissions = new HashSet<UriPermission>();
+        if (mWritePerms == null) {
+            mWritePerms = Sets.newArraySet();
         }
-        writeUriPermissions.add(perm);
+        mWritePerms.add(perm);
     }
 
     public void removeReadPermission(UriPermission perm) {
-        readUriPermissions.remove(perm);
-        if (readUriPermissions.size() == 0) {
-            readUriPermissions = null;
+        mReadPerms.remove(perm);
+        if (mReadPerms.isEmpty()) {
+            mReadPerms = null;
         }
     }
 
     public void removeWritePermission(UriPermission perm) {
-        writeUriPermissions.remove(perm);
-        if (writeUriPermissions.size() == 0) {
-            writeUriPermissions = null;
+        mWritePerms.remove(perm);
+        if (mWritePerms.isEmpty()) {
+            mWritePerms = null;
+        }
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        if (mReadPerms != null) {
+            pw.print(prefix); pw.print("readUriPermissions="); pw.println(mReadPerms);
+        }
+        if (mWritePerms != null) {
+            pw.print(prefix); pw.print("writeUriPermissions="); pw.println(mWritePerms);
         }
     }
 
diff --git a/services/core/java/com/android/server/content/SyncStorageEngine.java b/services/core/java/com/android/server/content/SyncStorageEngine.java
index 3a2e4db..35c494d 100644
--- a/services/core/java/com/android/server/content/SyncStorageEngine.java
+++ b/services/core/java/com/android/server/content/SyncStorageEngine.java
@@ -2443,8 +2443,8 @@
         if (!mPendingFile.getBaseFile().exists()) {
             if (Log.isLoggable(TAG_FILE, Log.VERBOSE)) {
                 Log.v(TAG_FILE, "No pending operation file.");
-                return;
             }
+            return;
         }
         try {
             fis = mPendingFile.openRead();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java b/services/core/java/com/android/server/display/DisplayBlanker.java
similarity index 76%
rename from packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
rename to services/core/java/com/android/server/display/DisplayBlanker.java
index 0377123..eb0ae6a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/OnSizeChangedListener.java
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.systemui.statusbar.policy;
+package com.android.server.display;
 
-import android.view.View;
-
-public interface OnSizeChangedListener {
-    void onSizeChanged(View view, int w, int h, int oldw, int oldh);
+/**
+ * Interface used to update the actual display state.
+ */
+public interface DisplayBlanker {
+    void requestDisplayState(int state);
 }
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 9ec1122..a5f9822 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -107,15 +107,9 @@
     }
 
     /**
-     * Blanks the display, if supported.
+     * Sets the display state, if supported.
      */
-    public void blankLocked() {
-    }
-
-    /**
-     * Unblanks the display, if supported.
-     */
-    public void unblankLocked() {
+    public void requestDisplayStateLocked(int state) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 75f1f53..a77443d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -176,6 +176,11 @@
     public String address;
 
     /**
+     * Display state.
+     */
+    public int state = Display.STATE_ON;
+
+    /**
      * The UID of the application that owns this display, or zero if it is owned by the system.
      * <p>
      * If the display is private, then only the owner can use it.
@@ -219,6 +224,7 @@
                 && rotation == other.rotation
                 && type == other.type
                 && Objects.equal(address, other.address)
+                && state == other.state
                 && ownerUid == other.ownerUid
                 && Objects.equal(ownerPackageName, other.ownerPackageName);
     }
@@ -241,6 +247,7 @@
         rotation = other.rotation;
         type = other.type;
         address = other.address;
+        state = other.state;
         ownerUid = other.ownerUid;
         ownerPackageName = other.ownerPackageName;
     }
@@ -260,6 +267,7 @@
         if (address != null) {
             sb.append(", address ").append(address);
         }
+        sb.append(", state ").append(Display.stateToString(state));
         if (ownerUid != 0 || ownerPackageName != null) {
             sb.append(", owner ").append(ownerPackageName);
             sb.append(" (uid ").append(ownerUid).append(")");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 693f7d8..6697b60 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -121,10 +121,6 @@
     private static final int MSG_REQUEST_TRAVERSAL = 4;
     private static final int MSG_UPDATE_VIEWPORT = 5;
 
-    private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
-    private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
-    private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
-
     private final Context mContext;
     private final DisplayManagerHandler mHandler;
     private final Handler mUiHandler;
@@ -176,8 +172,9 @@
     // Display power controller.
     private DisplayPowerController mDisplayPowerController;
 
-    // Set to true if all displays have been blanked by the power manager.
-    private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
+    // The overall display state, independent of changes that might influence one
+    // display or another in particular.
+    private int mGlobalDisplayState = Display.STATE_UNKNOWN;
 
     // Set to true when there are pending display changes that have yet to be applied
     // to the surface flinger state.
@@ -315,21 +312,11 @@
         }
     }
 
-    private void blankAllDisplaysFromPowerManagerInternal() {
+    private void requestGlobalDisplayStateInternal(int state) {
         synchronized (mSyncRoot) {
-            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
-                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
-                updateAllDisplayBlankingLocked();
-                scheduleTraversalLocked(false);
-            }
-        }
-    }
-
-    private void unblankAllDisplaysFromPowerManagerInternal() {
-        synchronized (mSyncRoot) {
-            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
-                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
-                updateAllDisplayBlankingLocked();
+            if (mGlobalDisplayState != state) {
+                mGlobalDisplayState = state;
+                updateGlobalDisplayStateLocked();
                 scheduleTraversalLocked(false);
             }
         }
@@ -530,6 +517,16 @@
         return -1;
     }
 
+    private void setVirtualDisplaySurfaceInternal(IBinder appToken, Surface surface) {
+        synchronized (mSyncRoot) {
+            if (mVirtualDisplayAdapter == null) {
+                return;
+            }
+
+            mVirtualDisplayAdapter.setVirtualDisplaySurfaceLocked(appToken, surface);
+        }
+    }
+
     private void releaseVirtualDisplayInternal(IBinder appToken) {
         synchronized (mSyncRoot) {
             if (mVirtualDisplayAdapter == null) {
@@ -616,7 +613,7 @@
 
         mDisplayDevices.add(device);
         addLogicalDisplayLocked(device);
-        updateDisplayBlankingLocked(device);
+        updateDisplayStateLocked(device);
         scheduleTraversalLocked(false);
     }
 
@@ -655,27 +652,20 @@
         scheduleTraversalLocked(false);
     }
 
-    private void updateAllDisplayBlankingLocked() {
+    private void updateGlobalDisplayStateLocked() {
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            updateDisplayBlankingLocked(device);
+            updateDisplayStateLocked(device);
         }
     }
 
-    private void updateDisplayBlankingLocked(DisplayDevice device) {
+    private void updateDisplayStateLocked(DisplayDevice device) {
         // Blank or unblank the display immediately to match the state requested
-        // by the power manager (if known).
+        // by the display power controller (if known).
         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-            switch (mAllDisplayBlankStateFromPowerManager) {
-                case DISPLAY_BLANK_STATE_BLANKED:
-                    device.blankLocked();
-                    break;
-                case DISPLAY_BLANK_STATE_UNBLANKED:
-                    device.unblankLocked();
-                    break;
-            }
+            device.requestDisplayStateLocked(mGlobalDisplayState);
         }
     }
 
@@ -816,9 +806,7 @@
                     + device.getDisplayDeviceInfoLocked());
             return;
         }
-        boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
-                && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
-        display.configureDisplayInTransactionLocked(device, isBlanked);
+        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
 
         // Update the viewports if needed.
         if (!mDefaultViewport.valid
@@ -897,8 +885,7 @@
             pw.println("  mOnlyCode=" + mOnlyCore);
             pw.println("  mSafeMode=" + mSafeMode);
             pw.println("  mPendingTraversal=" + mPendingTraversal);
-            pw.println("  mAllDisplayBlankStateFromPowerManager="
-                    + mAllDisplayBlankStateFromPowerManager);
+            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
             pw.println("  mDefaultViewport=" + mDefaultViewport);
             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
@@ -1244,9 +1231,6 @@
                 throw new IllegalArgumentException("width, height, and densityDpi must be "
                         + "greater than 0");
             }
-            if (surface == null) {
-                throw new IllegalArgumentException("surface must not be null");
-            }
             if (callingUid != Process.SYSTEM_UID &&
                     (flags & DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC) != 0) {
                 if (mContext.checkCallingPermission(android.Manifest.permission.CAPTURE_VIDEO_OUTPUT)
@@ -1278,6 +1262,16 @@
         }
 
         @Override // Binder call
+        public void setVirtualDisplaySurface(IBinder appToken, Surface surface) {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                setVirtualDisplaySurfaceInternal(appToken, surface);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override // Binder call
         public void releaseVirtualDisplay(IBinder appToken) {
             final long token = Binder.clearCallingIdentity();
             try {
@@ -1322,11 +1316,26 @@
 
     private final class LocalService extends DisplayManagerInternal {
         @Override
-        public void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler,
+        public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
                 SensorManager sensorManager) {
             synchronized (mSyncRoot) {
+                DisplayBlanker blanker = new DisplayBlanker() {
+                    @Override
+                    public void requestDisplayState(int state) {
+                        // The order of operations is important for legacy reasons.
+                        if (state == Display.STATE_OFF) {
+                            requestGlobalDisplayStateInternal(state);
+                        }
+
+                        callbacks.onDisplayStateChange(state);
+
+                        if (state != Display.STATE_OFF) {
+                            requestGlobalDisplayStateInternal(state);
+                        }
+                    }
+                };
                 mDisplayPowerController = new DisplayPowerController(
-                        mContext, callbacks, handler, sensorManager);
+                        mContext, callbacks, handler, sensorManager, blanker);
             }
         }
 
@@ -1343,16 +1352,6 @@
         }
 
         @Override
-        public void blankAllDisplaysFromPowerManager() {
-            blankAllDisplaysFromPowerManagerInternal();
-        }
-
-        @Override
-        public void unblankAllDisplaysFromPowerManager() {
-            unblankAllDisplaysFromPowerManagerInternal();
-        }
-
-        @Override
         public DisplayInfo getDisplayInfo(int displayId) {
             return getDisplayInfoInternal(displayId, Process.myUid());
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 62fb02a..1f38eb6 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -42,6 +42,7 @@
 import android.util.Slog;
 import android.util.Spline;
 import android.util.TimeUtils;
+import android.view.Display;
 
 import java.io.PrintWriter;
 
@@ -122,6 +123,9 @@
     // The sensor manager.
     private final SensorManager mSensorManager;
 
+    // The display blanker.
+    private final DisplayBlanker mBlanker;
+
     // The proximity sensor, or null if not available or needed.
     private Sensor mProximitySensor;
 
@@ -225,13 +229,15 @@
      * Creates the display power controller.
      */
     public DisplayPowerController(Context context,
-            DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) {
+            DisplayPowerCallbacks callbacks, Handler handler,
+            SensorManager sensorManager, DisplayBlanker blanker) {
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mCallbacks = callbacks;
 
         mBatteryStats = BatteryStatsService.getService();
         mLights = LocalServices.getService(LightsManager.class);
         mSensorManager = sensorManager;
+        mBlanker = blanker;
 
         final Resources resources = context.getResources();
 
@@ -366,8 +372,11 @@
     }
 
     private void initialize() {
-        mPowerState = new DisplayPowerState(new ElectronBeam(), mCallbacks,
-                mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
+        // Initialize the power state object for the default display.
+        // In the future, we might manage multiple displays independently.
+        mPowerState = new DisplayPowerState(mBlanker,
+                mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
+                new ElectronBeam(Display.DEFAULT_DISPLAY));
 
         mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
                 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -384,7 +393,7 @@
 
         // Initialize screen state for battery stats.
         try {
-            if (mPowerState.isScreenOn()) {
+            if (mPowerState.getScreenState() != Display.STATE_OFF) {
                 mBatteryStats.noteScreenOn();
             } else {
                 mBatteryStats.noteScreenOff();
@@ -523,7 +532,7 @@
         // Animate the screen on or off unless blocked.
         if (mScreenOffBecauseOfProximity) {
             // Screen off due to proximity.
-            setScreenOn(false);
+            setScreenState(Display.STATE_OFF);
             unblockScreenOn();
         } else if (mPowerRequest.wantScreenOnAny()) {
             // Want screen on.
@@ -534,7 +543,8 @@
                 // Turn the screen on.  The contents of the screen may not yet
                 // be visible if the electron beam has not been dismissed because
                 // its last frame of animation is solid black.
-                setScreenOn(true);
+                setScreenState(mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE
+                        ? Display.STATE_DOZING : Display.STATE_ON);
 
                 if (mPowerRequest.blockScreenOn
                         && mPowerState.getElectronBeamLevel() == 0.0f) {
@@ -567,12 +577,12 @@
             if (!mElectronBeamOnAnimator.isStarted()) {
                 if (!mElectronBeamOffAnimator.isStarted()) {
                     if (mPowerState.getElectronBeamLevel() == 0.0f) {
-                        setScreenOn(false);
+                        setScreenState(Display.STATE_OFF);
                     } else if (mPowerState.prepareElectronBeam(
                             mElectronBeamFadesConfig ?
                                     ElectronBeam.MODE_FADE :
                                             ElectronBeam.MODE_COOL_DOWN)
-                            && mPowerState.isScreenOn()) {
+                            && mPowerState.getScreenState() != Display.STATE_OFF) {
                         mElectronBeamOffAnimator.start();
                     } else {
                         mElectronBeamOffAnimator.end();
@@ -610,9 +620,9 @@
     private void blockScreenOn() {
         if (!mScreenOnWasBlocked) {
             mScreenOnWasBlocked = true;
+            mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
             if (DEBUG) {
                 Slog.d(TAG, "Blocked screen on.");
-                mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
             }
         }
     }
@@ -627,11 +637,11 @@
         }
     }
 
-    private void setScreenOn(boolean on) {
-        if (mPowerState.isScreenOn() != on) {
-            mPowerState.setScreenOn(on);
+    private void setScreenState(int state) {
+        if (mPowerState.getScreenState() != state) {
+            mPowerState.setScreenState(state);
             try {
-                if (on) {
+                if (state != Display.STATE_OFF) {
                     mBatteryStats.noteScreenOn();
                 } else {
                     mBatteryStats.noteScreenOff();
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index e1416d7..a5f8849 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -18,7 +18,6 @@
 
 import com.android.server.lights.Light;
 
-import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
@@ -27,6 +26,7 @@
 import android.util.IntProperty;
 import android.util.Slog;
 import android.view.Choreographer;
+import android.view.Display;
 
 import java.io.PrintWriter;
 
@@ -54,12 +54,12 @@
 
     private final Handler mHandler;
     private final Choreographer mChoreographer;
-    private final ElectronBeam mElectronBeam;
-    private final DisplayPowerCallbacks mCallbacks;
+    private final DisplayBlanker mBlanker;
     private final Light mBacklight;
+    private final ElectronBeam mElectronBeam;
     private final PhotonicModulator mPhotonicModulator;
 
-    private boolean mScreenOn;
+    private int mScreenState;
     private int mScreenBrightness;
     private boolean mScreenReady;
     private boolean mScreenUpdatePending;
@@ -71,13 +71,12 @@
 
     private Runnable mCleanListener;
 
-    public DisplayPowerState(ElectronBeam electronBean,
-            DisplayPowerCallbacks callbacks, Light backlight) {
+    public DisplayPowerState(DisplayBlanker blanker, Light backlight, ElectronBeam electronBeam) {
         mHandler = new Handler(true /*async*/);
         mChoreographer = Choreographer.getInstance();
-        mElectronBeam = electronBean;
-        mCallbacks = callbacks;
+        mBlanker = blanker;
         mBacklight = backlight;
+        mElectronBeam = electronBeam;
         mPhotonicModulator = new PhotonicModulator();
 
         // At boot time, we know that the screen is on and the electron beam
@@ -86,7 +85,7 @@
         // Although we set the brightness to full on here, the display power controller
         // will reset the brightness to a new level immediately before the changes
         // actually have a chance to be applied.
-        mScreenOn = true;
+        mScreenState = Display.STATE_ON;
         mScreenBrightness = PowerManager.BRIGHTNESS_ON;
         scheduleScreenUpdate();
 
@@ -122,25 +121,25 @@
     };
 
     /**
-     * Sets whether the screen is on or off.
+     * Sets whether the screen is on, off, or dozing.
      */
-    public void setScreenOn(boolean on) {
-        if (mScreenOn != on) {
+    public void setScreenState(int state) {
+        if (mScreenState != state) {
             if (DEBUG) {
-                Slog.d(TAG, "setScreenOn: on=" + on);
+                Slog.d(TAG, "setScreenState: state=" + state);
             }
 
-            mScreenOn = on;
+            mScreenState = state;
             mScreenReady = false;
             scheduleScreenUpdate();
         }
     }
 
     /**
-     * Returns true if the screen is on.
+     * Gets the desired screen state.
      */
-    public boolean isScreenOn() {
-        return mScreenOn;
+    public int getScreenState() {
+        return mScreenState;
     }
 
     /**
@@ -155,7 +154,7 @@
             }
 
             mScreenBrightness = brightness;
-            if (mScreenOn) {
+            if (mScreenState != Display.STATE_OFF) {
                 mScreenReady = false;
                 scheduleScreenUpdate();
             }
@@ -219,7 +218,7 @@
             }
 
             mElectronBeamLevel = level;
-            if (mScreenOn) {
+            if (mScreenState != Display.STATE_OFF) {
                 mScreenReady = false;
                 scheduleScreenUpdate(); // update backlight brightness
             }
@@ -256,7 +255,7 @@
     public void dump(PrintWriter pw) {
         pw.println();
         pw.println("Display Power State:");
-        pw.println("  mScreenOn=" + mScreenOn);
+        pw.println("  mScreenState=" + Display.stateToString(mScreenState));
         pw.println("  mScreenBrightness=" + mScreenBrightness);
         pw.println("  mScreenReady=" + mScreenReady);
         pw.println("  mScreenUpdatePending=" + mScreenUpdatePending);
@@ -302,8 +301,9 @@
         public void run() {
             mScreenUpdatePending = false;
 
-            int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
-            if (mPhotonicModulator.setState(mScreenOn, brightness)) {
+            int brightness = mScreenState != Display.STATE_OFF
+                    && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
+            if (mPhotonicModulator.setState(mScreenState, brightness)) {
                 if (DEBUG) {
                     Slog.d(TAG, "Screen ready");
                 }
@@ -335,26 +335,26 @@
      * Updates the state of the screen and backlight asynchronously on a separate thread.
      */
     private final class PhotonicModulator {
-        private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
+        private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
         private static final int INITIAL_BACKLIGHT = -1; // unknown
 
         private final Object mLock = new Object();
 
-        private boolean mPendingOn = INITIAL_SCREEN_ON;
+        private int mPendingState = INITIAL_SCREEN_STATE;
         private int mPendingBacklight = INITIAL_BACKLIGHT;
-        private boolean mActualOn = INITIAL_SCREEN_ON;
+        private int mActualState = INITIAL_SCREEN_STATE;
         private int mActualBacklight = INITIAL_BACKLIGHT;
         private boolean mChangeInProgress;
 
-        public boolean setState(boolean on, int backlight) {
+        public boolean setState(int state, int backlight) {
             synchronized (mLock) {
-                if (on != mPendingOn || backlight != mPendingBacklight) {
+                if (state != mPendingState || backlight != mPendingBacklight) {
                     if (DEBUG) {
-                        Slog.d(TAG, "Requesting new screen state: on=" + on
-                                + ", backlight=" + backlight);
+                        Slog.d(TAG, "Requesting new screen state: state="
+                                + Display.stateToString(state) + ", backlight=" + backlight);
                     }
 
-                    mPendingOn = on;
+                    mPendingState = state;
                     mPendingBacklight = backlight;
 
                     if (!mChangeInProgress) {
@@ -369,9 +369,9 @@
         public void dump(PrintWriter pw) {
             pw.println();
             pw.println("Photonic Modulator State:");
-            pw.println("  mPendingOn=" + mPendingOn);
+            pw.println("  mPendingState=" + Display.stateToString(mPendingState));
             pw.println("  mPendingBacklight=" + mPendingBacklight);
-            pw.println("  mActualOn=" + mActualOn);
+            pw.println("  mActualState=" + Display.stateToString(mActualState));
             pw.println("  mActualBacklight=" + mActualBacklight);
             pw.println("  mChangeInProgress=" + mChangeInProgress);
         }
@@ -381,35 +381,35 @@
             public void run() {
                 // Apply pending changes until done.
                 for (;;) {
-                    final boolean on;
-                    final boolean onChanged;
+                    final int state;
+                    final boolean stateChanged;
                     final int backlight;
                     final boolean backlightChanged;
                     synchronized (mLock) {
-                        on = mPendingOn;
-                        onChanged = (on != mActualOn);
+                        state = mPendingState;
+                        stateChanged = (state != mActualState);
                         backlight = mPendingBacklight;
                         backlightChanged = (backlight != mActualBacklight);
-                        if (!onChanged && !backlightChanged) {
+                        if (!stateChanged && !backlightChanged) {
                             mChangeInProgress = false;
                             break;
                         }
-                        mActualOn = on;
+                        mActualState = state;
                         mActualBacklight = backlight;
                     }
 
                     if (DEBUG) {
-                        Slog.d(TAG, "Updating screen state: on=" + on
-                                + ", backlight=" + backlight);
+                        Slog.d(TAG, "Updating screen state: state="
+                                + Display.stateToString(state) + ", backlight=" + backlight);
                     }
-                    if (onChanged && on) {
-                        mCallbacks.unblankAllDisplays();
+                    if (stateChanged && state != Display.STATE_OFF) {
+                        mBlanker.requestDisplayState(state);
                     }
                     if (backlightChanged) {
                         mBacklight.setBrightness(backlight);
                     }
-                    if (onChanged && !on) {
-                        mCallbacks.blankAllDisplays();
+                    if (stateChanged && state == Display.STATE_OFF) {
+                        mBlanker.requestDisplayState(state);
                     }
                 }
 
diff --git a/services/core/java/com/android/server/display/ElectronBeam.java b/services/core/java/com/android/server/display/ElectronBeam.java
index 13816bb..18e4049 100644
--- a/services/core/java/com/android/server/display/ElectronBeam.java
+++ b/services/core/java/com/android/server/display/ElectronBeam.java
@@ -35,7 +35,6 @@
 import android.os.Looper;
 import android.util.FloatMath;
 import android.util.Slog;
-import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface.OutOfResourcesException;
 import android.view.Surface;
@@ -74,6 +73,8 @@
     // See code for details.
     private static final int DEJANK_FRAMES = 3;
 
+    private final int mDisplayId;
+
     // Set to true when the animation context has been fully prepared.
     private boolean mPrepared;
     private int mMode;
@@ -118,8 +119,8 @@
      */
     public static final int MODE_FADE = 2;
 
-
-    public ElectronBeam() {
+    public ElectronBeam(int displayId) {
+        mDisplayId = displayId;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
     }
 
@@ -139,7 +140,7 @@
 
         // Get the display size and layer stack.
         // This is not expected to change while the electron beam surface is showing.
-        DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+        DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
         mDisplayLayerStack = displayInfo.layerStack;
         mDisplayWidth = displayInfo.getNaturalWidth();
         mDisplayHeight = displayInfo.getNaturalHeight();
@@ -528,7 +529,8 @@
             mSurface = new Surface();
             mSurface.copyFrom(mSurfaceControl);
 
-            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl);
+            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+                    mDisplayId, mSurfaceControl);
             mSurfaceLayout.onDisplayTransaction();
         } finally {
             SurfaceControl.closeTransaction();
@@ -687,11 +689,13 @@
      */
     private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
         private final DisplayManagerInternal mDisplayManagerInternal;
+        private final int mDisplayId;
         private SurfaceControl mSurfaceControl;
 
         public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal,
-                SurfaceControl surfaceControl) {
+                int displayId, SurfaceControl surfaceControl) {
             mDisplayManagerInternal = displayManagerInternal;
+            mDisplayId = displayId;
             mSurfaceControl = surfaceControl;
             mDisplayManagerInternal.registerDisplayTransactionListener(this);
         }
@@ -710,8 +714,7 @@
                     return;
                 }
 
-                DisplayInfo displayInfo =
-                        mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+                DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
                 switch (displayInfo.rotation) {
                     case Surface.ROTATION_0:
                         mSurfaceControl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 02be477..91afec7 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -95,13 +95,21 @@
         }
     }
 
+    static boolean shouldBlank(int state) {
+        return state == Display.STATE_OFF;
+    }
+
+    static boolean shouldUnblank(int state) {
+        return state == Display.STATE_ON || state == Display.STATE_DOZING;
+    }
+
     private final class LocalDisplayDevice extends DisplayDevice {
         private final int mBuiltInDisplayId;
         private final SurfaceControl.PhysicalDisplayInfo mPhys;
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
-        private boolean mBlanked;
+        private int mState = Display.STATE_UNKNOWN;
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
                 SurfaceControl.PhysicalDisplayInfo phys) {
@@ -134,6 +142,7 @@
                 mInfo.width = mPhys.width;
                 mInfo.height = mPhys.height;
                 mInfo.refreshRate = mPhys.refreshRate;
+                mInfo.state = mState;
 
                 // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
@@ -177,15 +186,16 @@
         }
 
         @Override
-        public void blankLocked() {
-            mBlanked = true;
-            SurfaceControl.blankDisplay(getDisplayTokenLocked());
-        }
-
-        @Override
-        public void unblankLocked() {
-            mBlanked = false;
-            SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+        public void requestDisplayStateLocked(int state) {
+            if (mState != state) {
+                if (shouldBlank(state) && !shouldBlank(mState)) {
+                    SurfaceControl.blankDisplay(getDisplayTokenLocked());
+                } else if (shouldUnblank(state) && !shouldUnblank(mState)) {
+                    SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+                }
+                mState = state;
+                updateDeviceInfoLocked();
+            }
         }
 
         @Override
@@ -193,7 +203,12 @@
             super.dumpLocked(pw);
             pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
             pw.println("mPhys=" + mPhys);
-            pw.println("mBlanked=" + mBlanked);
+            pw.println("mState=" + Display.stateToString(mState));
+        }
+
+        private void updateDeviceInfoLocked() {
+            mInfo = null;
+            sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index c26c438..d61a35b 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -114,6 +114,7 @@
                 mInfo.copyFrom(mOverrideDisplayInfo);
                 mInfo.layerStack = mBaseDisplayInfo.layerStack;
                 mInfo.name = mBaseDisplayInfo.name;
+                mInfo.state = mBaseDisplayInfo.state;
             } else {
                 mInfo.copyFrom(mBaseDisplayInfo);
             }
@@ -212,6 +213,7 @@
             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
             mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
+            mBaseDisplayInfo.state = deviceInfo.state;
             mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
             mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
             mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 007acf7..bfd8372c 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -194,12 +194,14 @@
         private final int mDensityDpi;
         private final boolean mSecure;
 
-        private Surface mSurface;
+        private int mState;
         private SurfaceTexture mSurfaceTexture;
+        private Surface mSurface;
         private DisplayDeviceInfo mInfo;
 
         public OverlayDisplayDevice(IBinder displayToken, String name,
-                int width, int height, float refreshRate, int densityDpi, boolean secure,
+                int width, int height, float refreshRate,
+                int densityDpi, boolean secure, int state,
                 SurfaceTexture surfaceTexture) {
             super(OverlayDisplayAdapter.this, displayToken);
             mName = name;
@@ -208,6 +210,7 @@
             mRefreshRate = refreshRate;
             mDensityDpi = densityDpi;
             mSecure = secure;
+            mState = state;
             mSurfaceTexture = surfaceTexture;
         }
 
@@ -230,6 +233,11 @@
             }
         }
 
+        public void setStateLocked(int state) {
+            mState = state;
+            mInfo = null;
+        }
+
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
@@ -247,6 +255,7 @@
                 }
                 mInfo.type = Display.TYPE_OVERLAY;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+                mInfo.state = mState;
             }
             return mInfo;
         }
@@ -288,11 +297,12 @@
 
         // Called on the UI thread.
         @Override
-        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
+        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, int state) {
             synchronized (getSyncRoot()) {
                 IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure);
                 mDevice = new OverlayDisplayDevice(displayToken, mName,
-                        mWidth, mHeight, refreshRate, mDensityDpi, mSecure, surfaceTexture);
+                        mWidth, mHeight, refreshRate, mDensityDpi, mSecure,
+                        state, surfaceTexture);
 
                 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
             }
@@ -309,6 +319,17 @@
             }
         }
 
+        // Called on the UI thread.
+        @Override
+        public void onStateChanged(int state) {
+            synchronized (getSyncRoot()) {
+                if (mDevice != null) {
+                    mDevice.setStateLocked(state);
+                    sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+                }
+            }
+        }
+
         public void dumpLocked(PrintWriter pw) {
             pw.println("  " + mName + ":");
             pw.println("    mWidth=" + mWidth);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index f1dd60a..06891f3 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -282,6 +282,7 @@
             if (displayId == mDefaultDisplay.getDisplayId()) {
                 if (updateDefaultDisplayInfo()) {
                     relayout();
+                    mListener.onStateChanged(mDefaultDisplayInfo.state);
                 } else {
                     dismiss();
                 }
@@ -301,7 +302,8 @@
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                 int width, int height) {
-            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
+            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate,
+                    mDefaultDisplayInfo.state);
         }
 
         @Override
@@ -370,7 +372,9 @@
      * Watches for significant changes in the overlay display window lifecycle.
      */
     public interface Listener {
-        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
+        public void onWindowCreated(SurfaceTexture surfaceTexture,
+                float refreshRate, int state);
         public void onWindowDestroyed();
+        public void onStateChanged(int state);
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
index 95ca0d2..a165f26 100644
--- a/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/VirtualDisplayAdapter.java
@@ -69,6 +69,13 @@
         return device;
     }
 
+    public void setVirtualDisplaySurfaceLocked(IBinder appToken, Surface surface) {
+        VirtualDisplayDevice device = mVirtualDisplayDevices.get(appToken);
+        if (device != null) {
+            device.setSurfaceLocked(surface);
+        }
+    }
+
     public DisplayDevice releaseVirtualDisplayLocked(IBinder appToken) {
         VirtualDisplayDevice device = mVirtualDisplayDevices.remove(appToken);
         if (device != null) {
@@ -144,6 +151,17 @@
             }
         }
 
+        public void setSurfaceLocked(Surface surface) {
+            if (mSurface != surface) {
+                if ((mSurface != null) != (surface != null)) {
+                    sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
+                }
+                sendTraversalRequestLocked();
+                mSurface = surface;
+                mInfo = null;
+            }
+        }
+
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
@@ -171,6 +189,7 @@
                 }
                 mInfo.type = Display.TYPE_VIRTUAL;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+                mInfo.state = mSurface != null ? Display.STATE_ON : Display.STATE_OFF;
                 mInfo.ownerUid = mOwnerUid;
                 mInfo.ownerPackageName = mOwnerPackageName;
             }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecController.java b/services/core/java/com/android/server/hdmi/HdmiCecController.java
new file mode 100644
index 0000000..5f07108
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiCecController.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+
+/**
+ * Manages HDMI-CEC command and behaviors. It converts user's command into CEC command
+ * and pass it to CEC HAL so that it sends message to other device. For incoming
+ * message it translates the message and delegates it to proper module.
+ *
+ * <p>It can be created only by {@link HdmiCecController#create}
+ *
+ * <p>Declared as package-private, accessed by {@link HdmiControlService} only.
+ */
+class HdmiCecController {
+    private static final String TAG = "HdmiCecController";
+
+    // Handler instance to process synchronous I/O (mainly send) message.
+    private Handler mIoHandler;
+
+    // Handler instance to process various messages coming from other CEC
+    // device or issued by internal state change.
+    private Handler mMessageHandler;
+
+    // Stores the pointer to the native implementation of the service that
+    // interacts with HAL.
+    private long mNativePtr;
+
+    // Private constructor.  Use HdmiCecController.create().
+    private HdmiCecController() {
+    }
+
+    /**
+     * A factory method to get {@link HdmiCecController}. If it fails to initialize
+     * inner device or has no device it will return {@code null}.
+     *
+     * <p>Declared as package-private, accessed by {@link HdmiControlService} only.
+     *
+     * @param ioLooper a Looper instance to handle IO (mainly send message) operation.
+     * @param messageHandler a message handler that processes a message coming from other
+     *                       CEC compatible device or callback of internal state change.
+     * @return {@link HdmiCecController} if device is initialized successfully. Otherwise,
+     *         returns {@code null}.
+     */
+    static HdmiCecController create(Looper ioLooper, Handler messageHandler) {
+        HdmiCecController handler = new HdmiCecController();
+        long nativePtr = nativeInit(handler);
+        if (nativePtr == 0L) {
+            handler = null;
+            return null;
+        }
+
+        handler.init(ioLooper, messageHandler, nativePtr);
+        return handler;
+    }
+
+    private void init(Looper ioLooper, Handler messageHandler, long nativePtr) {
+        mIoHandler = new Handler(ioLooper) {
+                @Override
+            public void handleMessage(Message msg) {
+                // TODO: Call native sendMessage.
+            }
+        };
+
+        mMessageHandler = messageHandler;
+        mNativePtr = nativePtr;
+    }
+
+    /**
+     * Called by native when an HDMI-CEC message arrived.
+     */
+    private void handleMessage(int srcAddress, int dstAddres, int opcode, byte[] params) {
+        // TODO: Translate message and delegate it to main message handler.
+    }
+
+    private static native long nativeInit(HdmiCecController handler);
+}
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
index 64b51c9..baae1d9 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevice.java
@@ -182,11 +182,49 @@
     }
 
     /**
+     * Send &lt;Active Source&gt; command. The default implementation does nothing. Should be
+     * overriden by subclass.
+     */
+    public void sendActiveSource(int physicalAddress) {
+        logWarning("<Active Source> not valid for the device type: " + mType
+                + " address:" + physicalAddress);
+    }
+
+    /**
+     * Send &lt;Inactive Source&gt; command. The default implementation does nothing. Should be
+     * overriden by subclass.
+     */
+    public void sendInactiveSource(int physicalAddress) {
+        logWarning("<Inactive Source> not valid for the device type: " + mType
+                + " address:" + physicalAddress);
+    }
+
+    /**
+     * Send &lt;Image View On&gt; command. The default implementation does nothing. Should be
+     * overriden by subclass.
+     */
+    public void sendImageViewOn() {
+        logWarning("<Image View On> not valid for the device type: " + mType);
+    }
+
+    /**
+     * Send &lt;Text View On&gt; command. The default implementation does nothing. Should be
+     * overriden by subclass.
+     */
+    public void sendTextViewOn() {
+        logWarning("<Text View On> not valid for the device type: " + mType);
+    }
+
+    /**
      * Check if the connected sink device is in powered-on state. The default implementation
      * simply returns false. Should be overriden by subclass to report the correct state.
      */
     public boolean isSinkDeviceOn() {
-        Log.w(TAG, "Not valid for the device type: " + mType);
+        logWarning("isSinkDeviceOn() not valid for the device type: " + mType);
         return false;
     }
+
+    private void logWarning(String msg) {
+        Log.w(TAG, msg);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
index 0310264..f8cf11d 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecDevicePlayback.java
@@ -66,14 +66,11 @@
         // 1) Response for the queried power status request arrives. Update the status.
         // 2) Broadcast or direct <Standby> command from TV, which is sent as TV itself is going
         //    into standby mode too.
-        // 3) Broadcast <Report Physical Address> command from TV, which is sent while it boots up.
         if (opcode == HdmiCec.MESSAGE_REPORT_POWER_STATUS) {
             mSinkDevicePowerStatus = params[0];
         } else if (srcAddress == HdmiCec.ADDR_TV) {
             if (opcode == HdmiCec.MESSAGE_STANDBY) {
                 mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_STANDBY;
-            } else if (opcode == HdmiCec.MESSAGE_REPORT_PHYSICAL_ADDRESS) {
-                mSinkDevicePowerStatus = HdmiCec.POWER_STATUS_ON;
             }
         }
         super.handleMessage(srcAddress, dstAddress, opcode, params);
@@ -95,4 +92,38 @@
     public boolean isSinkDeviceOn() {
         return mSinkDevicePowerStatus == HdmiCec.POWER_STATUS_ON;
     }
+
+    @Override
+    public void sendActiveSource(int physicalAddress) {
+        setIsActiveSource(true);
+        byte[] param = new byte[] {
+                (byte) ((physicalAddress >> 8) & 0xff),
+                (byte) (physicalAddress & 0xff)
+        };
+        getService().sendMessage(getType(), HdmiCec.ADDR_BROADCAST, HdmiCec.MESSAGE_ACTIVE_SOURCE,
+                param);
+    }
+
+    @Override
+    public void sendInactiveSource(int physicalAddress) {
+        setIsActiveSource(false);
+        byte[] param = new byte[] {
+                (byte) ((physicalAddress >> 8) & 0xff),
+                (byte) (physicalAddress & 0xff)
+        };
+        getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_INACTIVE_SOURCE,
+                param);
+    }
+
+    @Override
+    public void sendImageViewOn() {
+        getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_IMAGE_VIEW_ON,
+                HdmiCecService.EMPTY_PARAM);
+    }
+
+    @Override
+    public void sendTextViewOn() {
+        getService().sendMessage(getType(), HdmiCec.ADDR_TV, HdmiCec.MESSAGE_TEXT_VIEW_ON,
+                HdmiCecService.EMPTY_PARAM);
+    }
 }
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecService.java b/services/core/java/com/android/server/hdmi/HdmiCecService.java
index aa496c5..0a4c719 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecService.java
@@ -277,14 +277,7 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                device.setIsActiveSource(true);
-                int physicalAddress = nativeGetPhysicalAddress(mNativePtr);
-                byte[] param = new byte[] {
-                    (byte) ((physicalAddress >> 8) & 0xff),
-                    (byte) (physicalAddress & 0xff)
-                };
-                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
-                        HdmiCec.MESSAGE_ACTIVE_SOURCE, param);
+                device.sendActiveSource(nativeGetPhysicalAddress(mNativePtr));
             }
         }
 
@@ -293,9 +286,7 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                device.setIsActiveSource(false);
-                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_BROADCAST,
-                        HdmiCec.MESSAGE_INACTIVE_SOURCE, EMPTY_PARAM);
+                device.sendInactiveSource(nativeGetPhysicalAddress(mNativePtr));
             }
         }
 
@@ -304,8 +295,7 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
-                        HdmiCec.MESSAGE_IMAGE_VIEW_ON, EMPTY_PARAM);
+                device.sendImageViewOn();
             }
         }
 
@@ -314,8 +304,16 @@
             enforceAccessPermission();
             synchronized (mLock) {
                 HdmiCecDevice device = getLogicalDeviceLocked(b);
-                nativeSendMessage(mNativePtr, device.getType(), HdmiCec.ADDR_TV,
-                        HdmiCec.MESSAGE_TEXT_VIEW_ON, EMPTY_PARAM);
+                device.sendTextViewOn();
+            }
+        }
+
+        public void sendGiveDevicePowerStatus(IBinder b, int address) {
+            enforceAccessPermission();
+            synchronized (mLock) {
+                HdmiCecDevice device = getLogicalDeviceLocked(b);
+                nativeSendMessage(mNativePtr, device.getType(), address,
+                        HdmiCec.MESSAGE_GIVE_DEVICE_POWER_STATUS, EMPTY_PARAM);
             }
         }
 
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
new file mode 100644
index 0000000..56c5b49
--- /dev/null
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.hdmi;
+
+import android.annotation.Nullable;
+import android.content.Context;
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Message;
+import android.util.Slog;
+
+import com.android.server.SystemService;
+
+/**
+ * Provides a service for sending and processing HDMI control messages,
+ * HDMI-CEC and MHL control command, and providing the information on both standard.
+ */
+public final class HdmiControlService extends SystemService {
+    private static final String TAG = "HdmiControlService";
+
+    // A thread to handle synchronous IO of CEC and MHL control service.
+    // Since all of CEC and MHL HAL interfaces processed in short time (< 200ms)
+    // and sparse call it shares a thread to handle IO operations.
+    private final HandlerThread mIoThread = new HandlerThread("Hdmi Control Io Thread");
+
+    // Main handler class to handle incoming message from each controller.
+    private final Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            // TODO: Add handler for each message type.
+        }
+    };
+
+    @Nullable
+    private HdmiCecController mCecController;
+
+    @Nullable
+    private HdmiMhlController mMhlController;
+
+    public HdmiControlService(Context context) {
+        super(context);
+    }
+
+    @Override
+    public void onStart() {
+        mCecController = HdmiCecController.create(mIoThread.getLooper(), mHandler);
+        if (mCecController == null) {
+            Slog.i(TAG, "Device does not support HDMI-CEC.");
+        }
+
+        mMhlController = HdmiMhlController.create(mIoThread.getLooper(), mHandler);
+        if (mMhlController == null) {
+            Slog.i(TAG, "Device does not support MHL-control.");
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index 316bd57..54cb035 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -185,6 +185,7 @@
             InputChannel fromChannel, InputChannel toChannel);
     private static native void nativeSetPointerSpeed(long ptr, int speed);
     private static native void nativeSetShowTouches(long ptr, boolean enabled);
+    private static native void nativeSetInteractive(long ptr, boolean interactive);
     private static native void nativeReloadCalibration(long ptr);
     private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
             int repeat, int token);
@@ -1404,14 +1405,13 @@
     }
 
     // Native callback.
-    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
-        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(
-                event, policyFlags, isScreenOn);
+    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
     }
 
     // Native callback.
-    private int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
-        return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(
+    private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+        return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
                 whenNanos, policyFlags);
     }
 
@@ -1570,9 +1570,9 @@
         public long notifyANR(InputApplicationHandle inputApplicationHandle,
                 InputWindowHandle inputWindowHandle, String reason);
 
-        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
-        public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
+        public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
 
         public long interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags);
@@ -1740,5 +1740,10 @@
         public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
             return injectInputEventInternal(event, displayId, mode);
         }
+
+        @Override
+        public void setInteractive(boolean interactive) {
+            nativeSetInteractive(mPtr, interactive);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/location/FlpHardwareProvider.java b/services/core/java/com/android/server/location/FlpHardwareProvider.java
index fab84a8..09f1c56 100644
--- a/services/core/java/com/android/server/location/FlpHardwareProvider.java
+++ b/services/core/java/com/android/server/location/FlpHardwareProvider.java
@@ -60,11 +60,16 @@
     private static final int FLP_RESULT_ID_UNKNOWN = -5;
     private static final int FLP_RESULT_INVALID_GEOFENCE_TRANSITION = -6;
 
+    // FlpHal monitor status codes, they must be equal to the ones in fused_location.h
+    private static final int FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE = 1<<0;
+    private static final int FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE = 1<<1;
+
     public static FlpHardwareProvider getInstance(Context context) {
         if (sSingletonInstance == null) {
             sSingletonInstance = new FlpHardwareProvider(context);
         }
 
+        nativeInit();
         return sSingletonInstance;
     }
 
@@ -92,6 +97,7 @@
     }
 
     public static boolean isSupported() {
+        nativeInit();
         return nativeIsSupported();
     }
 
@@ -141,6 +147,8 @@
             int transition,
             long timestamp,
             int sourcesUsed) {
+        // the transition Id does not require translation because the values in fused_location.h
+        // and GeofenceHardware are in sync
         getGeofenceHardwareSink().reportGeofenceTransition(
                 geofenceId,
                 updateLocationInformation(location),
@@ -157,9 +165,23 @@
             updatedLocation = updateLocationInformation(location);
         }
 
+        int monitorStatus;
+        switch (status) {
+            case FLP_GEOFENCE_MONITOR_STATUS_UNAVAILABLE:
+                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
+                break;
+            case FLP_GEOFENCE_MONITOR_STATUS_AVAILABLE:
+                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_AVAILABLE;
+                break;
+            default:
+                Log.e(TAG, "Invalid FlpHal Geofence monitor status: " + status);
+                monitorStatus = GeofenceHardware.MONITOR_CURRENTLY_UNAVAILABLE;
+                break;
+        }
+
         getGeofenceHardwareSink().reportGeofenceMonitorStatus(
                 GeofenceHardware.MONITORING_TYPE_FUSED_HARDWARE,
-                status,
+                monitorStatus,
                 updatedLocation,
                 source);
     }
@@ -196,9 +218,9 @@
     // Core members
     private static native void nativeClassInit();
     private static native boolean nativeIsSupported();
+    private static native void nativeInit();
 
     // FlpLocationInterface members
-    private native void nativeInit();
     private native int nativeGetBatchSize();
     private native void nativeStartBatching(int requestId, FusedBatchOptions options);
     private native void nativeUpdateBatchingOptions(int requestId, FusedBatchOptions optionsObject);
@@ -238,12 +260,10 @@
     public static final String GEOFENCING = "Geofencing";
 
     public IFusedLocationHardware getLocationHardware() {
-        nativeInit();
         return mLocationHardware;
     }
 
     public IFusedGeofenceHardware getGeofenceHardware() {
-        nativeInit();
         return mGeofenceHardwareService;
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderProxy.java b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
new file mode 100644
index 0000000..c4e2058
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaRouteProviderProxy.java
@@ -0,0 +1,394 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.media;
+
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.media.routeprovider.IRouteConnection;
+import android.media.routeprovider.IRouteProvider;
+import android.media.routeprovider.IRouteProviderCallback;
+import android.media.routeprovider.RouteProviderService;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.RouteEvent;
+import android.media.session.RouteInfo;
+import android.media.session.Session;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.os.UserHandle;
+import android.util.Log;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * System representation and interface to a MediaRouteProvider. This class is
+ * not thread safe so all calls should be made on the main thread.
+ */
+public class MediaRouteProviderProxy {
+    private static final String TAG = "MRPProxy";
+    private static final boolean DEBUG = true;
+
+    private static final int MAX_RETRIES = 3;
+
+    private final Object mLock = new Object();
+    private final Context mContext;
+    private final String mId;
+    private final ComponentName mComponentName;
+    private final int mUserId;
+    // Interfaces declared in the manifest
+    private final ArrayList<String> mInterfaces = new ArrayList<String>();
+    private final ArrayList<RouteConnectionRecord> mConnections = new ArrayList<RouteConnectionRecord>();
+    private final Handler mHandler = new Handler();
+
+    private Intent mBindIntent;
+    private IRouteProvider mBinder;
+    private boolean mRunning;
+    private boolean mInterested;
+    private boolean mBound;
+    private int mRetryCount;
+
+    private RoutesListener mRouteListener;
+
+    public MediaRouteProviderProxy(Context context, String id, ComponentName component, int uid,
+            ArrayList<String> interfaces) {
+        mContext = context;
+        mId = id;
+        mComponentName = component;
+        mUserId = uid;
+        if (interfaces != null) {
+            mInterfaces.addAll(interfaces);
+        }
+        mBindIntent = new Intent(RouteProviderService.SERVICE_INTERFACE);
+        mBindIntent.setComponent(mComponentName);
+    }
+
+    /**
+     * Send any cleanup messages and unbind from the media route provider
+     */
+    public void stop() {
+        if (mRunning) {
+            mRunning = false;
+            mRetryCount = 0;
+            updateBinding();
+        }
+    }
+
+    /**
+     * Bind to the media route provider and perform any setup needed
+     */
+    public void start() {
+        if (!mRunning) {
+            mRunning = true;
+            updateBinding();
+        }
+    }
+
+    /**
+     * Set whether or not this provider is currently interesting to the system.
+     * In the future this may take a list of interfaces instead.
+     *
+     * @param interested True if we want to connect to this provider
+     */
+    public void setInterested(boolean interested) {
+        mInterested = interested;
+        updateBinding();
+    }
+
+    /**
+     * Set a listener to get route updates on.
+     *
+     * @param listener The listener to receive updates on.
+     */
+    public void setRoutesListener(RoutesListener listener) {
+        mRouteListener = listener;
+    }
+
+    /**
+     * Send a request to the Provider to get all the routes that the session can
+     * use.
+     *
+     * @param record The session to get routes for.
+     * @param requestId An id to identify this request.
+     */
+    public void getRoutes(MediaSessionRecord record, final int requestId) {
+        // TODO change routes to have a system global id and maintain a mapping
+        // to the original route
+        if (mBinder == null) {
+            Log.wtf(TAG, "Attempted to call getRoutes without a binder connection");
+            return;
+        }
+        List<RouteRequest> requests = record.getRouteRequests();
+        final String sessionId = record.getSessionInfo().getId();
+        try {
+            mBinder.getAvailableRoutes(requests, new ResultReceiver(mHandler) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle resultData) {
+                    if (resultCode != RouteProviderService.RESULT_SUCCESS) {
+                        // ignore failures, just means no routes were generated
+                        return;
+                    }
+                    ArrayList<RouteInfo> routes
+                            = resultData.getParcelableArrayList(RouteProviderService.KEY_ROUTES);
+                    ArrayList<RouteInfo> sysRoutes = new ArrayList<RouteInfo>();
+                    for (int i = 0; i < routes.size(); i++) {
+                        RouteInfo route = routes.get(i);
+                        RouteInfo.Builder bob = new RouteInfo.Builder(route);
+                        bob.setProviderId(mId);
+                        sysRoutes.add(bob.build());
+                    }
+                    if (mRouteListener != null) {
+                        mRouteListener.onRoutesUpdated(sessionId, sysRoutes, requestId);
+                    }
+                }
+            });
+        } catch (RemoteException e) {
+            Log.d(TAG, "Error in getRoutes", e);
+        }
+    }
+
+    /**
+     * Try connecting again if we've been disconnected.
+     */
+    public void rebindIfDisconnected() {
+        if (mBinder == null && shouldBind()) {
+            unbind();
+            bind();
+        }
+    }
+
+    /**
+     * Send a request to connect to a route.
+     *
+     * @param session The session that is trying to connect.
+     * @param route The route it is connecting to.
+     * @param request The request with the connection parameters.
+     * @return true if the request was sent, false otherwise.
+     */
+    public boolean connectToRoute(MediaSessionRecord session, final RouteInfo route,
+            final RouteRequest request) {
+        final String sessionId = session.getSessionInfo().getId();
+        try {
+            mBinder.connect(route, request, new ResultReceiver(mHandler) {
+                @Override
+                protected void onReceiveResult(int resultCode, Bundle resultData) {
+                    if (resultCode != RouteProviderService.RESULT_SUCCESS) {
+                        // TODO handle connection failure
+                        return;
+                    }
+                    IBinder binder = resultData.getBinder(RouteProviderService.KEY_CONNECTION);
+                    IRouteConnection connection = null;
+                    if (binder != null) {
+                        connection = IRouteConnection.Stub.asInterface(binder);
+                    }
+
+                    if (connection != null) {
+                        RouteConnectionRecord record = new RouteConnectionRecord(
+                                connection, mComponentName.getPackageName(), mUserId);
+                        mConnections.add(record);
+                        if (mRouteListener != null) {
+                            mRouteListener.onRouteConnected(sessionId, route, request, record);
+                        }
+                    }
+                }
+            });
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error connecting to route.", e);
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Check if this is the provider you're looking for.
+     */
+    public boolean hasComponentName(String packageName, String className) {
+        return mComponentName.getPackageName().equals(packageName)
+                && mComponentName.getClassName().equals(className);
+    }
+
+    /**
+     * Get the unique id for this provider.
+     *
+     * @return The provider's id.
+     */
+    public String getId() {
+        return mId;
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + mId + " " + this);
+        String indent = prefix + "  ";
+
+        pw.println(indent + "component=" + mComponentName.toString());
+        pw.println(indent + "user id=" + mUserId);
+        pw.println(indent + "interfaces=" + mInterfaces.toString());
+        pw.println(indent + "connections=" + mConnections.toString());
+        pw.println(indent + "running=" + mRunning);
+        pw.println(indent + "interested=" + mInterested);
+        pw.println(indent + "bound=" + mBound);
+    }
+
+    private void updateBinding() {
+        if (shouldBind()) {
+            bind();
+        } else {
+            unbind();
+        }
+    }
+
+    private boolean shouldBind() {
+        return mRunning && mInterested;
+    }
+
+    private void bind() {
+        if (!mBound) {
+            if (DEBUG) {
+                Slog.d(TAG, this + ": Binding");
+            }
+
+            try {
+                mBound = mContext.bindServiceAsUser(mBindIntent, mServiceConn,
+                        Context.BIND_AUTO_CREATE, new UserHandle(mUserId));
+                if (!mBound && DEBUG) {
+                    Slog.d(TAG, this + ": Bind failed");
+                }
+            } catch (SecurityException ex) {
+                if (DEBUG) {
+                    Slog.d(TAG, this + ": Bind failed", ex);
+                }
+            }
+        }
+    }
+
+    private void unbind() {
+        if (mBound) {
+            if (DEBUG) {
+                Slog.d(TAG, this + ": Unbinding");
+            }
+
+            mBound = false;
+            mContext.unbindService(mServiceConn);
+        }
+    }
+
+    private RouteConnectionRecord getConnectionLocked(IBinder binder) {
+        for (int i = mConnections.size() - 1; i >= 0; i--) {
+            RouteConnectionRecord record = mConnections.get(i);
+            if (record.isConnection(binder)) {
+                return record;
+            }
+        }
+        return null;
+    }
+
+    private ServiceConnection mServiceConn = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            mBinder = IRouteProvider.Stub.asInterface(service);
+            if (DEBUG) {
+                Slog.d(TAG, "Connected to route provider");
+            }
+            try {
+                mBinder.registerCallback(mCbStub);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Error registering callback on route provider. Retry count: "
+                        + mRetryCount, e);
+                if (mRetryCount < MAX_RETRIES) {
+                    mRetryCount++;
+                    rebindIfDisconnected();
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mBinder = null;
+            if (DEBUG) {
+                Slog.d(TAG, "Disconnected from route provider");
+            }
+        }
+
+    };
+
+    private IRouteProviderCallback.Stub mCbStub = new IRouteProviderCallback.Stub() {
+        @Override
+        public void onConnectionStateChanged(IRouteConnection connection, int state)
+                throws RemoteException {
+            // TODO
+        }
+
+        @Override
+        public void onRouteEvent(RouteEvent event) throws RemoteException {
+            synchronized (mLock) {
+                RouteConnectionRecord record = getConnectionLocked(event.getConnection());
+                Log.d(TAG, "Received route event for record " + record);
+                if (record != null) {
+                    record.sendEvent(event);
+                }
+            }
+        }
+
+        @Override
+        public void onConnectionTerminated(IRouteConnection connection) throws RemoteException {
+            synchronized (mLock) {
+                RouteConnectionRecord record = getConnectionLocked(connection.asBinder());
+                if (record != null) {
+                    record.disconnect();
+                    mConnections.remove(record);
+                }
+            }
+        }
+
+        @Override
+        public void onRoutesChanged() throws RemoteException {
+            // TODO
+        }
+    };
+
+    /**
+     * Listener for receiving responses to route requests on the provider.
+     */
+    public interface RoutesListener {
+        /**
+         * Called when routes have been returned from a request to getRoutes.
+         *
+         * @param record The session that the routes were requested for.
+         * @param routes The matching routes returned by the provider.
+         * @param reqId The request id this is responding to.
+         */
+        public void onRoutesUpdated(String sessionId, ArrayList<RouteInfo> routes,
+                int reqId);
+
+        /**
+         * Called when a route has successfully connected.
+         *
+         * @param session The session that was connected.
+         * @param route The route it connected to.
+         * @param options The options that were used for the connection.
+         * @param connection The connection instance that was created.
+         */
+        public void onRouteConnected(String sessionId, RouteInfo route,
+                RouteRequest options, RouteConnectionRecord connection);
+    }
+}
diff --git a/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java b/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java
new file mode 100644
index 0000000..cf1d95ab
--- /dev/null
+++ b/services/core/java/com/android/server/media/MediaRouteProviderWatcher.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.media;
+
+import android.Manifest;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.media.routeprovider.RouteProviderService;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.text.TextUtils;
+import android.util.Slog;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.UUID;
+
+/**
+ * Watches for media route provider services to be installed. Adds a provider to
+ * the media session service for each registered service. For now just run all
+ * providers. In the future define a policy for when to run providers.
+ */
+public class MediaRouteProviderWatcher {
+    private static final String TAG = "MRPWatcher";
+    private static final boolean DEBUG = true; // Log.isLoggable(TAG,
+                                               // Log.DEBUG);
+
+    private final Context mContext;
+    private final Callback mCallback;
+    private final Handler mHandler;
+    private final int mUserId;
+    private final PackageManager mPackageManager;
+
+    private final ArrayList<MediaRouteProviderProxy> mProviders =
+            new ArrayList<MediaRouteProviderProxy>();
+    private boolean mRunning;
+
+    public MediaRouteProviderWatcher(Context context, Callback callback, Handler handler,
+            int userId) {
+        mContext = context;
+        mCallback = callback;
+        mHandler = handler;
+        mUserId = userId;
+        mPackageManager = context.getPackageManager();
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + " mUserId=" + mUserId);
+        pw.println(prefix + " mRunning=" + mRunning);
+        pw.println(prefix + " mProviders.size()=" + mProviders.size());
+    }
+
+    public void start() {
+        if (!mRunning) {
+            mRunning = true;
+
+            IntentFilter filter = new IntentFilter();
+            filter.addAction(Intent.ACTION_PACKAGE_ADDED);
+            filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
+            filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
+            filter.addAction(Intent.ACTION_PACKAGE_REPLACED);
+            filter.addAction(Intent.ACTION_PACKAGE_RESTARTED);
+            filter.addDataScheme("package");
+            mContext.registerReceiverAsUser(mScanPackagesReceiver,
+                    new UserHandle(mUserId), filter, null, mHandler);
+
+            // Scan packages.
+            // Also has the side-effect of restarting providers if needed.
+            mHandler.post(mScanPackagesRunnable);
+        }
+    }
+
+    public void stop() {
+        if (mRunning) {
+            mRunning = false;
+
+            mContext.unregisterReceiver(mScanPackagesReceiver);
+            mHandler.removeCallbacks(mScanPackagesRunnable);
+
+            // Stop all providers.
+            for (int i = mProviders.size() - 1; i >= 0; i--) {
+                mProviders.get(i).stop();
+            }
+        }
+    }
+
+    public ArrayList<MediaRouteProviderProxy> getProviders() {
+        return mProviders;
+    }
+
+    public MediaRouteProviderProxy getProvider(String id) {
+        int providerIndex = findProvider(id);
+        if (providerIndex != -1) {
+            return mProviders.get(providerIndex);
+        }
+        return null;
+    }
+
+    private void scanPackages() {
+        if (!mRunning) {
+            return;
+        }
+
+        // Add providers for all new services.
+        // Reorder the list so that providers left at the end will be the ones
+        // to remove.
+        int targetIndex = 0;
+        Intent intent = new Intent(RouteProviderService.SERVICE_INTERFACE);
+        for (ResolveInfo resolveInfo : mPackageManager.queryIntentServicesAsUser(
+                intent, 0, mUserId)) {
+            ServiceInfo serviceInfo = resolveInfo.serviceInfo;
+            if (DEBUG) {
+                Slog.d(TAG, "Checking service " + (serviceInfo == null ? null : serviceInfo.name));
+            }
+            if (serviceInfo != null && verifyServiceTrusted(serviceInfo)) {
+                int sourceIndex = findProvider(serviceInfo.packageName, serviceInfo.name);
+                if (sourceIndex < 0) {
+                    // TODO get declared interfaces from manifest
+                    if (DEBUG) {
+                        Slog.d(TAG, "Creating new provider proxy for service");
+                    }
+                    MediaRouteProviderProxy provider =
+                            new MediaRouteProviderProxy(mContext, UUID.randomUUID().toString(),
+                                    new ComponentName(serviceInfo.packageName, serviceInfo.name),
+                                    mUserId, null);
+                    provider.start();
+                    mProviders.add(targetIndex++, provider);
+                    mCallback.addProvider(provider);
+                } else if (sourceIndex >= targetIndex) {
+                    MediaRouteProviderProxy provider = mProviders.get(sourceIndex);
+                    provider.start(); // restart the provider if needed
+                    provider.rebindIfDisconnected();
+                    Collections.swap(mProviders, sourceIndex, targetIndex++);
+                }
+            }
+        }
+
+        // Remove providers for missing services.
+        if (targetIndex < mProviders.size()) {
+            for (int i = mProviders.size() - 1; i >= targetIndex; i--) {
+                MediaRouteProviderProxy provider = mProviders.get(i);
+                mCallback.removeProvider(provider);
+                mProviders.remove(provider);
+                provider.stop();
+            }
+        }
+    }
+
+    private boolean verifyServiceTrusted(ServiceInfo serviceInfo) {
+        if (serviceInfo.permission == null || !serviceInfo.permission.equals(
+                Manifest.permission.BIND_ROUTE_PROVIDER)) {
+            // If the service does not require this permission then any app
+            // could potentially bind to it and mess with their routes. So we
+            // only want to trust providers that require the
+            // correct permissions.
+            Slog.w(TAG, "Ignoring route provider service because it did not "
+                    + "require the BIND_ROUTE_PROVIDER permission in its manifest: "
+                    + serviceInfo.packageName + "/" + serviceInfo.name);
+            return false;
+        }
+        // Looks good.
+        return true;
+    }
+
+    private int findProvider(String id) {
+        int count = mProviders.size();
+        for (int i = 0; i < count; i++) {
+            MediaRouteProviderProxy provider = mProviders.get(i);
+            if (TextUtils.equals(id, provider.getId())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private int findProvider(String packageName, String className) {
+        int count = mProviders.size();
+        for (int i = 0; i < count; i++) {
+            MediaRouteProviderProxy provider = mProviders.get(i);
+            if (provider.hasComponentName(packageName, className)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private final BroadcastReceiver mScanPackagesReceiver = new BroadcastReceiver() {
+            @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) {
+                Slog.d(TAG, "Received package manager broadcast: " + intent);
+            }
+            scanPackages();
+        }
+    };
+
+    private final Runnable mScanPackagesRunnable = new Runnable() {
+            @Override
+        public void run() {
+            scanPackages();
+        }
+    };
+
+    public interface Callback {
+        void addProvider(MediaRouteProviderProxy provider);
+
+        void removeProvider(MediaRouteProviderProxy provider);
+    }
+}
diff --git a/services/core/java/com/android/server/media/MediaSessionRecord.java b/services/core/java/com/android/server/media/MediaSessionRecord.java
index 1ff925c..ab2a723 100644
--- a/services/core/java/com/android/server/media/MediaSessionRecord.java
+++ b/services/core/java/com/android/server/media/MediaSessionRecord.java
@@ -17,11 +17,20 @@
 package com.android.server.media;
 
 import android.content.Intent;
-import android.media.session.IMediaController;
-import android.media.session.IMediaControllerCallback;
-import android.media.session.IMediaSession;
-import android.media.session.IMediaSessionCallback;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.ISessionController;
+import android.media.session.ISessionControllerCallback;
+import android.media.session.ISession;
+import android.media.session.ISessionCallback;
+import android.media.session.SessionController;
 import android.media.session.MediaMetadata;
+import android.media.session.RouteCommand;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
+import android.media.session.RouteEvent;
+import android.media.session.Session;
+import android.media.session.SessionInfo;
+import android.media.session.RouteInterface;
 import android.media.session.PlaybackState;
 import android.media.Rating;
 import android.os.Bundle;
@@ -31,37 +40,46 @@
 import android.os.Message;
 import android.os.RemoteException;
 import android.os.ResultReceiver;
+import android.os.SystemClock;
+import android.text.TextUtils;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.view.KeyEvent;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.UUID;
 
 /**
  * This is the system implementation of a Session. Apps will interact with the
  * MediaSession wrapper class instead.
  */
 public class MediaSessionRecord implements IBinder.DeathRecipient {
-    private static final String TAG = "MediaSessionImpl";
+    private static final String TAG = "MediaSessionRecord";
 
     private final MessageHandler mHandler;
 
     private final int mPid;
-    private final String mPackageName;
+    private final SessionInfo mSessionInfo;
     private final String mTag;
     private final ControllerStub mController;
     private final SessionStub mSession;
     private final SessionCb mSessionCb;
     private final MediaSessionService mService;
 
-    private final Object mControllerLock = new Object();
-    private final ArrayList<IMediaControllerCallback> mControllerCallbacks =
-            new ArrayList<IMediaControllerCallback>();
-    private final ArrayList<String> mInterfaces = new ArrayList<String>();
+    private final Object mLock = new Object();
+    private final ArrayList<ISessionControllerCallback> mControllerCallbacks =
+            new ArrayList<ISessionControllerCallback>();
+    private final ArrayList<RouteRequest> mRequests = new ArrayList<RouteRequest>();
 
     private boolean mTransportPerformerEnabled = false;
-    private Bundle mRoute;
+    private RouteInfo mRoute;
+    private RouteOptions mRequest;
+    private RouteConnectionRecord mConnection;
+    // TODO define a RouteState class with relevant info
+    private int mRouteState;
 
     // TransportPerformer fields
 
@@ -72,10 +90,10 @@
 
     private boolean mIsPublished = false;
 
-    public MediaSessionRecord(int pid, String packageName, IMediaSessionCallback cb, String tag,
+    public MediaSessionRecord(int pid, String packageName, ISessionCallback cb, String tag,
             MediaSessionService service, Handler handler) {
         mPid = pid;
-        mPackageName = packageName;
+        mSessionInfo = new SessionInfo(UUID.randomUUID().toString(), packageName);
         mTag = tag;
         mController = new ControllerStub();
         mSession = new SessionStub();
@@ -84,21 +102,151 @@
         mHandler = new MessageHandler(handler.getLooper());
     }
 
-    public IMediaSession getSessionBinder() {
+    /**
+     * Get the binder for the {@link Session}.
+     *
+     * @return The session binder apps talk to.
+     */
+    public ISession getSessionBinder() {
         return mSession;
     }
 
-    public IMediaController getControllerBinder() {
+    /**
+     * Get the binder for the {@link SessionController}.
+     *
+     * @return The controller binder apps talk to.
+     */
+    public ISessionController getControllerBinder() {
         return mController;
     }
 
+    /**
+     * Get the set of route requests this session is interested in.
+     *
+     * @return The list of RouteRequests
+     */
+    public List<RouteRequest> getRouteRequests() {
+        return mRequests;
+    }
+
+    /**
+     * Get the route this session is currently on.
+     *
+     * @return The route the session is on.
+     */
+    public RouteInfo getRoute() {
+        return mRoute;
+    }
+
+    /**
+     * Get the info for this session.
+     *
+     * @return Info that identifies this session.
+     */
+    public SessionInfo getSessionInfo() {
+        return mSessionInfo;
+    }
+
+    /**
+     * Set the selected route. This does not connect to the route, just notifies
+     * the app that a new route has been selected.
+     *
+     * @param route The route that was selected.
+     */
+    public void selectRoute(RouteInfo route) {
+        synchronized (mLock) {
+            if (route != mRoute) {
+                if (mConnection != null) {
+                    mConnection.disconnect();
+                    mConnection = null;
+                }
+            }
+            mRoute = route;
+        }
+        mSessionCb.sendRouteChange(route);
+    }
+
+    /**
+     * Update the state of the route this session is using and notify the
+     * session.
+     *
+     * @param state The new state of the route.
+     */
+    public void setRouteState(int state) {
+        mSessionCb.sendRouteStateChange(state);
+    }
+
+    /**
+     * Send an event to this session from the route it is using.
+     *
+     * @param event The event to send.
+     */
+    public void sendRouteEvent(RouteEvent event) {
+        mSessionCb.sendRouteEvent(event);
+    }
+
+    /**
+     * Set the connection to use for the selected route and notify the app it is
+     * now connected.
+     *
+     * @param route The route the connection is to.
+     * @param request The request that was used to connect.
+     * @param connection The connection to the route.
+     * @return True if this connection is still valid, false if it is stale.
+     */
+    public boolean setRouteConnected(RouteInfo route, RouteOptions request,
+            RouteConnectionRecord connection) {
+        synchronized (mLock) {
+            if (mRoute == null || !TextUtils.equals(route.getId(), mRoute.getId())) {
+                Log.w(TAG, "setRouteConnected: connected route is stale");
+                // TODO figure out disconnection path
+                return false;
+            }
+            if (request != mRequest) {
+                Log.w(TAG, "setRouteConnected: connection request is stale");
+                // TODO figure out disconnection path
+                return false;
+            }
+            mConnection = connection;
+            mConnection.setListener(mConnectionListener);
+            mSessionCb.sendRouteConnected();
+        }
+        return true;
+    }
+
+    /**
+     * Check if this session has been published by the app yet.
+     *
+     * @return True if it has been published, false otherwise.
+     */
+    public boolean isPublished() {
+        return mIsPublished;
+    }
+
     @Override
     public void binderDied() {
         mService.sessionDied(this);
     }
 
-    public boolean isPublished() {
-        return mIsPublished;
+    public void dump(PrintWriter pw, String prefix) {
+        pw.println(prefix + mTag + " " + this);
+
+        final String indent = prefix + "  ";
+        pw.println(indent + "pid=" + mPid);
+        pw.println(indent + "info=" + mSessionInfo.toString());
+        pw.println(indent + "published=" + mIsPublished);
+        pw.println(indent + "transport controls enabled=" + mTransportPerformerEnabled);
+        pw.println(indent + "rating type=" + mRatingType);
+        pw.println(indent + "controllers: " + mControllerCallbacks.size());
+        pw.println(indent + "route requests {");
+        int size = mRequests.size();
+        for (int i = 0; i < size; i++) {
+            pw.println(indent + "  " + mRequests.get(i).toString());
+        }
+        pw.println(indent + "}");
+        pw.println(indent + "route=" + (mRoute == null ? null : mRoute.toString()));
+        pw.println(indent + "connection=" + (mConnection == null ? null : mConnection.toString()));
+        pw.println(indent + "params=" + (mRequest == null ? null : mRequest.toString()));
     }
 
     private void onDestroy() {
@@ -106,9 +254,9 @@
     }
 
     private void pushPlaybackStateUpdate() {
-        synchronized (mControllerLock) {
+        synchronized (mLock) {
             for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
-                IMediaControllerCallback cb = mControllerCallbacks.get(i);
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
                 try {
                     cb.onPlaybackStateChanged(mPlaybackState);
                 } catch (RemoteException e) {
@@ -120,9 +268,9 @@
     }
 
     private void pushMetadataUpdate() {
-        synchronized (mControllerLock) {
+        synchronized (mLock) {
             for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
-                IMediaControllerCallback cb = mControllerCallbacks.get(i);
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
                 try {
                     cb.onMetadataChanged(mMetadata);
                 } catch (RemoteException e) {
@@ -134,9 +282,9 @@
     }
 
     private void pushRouteUpdate() {
-        synchronized (mControllerLock) {
+        synchronized (mLock) {
             for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
-                IMediaControllerCallback cb = mControllerCallbacks.get(i);
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
                 try {
                     cb.onRouteChanged(mRoute);
                 } catch (RemoteException e) {
@@ -148,21 +296,78 @@
     }
 
     private void pushEvent(String event, Bundle data) {
-        synchronized (mControllerLock) {
+        synchronized (mLock) {
             for (int i = mControllerCallbacks.size() - 1; i >= 0; i--) {
-                IMediaControllerCallback cb = mControllerCallbacks.get(i);
+                ISessionControllerCallback cb = mControllerCallbacks.get(i);
                 try {
                     cb.onEvent(event, data);
                 } catch (RemoteException e) {
-                    Log.w(TAG, "Removing dead callback in pushRouteUpdate.", e);
-                    mControllerCallbacks.remove(i);
+                    Log.w(TAG, "Error with callback in pushEvent.", e);
                 }
             }
         }
     }
 
-    private final class SessionStub extends IMediaSession.Stub {
+    private void pushRouteCommand(RouteCommand command, ResultReceiver cb) {
+        synchronized (mLock) {
+            if (mRoute == null || !TextUtils.equals(command.getRouteInfo(), mRoute.getId())) {
+                if (cb != null) {
+                    cb.send(RouteInterface.RESULT_ROUTE_IS_STALE, null);
+                    return;
+                }
+            }
+            if (mConnection != null) {
+                mConnection.sendCommand(command, cb);
+            } else if (cb != null) {
+                cb.send(RouteInterface.RESULT_NOT_CONNECTED, null);
+            }
+        }
+    }
 
+    private PlaybackState getStateWithUpdatedPosition() {
+        PlaybackState state = mPlaybackState;
+        long duration = -1;
+        if (mMetadata != null && mMetadata.containsKey(MediaMetadata.METADATA_KEY_DURATION)) {
+            duration = mMetadata.getLong(MediaMetadata.METADATA_KEY_DURATION);
+        }
+        PlaybackState result = null;
+        if (state != null) {
+            if (state.getState() == PlaybackState.PLAYSTATE_PLAYING
+                    || state.getState() == PlaybackState.PLAYSTATE_FAST_FORWARDING
+                    || state.getState() == PlaybackState.PLAYSTATE_REWINDING) {
+                long updateTime = state.getLastPositionUpdateTime();
+                if (updateTime > 0) {
+                    long position = (long) (state.getRate()
+                            * (SystemClock.elapsedRealtime() - updateTime)) + state.getPosition();
+                    if (duration >= 0 && position > duration) {
+                        position = duration;
+                    } else if (position < 0) {
+                        position = 0;
+                    }
+                    result = new PlaybackState(state);
+                    result.setState(state.getState(), position, state.getRate());
+                }
+            }
+        }
+        return result == null ? state : result;
+    }
+
+    private final RouteConnectionRecord.Listener mConnectionListener
+            = new RouteConnectionRecord.Listener() {
+        @Override
+        public void onEvent(RouteEvent event) {
+            RouteEvent eventForSession = new RouteEvent(null, event.getIface(),
+                    event.getEvent(), event.getExtras());
+            mSessionCb.sendRouteEvent(eventForSession);
+        }
+
+        @Override
+        public void disconnect() {
+            // TODO
+        }
+    };
+
+    private final class SessionStub extends ISession.Stub {
         @Override
         public void destroy() {
             onDestroy();
@@ -174,21 +379,11 @@
         }
 
         @Override
-        public IMediaController getMediaController() {
+        public ISessionController getController() {
             return mController;
         }
 
         @Override
-        public void setRouteState(Bundle routeState) {
-        }
-
-        @Override
-        public void setRoute(Bundle mediaRouteDescriptor) {
-            mRoute = mediaRouteDescriptor;
-            mHandler.post(MessageHandler.MSG_UPDATE_ROUTE);
-        }
-
-        @Override
         public void publish() {
             mIsPublished = true; // TODO push update to service
         }
@@ -198,11 +393,6 @@
         }
 
         @Override
-        public List<String> getSupportedInterfaces() {
-            return mInterfaces;
-        }
-
-        @Override
         public void setMetadata(MediaMetadata metadata) {
             mMetadata = metadata;
             mHandler.post(MessageHandler.MSG_UPDATE_METADATA);
@@ -218,12 +408,44 @@
         public void setRatingType(int type) {
             mRatingType = type;
         }
+
+        @Override
+        public void sendRouteCommand(RouteCommand command, ResultReceiver cb) {
+            mHandler.post(MessageHandler.MSG_SEND_COMMAND,
+                    new Pair<RouteCommand, ResultReceiver>(command, cb));
+        }
+
+        @Override
+        public boolean setRoute(RouteInfo route) throws RemoteException {
+            // TODO decide if allowed to set route and if the route exists
+            return false;
+        }
+
+        @Override
+        public void connectToRoute(RouteInfo route, RouteOptions request)
+                throws RemoteException {
+            if (mRoute == null || !TextUtils.equals(route.getId(), mRoute.getId())) {
+                throw new RemoteException("RouteInfo does not match current route");
+            }
+            mService.connectToRoute(MediaSessionRecord.this, route, request);
+            mRequest = request;
+        }
+
+        @Override
+        public void setRouteOptions(List<RouteOptions> options) throws RemoteException {
+            mRequests.clear();
+            for (int i = options.size() - 1; i >= 0; i--) {
+                RouteRequest request = new RouteRequest(mSessionInfo, options.get(i),
+                        false);
+                mRequests.add(request);
+            }
+        }
     }
 
     class SessionCb {
-        private final IMediaSessionCallback mCb;
+        private final ISessionCallback mCb;
 
-        public SessionCb(IMediaSessionCallback cb) {
+        public SessionCb(ISessionCallback cb) {
             mCb = cb;
         }
 
@@ -245,6 +467,38 @@
             }
         }
 
+        public void sendRouteChange(RouteInfo route) {
+            try {
+                mCb.onRequestRouteChange(route);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in sendRouteChange.", e);
+            }
+        }
+
+        public void sendRouteStateChange(int state) {
+            try {
+                mCb.onRouteStateChange(state);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in sendRouteStateChange.", e);
+            }
+        }
+
+        public void sendRouteEvent(RouteEvent event) {
+            try {
+                mCb.onRouteEvent(event);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in sendRouteEvent.", e);
+            }
+        }
+
+        public void sendRouteConnected() {
+            try {
+                mCb.onRouteConnected(mRoute, mRequest);
+            } catch (RemoteException e) {
+                Slog.e(TAG, "Remote failure in sendRouteStateChange.", e);
+            }
+        }
+
         public void play() {
             try {
                 mCb.onPlay();
@@ -318,7 +572,7 @@
         }
     }
 
-    class ControllerStub extends IMediaController.Stub {
+    class ControllerStub extends ISessionController.Stub {
         @Override
         public void sendCommand(String command, Bundle extras, ResultReceiver cb)
                 throws RemoteException {
@@ -331,8 +585,8 @@
         }
 
         @Override
-        public void registerCallbackListener(IMediaControllerCallback cb) {
-            synchronized (mControllerLock) {
+        public void registerCallbackListener(ISessionControllerCallback cb) {
+            synchronized (mLock) {
                 if (!mControllerCallbacks.contains(cb)) {
                     mControllerCallbacks.add(cb);
                 }
@@ -340,9 +594,9 @@
         }
 
         @Override
-        public void unregisterCallbackListener(IMediaControllerCallback cb)
+        public void unregisterCallbackListener(ISessionControllerCallback cb)
                 throws RemoteException {
-            synchronized (mControllerLock) {
+            synchronized (mLock) {
                 mControllerCallbacks.remove(cb);
             }
         }
@@ -400,7 +654,7 @@
 
         @Override
         public PlaybackState getPlaybackState() {
-            return mPlaybackState;
+            return getStateWithUpdatedPosition();
         }
 
         @Override
@@ -409,9 +663,14 @@
         }
 
         @Override
-        public boolean isTransportControlEnabled() throws RemoteException {
+        public boolean isTransportControlEnabled() {
             return mTransportPerformerEnabled;
         }
+
+        @Override
+        public void showRoutePicker() {
+            mService.showRoutePickerForSession(MediaSessionRecord.this);
+        }
     }
 
     private class MessageHandler extends Handler {
@@ -419,6 +678,8 @@
         private static final int MSG_UPDATE_PLAYBACK_STATE = 2;
         private static final int MSG_UPDATE_ROUTE = 3;
         private static final int MSG_SEND_EVENT = 4;
+        private static final int MSG_UPDATE_ROUTE_FILTERS = 5;
+        private static final int MSG_SEND_COMMAND = 6;
 
         public MessageHandler(Looper looper) {
             super(looper);
@@ -438,6 +699,11 @@
                 case MSG_SEND_EVENT:
                     pushEvent((String) msg.obj, msg.getData());
                     break;
+                case MSG_SEND_COMMAND:
+                    Pair<RouteCommand, ResultReceiver> cmd =
+                            (Pair<RouteCommand, ResultReceiver>) msg.obj;
+                    pushRouteCommand(cmd.first, cmd.second);
+                    break;
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaSessionService.java b/services/core/java/com/android/server/media/MediaSessionService.java
index 8fe6055..107f6ad 100644
--- a/services/core/java/com/android/server/media/MediaSessionService.java
+++ b/services/core/java/com/android/server/media/MediaSessionService.java
@@ -16,10 +16,15 @@
 
 package com.android.server.media;
 
+import android.Manifest;
 import android.content.Context;
-import android.media.session.IMediaSession;
-import android.media.session.IMediaSessionCallback;
-import android.media.session.IMediaSessionManager;
+import android.content.pm.PackageManager;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.ISession;
+import android.media.session.ISessionCallback;
+import android.media.session.ISessionManager;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -27,42 +32,110 @@
 import android.util.Log;
 
 import com.android.server.SystemService;
+import com.android.server.Watchdog;
+import com.android.server.Watchdog.Monitor;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 /**
  * System implementation of MediaSessionManager
  */
-public class MediaSessionService extends SystemService {
+public class MediaSessionService extends SystemService implements Monitor {
     private static final String TAG = "MediaSessionService";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final SessionManagerImpl mSessionManagerImpl;
+    private final MediaRouteProviderWatcher mRouteProviderWatcher;
 
     private final ArrayList<MediaSessionRecord> mSessions
             = new ArrayList<MediaSessionRecord>();
+    private final ArrayList<MediaRouteProviderProxy> mProviders
+            = new ArrayList<MediaRouteProviderProxy>();
     private final Object mLock = new Object();
     // TODO do we want a separate thread for handling mediasession messages?
     private final Handler mHandler = new Handler();
 
+    // Used to keep track of the current request to show routes for a specific
+    // session so we drop late callbacks properly.
+    private int mShowRoutesRequestId = 0;
+
+    // TODO refactor to have per user state. See MediaRouterService for an
+    // example
+
     public MediaSessionService(Context context) {
         super(context);
         mSessionManagerImpl = new SessionManagerImpl();
+        mRouteProviderWatcher = new MediaRouteProviderWatcher(context, mProviderWatcherCallback,
+                mHandler, context.getUserId());
     }
 
     @Override
     public void onStart() {
         publishBinderService(Context.MEDIA_SESSION_SERVICE, mSessionManagerImpl);
+        mRouteProviderWatcher.start();
+        Watchdog.getInstance().addMonitor(this);
+    }
+
+    /**
+     * Should trigger showing the Media route picker dialog. Right now it just
+     * kicks off a query to all the providers to get routes.
+     *
+     * @param record The session to show the picker for.
+     */
+    public void showRoutePickerForSession(MediaSessionRecord record) {
+        // TODO for now just toggle the route to test (we will only have one
+        // match for now)
+        if (record.getRoute() != null) {
+            // For now send null to mean the local route
+            record.selectRoute(null);
+            return;
+        }
+        mShowRoutesRequestId++;
+        ArrayList<MediaRouteProviderProxy> providers = mRouteProviderWatcher.getProviders();
+        for (int i = providers.size() - 1; i >= 0; i--) {
+            MediaRouteProviderProxy provider = providers.get(i);
+            provider.getRoutes(record, mShowRoutesRequestId);
+        }
+    }
+
+    /**
+     * Connect a session to the given route.
+     *
+     * @param session The session to connect.
+     * @param route The route to connect to.
+     * @param options The options to use for the connection.
+     */
+    public void connectToRoute(MediaSessionRecord session, RouteInfo route,
+            RouteOptions options) {
+        synchronized (mLock) {
+            MediaRouteProviderProxy proxy = getProviderLocked(route.getProvider());
+            if (proxy == null) {
+                Log.w(TAG, "Provider for route " + route.getName() + " does not exist.");
+                return;
+            }
+            RouteRequest request = new RouteRequest(session.getSessionInfo(), options, true);
+            // TODO make connect an async call to a ThreadPoolExecutor
+            proxy.connectToRoute(session, route, request);
+        }
+    }
+
+    @Override
+    public void monitor() {
+        synchronized (mLock) {
+            // Check for deadlock
+        }
     }
 
     void sessionDied(MediaSessionRecord session) {
-        synchronized (mSessions) {
+        synchronized (mLock) {
             destroySessionLocked(session);
         }
     }
 
     void destroySession(MediaSessionRecord session) {
-        synchronized (mSessions) {
+        synchronized (mLock) {
             destroySessionLocked(session);
         }
     }
@@ -86,14 +159,14 @@
     }
 
     private MediaSessionRecord createSessionInternal(int pid, String packageName,
-            IMediaSessionCallback cb, String tag) {
+            ISessionCallback cb, String tag) {
         synchronized (mLock) {
             return createSessionLocked(pid, packageName, cb, tag);
         }
     }
 
     private MediaSessionRecord createSessionLocked(int pid, String packageName,
-            IMediaSessionCallback cb, String tag) {
+            ISessionCallback cb, String tag) {
         final MediaSessionRecord session = new MediaSessionRecord(pid, packageName, cb, tag, this,
                 mHandler);
         try {
@@ -101,18 +174,89 @@
         } catch (RemoteException e) {
             throw new RuntimeException("Media Session owner died prematurely.", e);
         }
-        synchronized (mSessions) {
-            mSessions.add(session);
-        }
+        mSessions.add(session);
         if (DEBUG) {
             Log.d(TAG, "Created session for package " + packageName + " with tag " + tag);
         }
         return session;
     }
 
-    class SessionManagerImpl extends IMediaSessionManager.Stub {
+    private MediaRouteProviderProxy getProviderLocked(String providerId) {
+        for (int i = mProviders.size() - 1; i >= 0; i--) {
+            MediaRouteProviderProxy provider = mProviders.get(i);
+            if (TextUtils.equals(providerId, provider.getId())) {
+                return provider;
+            }
+        }
+        return null;
+    }
+
+    private int findIndexOfSessionForIdLocked(String sessionId) {
+        for (int i = mSessions.size() - 1; i >= 0; i--) {
+            MediaSessionRecord session = mSessions.get(i);
+            if (TextUtils.equals(session.getSessionInfo().getId(), sessionId)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    private MediaRouteProviderWatcher.Callback mProviderWatcherCallback
+            = new MediaRouteProviderWatcher.Callback() {
         @Override
-        public IMediaSession createSession(String packageName, IMediaSessionCallback cb, String tag)
+        public void removeProvider(MediaRouteProviderProxy provider) {
+            synchronized (mLock) {
+                mProviders.remove(provider);
+                provider.setRoutesListener(null);
+                provider.setInterested(false);
+            }
+        }
+
+        @Override
+        public void addProvider(MediaRouteProviderProxy provider) {
+            synchronized (mLock) {
+                mProviders.add(provider);
+                provider.setRoutesListener(mRoutesCallback);
+                provider.setInterested(true);
+            }
+        }
+    };
+
+    private MediaRouteProviderProxy.RoutesListener mRoutesCallback
+            = new MediaRouteProviderProxy.RoutesListener() {
+        @Override
+        public void onRoutesUpdated(String sessionId, ArrayList<RouteInfo> routes,
+                int reqId) {
+            // TODO for now select the first route to test, eventually add the
+            // new routes to the dialog if it is still open
+            synchronized (mLock) {
+                int index = findIndexOfSessionForIdLocked(sessionId);
+                if (index != -1 && routes != null && routes.size() > 0) {
+                    MediaSessionRecord record = mSessions.get(index);
+                    record.selectRoute(routes.get(0));
+                }
+            }
+        }
+
+        @Override
+        public void onRouteConnected(String sessionId, RouteInfo route,
+                RouteRequest options, RouteConnectionRecord connection) {
+            synchronized (mLock) {
+                int index = findIndexOfSessionForIdLocked(sessionId);
+                if (index != -1) {
+                    MediaSessionRecord session = mSessions.get(index);
+                    session.setRouteConnected(route, options.getConnectionOptions(), connection);
+                }
+            }
+        }
+    };
+
+    class SessionManagerImpl extends ISessionManager.Stub {
+        // TODO add createSessionAsUser, pass user-id to
+        // ActivityManagerNative.handleIncomingUser and stash result for use
+        // when starting services on that session's behalf.
+        @Override
+        public ISession createSession(String packageName, ISessionCallback cb, String tag)
                 throws RemoteException {
             final int pid = Binder.getCallingPid();
             final int uid = Binder.getCallingUid();
@@ -127,6 +271,36 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        public void dump(FileDescriptor fd, final PrintWriter pw, String[] args) {
+            if (getContext().checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump MediaSessionService from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+                return;
+            }
+
+            pw.println("MEDIA SESSION SERVICE (dumpsys media_session)");
+            pw.println();
+
+            synchronized (mLock) {
+                int count = mSessions.size();
+                pw.println("Sessions - have " + count + " states:");
+                for (int i = 0; i < count; i++) {
+                    MediaSessionRecord record = mSessions.get(i);
+                    pw.println();
+                    record.dump(pw, "");
+                }
+                pw.println("Providers:");
+                count = mProviders.size();
+                for (int i = 0; i < count; i++) {
+                    MediaRouteProviderProxy provider = mProviders.get(i);
+                    provider.dump(pw, "");
+                }
+            }
+        }
     }
 
 }
diff --git a/services/core/java/com/android/server/media/RouteConnectionRecord.java b/services/core/java/com/android/server/media/RouteConnectionRecord.java
new file mode 100644
index 0000000..90ddf29
--- /dev/null
+++ b/services/core/java/com/android/server/media/RouteConnectionRecord.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.media;
+
+import android.media.routeprovider.IRouteConnection;
+import android.media.session.RouteCommand;
+import android.media.session.RouteEvent;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+/**
+ * A connection between a Session and a Route.
+ */
+public class RouteConnectionRecord {
+    private static final String TAG = "RouteConnRecord";
+    private final IRouteConnection mBinder;
+    private final String mPackageName;
+    private final int mUid;
+    private Listener mListener;
+
+    public RouteConnectionRecord(IRouteConnection binder, String packageName, int uid) {
+        mBinder = binder;
+        mPackageName = packageName;
+        mUid = uid;
+    }
+
+    /**
+     * Add a listener to get route events on.
+     *
+     * @param listener The listener to get events on.
+     */
+    public void setListener(Listener listener) {
+        mListener = listener;
+    }
+
+    /**
+     * Check if this connection matches the token given.
+     *
+     * @param binder The token to check
+     * @return True if this is the connection you're looking for, false
+     *         otherwise.
+     */
+    public boolean isConnection(IBinder binder) {
+        return binder != null && binder.equals(mBinder.asBinder());
+    }
+
+    /**
+     * Send an event from this connection.
+     *
+     * @param event The event to send.
+     */
+    public void sendEvent(RouteEvent event) {
+        if (mListener != null) {
+            mListener.onEvent(event);
+        }
+    }
+
+    /**
+     * Send a command to this connection.
+     *
+     * @param command The command to send.
+     * @param cb The receiver to get a result on.
+     */
+    public void sendCommand(RouteCommand command, ResultReceiver cb) {
+        try {
+            mBinder.onCommand(command, cb);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Error in sendCommand", e);
+        }
+    }
+
+    /**
+     * Tell the session that the provider has disconnected it.
+     */
+    public void disconnect() {
+        if (mListener != null) {
+            mListener.disconnect();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "RouteConnection { binder=" + mBinder.toString() + ", package=" + mPackageName
+                + ", uid=" + mUid + "}";
+    }
+
+    /**
+     * Listener to receive updates from the provider for this connection.
+     */
+    public static interface Listener {
+        /**
+         * Called when an event is sent on this connection.
+         *
+         * @param event The event that was sent.
+         */
+        public void onEvent(RouteEvent event);
+
+        /**
+         * Called when the provider has disconnected the route.
+         */
+        public void disconnect();
+    }
+}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index eb7cc4c..416a6b1 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -410,7 +410,7 @@
         }
 
         @Override
-        public void onImportanceChanged(int pid, int uid, int importance) {
+        public void onProcessStateChanged(int pid, int uid, int procState) {
         }
 
         @Override
@@ -1730,7 +1730,7 @@
     private void updateScreenOn() {
         synchronized (mRulesLock) {
             try {
-                mScreenOn = mPowerManager.isScreenOn();
+                mScreenOn = mPowerManager.isInteractive();
             } catch (RemoteException e) {
                 // ignored; service lives in system_server
             }
diff --git a/services/core/java/com/android/server/notification/ConditionProviders.java b/services/core/java/com/android/server/notification/ConditionProviders.java
new file mode 100644
index 0000000..5567944
--- /dev/null
+++ b/services/core/java/com/android/server/notification/ConditionProviders.java
@@ -0,0 +1,263 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.content.Context;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.service.notification.Condition;
+import android.service.notification.ConditionProviderService;
+import android.service.notification.IConditionListener;
+import android.service.notification.IConditionProvider;
+import android.util.ArrayMap;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import libcore.util.Objects;
+
+import java.io.PrintWriter;
+import java.util.Arrays;
+
+public class ConditionProviders extends ManagedServices {
+
+    private final ZenModeHelper mZenModeHelper;
+    private final ArrayMap<IBinder, IConditionListener> mListeners
+            = new ArrayMap<IBinder, IConditionListener>();
+    private final ArrayMap<Uri, ManagedServiceInfo> mConditions
+            = new ArrayMap<Uri, ManagedServiceInfo>();
+
+    private Uri mCurrentConditionId;
+
+    public ConditionProviders(Context context, Handler handler,
+            UserProfiles userProfiles, ZenModeHelper zenModeHelper) {
+        super(context, handler, new Object(), userProfiles);
+        mZenModeHelper = zenModeHelper;
+        mZenModeHelper.addCallback(new ZenModeHelperCallback());
+    }
+
+    @Override
+    protected Config getConfig() {
+        Config c = new Config();
+        c.caption = "condition provider";
+        c.serviceInterface = ConditionProviderService.SERVICE_INTERFACE;
+        c.secureSettingName = Settings.Secure.ENABLED_CONDITION_PROVIDERS;
+        c.bindPermission = android.Manifest.permission.BIND_CONDITION_PROVIDER_SERVICE;
+        c.settingsAction = Settings.ACTION_CONDITION_PROVIDER_SETTINGS;
+        c.clientLabel = R.string.condition_provider_service_binding_label;
+        return c;
+    }
+
+    @Override
+    public void dump(PrintWriter pw) {
+        super.dump(pw);
+        synchronized(mMutex) {
+            pw.print("    mCurrentConditionId="); pw.println(mCurrentConditionId);
+            pw.print("    mListeners("); pw.print(mListeners.size()); pw.println("):");
+            for (int i = 0; i < mListeners.size(); i++) {
+                pw.print("      "); pw.println(mListeners.keyAt(i));
+            }
+            pw.print("    mConditions("); pw.print(mConditions.size()); pw.println("):");
+            for (int i = 0; i < mConditions.size(); i++) {
+                pw.print("      "); pw.print(mConditions.keyAt(i));
+                final ManagedServiceInfo info = mConditions.valueAt(i);
+                pw.print(" -> "); pw.print(info.component);
+                if (!mServices.contains(info)) {
+                    pw.print(" (orphan)");
+                }
+                pw.println();
+            }
+        }
+    }
+
+    @Override
+    protected IInterface asInterface(IBinder binder) {
+        return IConditionProvider.Stub.asInterface(binder);
+    }
+
+    @Override
+    protected void onServiceAdded(IInterface service) {
+        Slog.d(TAG, "onServiceAdded " + service);
+        final IConditionProvider provider = (IConditionProvider) service;
+        try {
+            provider.onConnected();
+        } catch (RemoteException e) {
+            // we tried
+        }
+    }
+
+    @Override
+    protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
+        if (removed == null) return;
+        if (mCurrentConditionId != null) {
+            if (removed.equals(mConditions.get(mCurrentConditionId))) {
+                mCurrentConditionId = null;
+                mZenModeHelper.setZenMode(Global.ZEN_MODE_OFF);
+            }
+        }
+        for (int i = mConditions.size() - 1; i >= 0; i--) {
+            if (removed.equals(mConditions.valueAt(i))) {
+                mConditions.removeAt(i);
+            }
+        }
+    }
+
+    public ManagedServiceInfo checkServiceToken(IConditionProvider provider) {
+        synchronized(mMutex) {
+            return checkServiceTokenLocked(provider);
+        }
+    }
+
+    public void requestZenModeConditions(IConditionListener callback, boolean requested) {
+        synchronized(mMutex) {
+            if (DEBUG) Slog.d(TAG, "requestZenModeConditions callback=" + callback
+                    + " requested=" + requested);
+            if (callback == null) return;
+            if (requested) {
+                mListeners.put(callback.asBinder(), callback);
+                requestConditionsLocked(Condition.FLAG_RELEVANT_NOW);
+            } else {
+                mListeners.remove(callback.asBinder());
+                if (mListeners.isEmpty()) {
+                    requestConditionsLocked(0);
+                }
+            }
+        }
+    }
+
+    public void notifyConditions(String pkg, ManagedServiceInfo info, Condition[] conditions) {
+        synchronized(mMutex) {
+            if (DEBUG) Slog.d(TAG, "notifyConditions pkg=" + pkg + " info=" + info + " conditions="
+                    + (conditions == null ? null : Arrays.asList(conditions)));
+            if (conditions == null || conditions.length == 0) return;
+            final int N = conditions.length;
+            boolean valid = true;
+            for (int i = 0; i < N; i++) {
+                final Uri id = conditions[i].id;
+                if (!Condition.isValidId(id, pkg)) {
+                    Slog.w(TAG, "Ignoring conditions from " + pkg + " for invalid id: " + id);
+                    valid = false;
+                }
+            }
+            if (!valid) return;
+
+            for (int i = 0; i < N; i++) {
+                mConditions.put(conditions[i].id, info);
+            }
+            for (IConditionListener listener : mListeners.values()) {
+                try {
+                    listener.onConditionsReceived(conditions);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Error sending conditions to listener " + listener, e);
+                }
+            }
+            if (mCurrentConditionId != null) {
+                for (int i = 0; i < N; i++) {
+                    final Condition c = conditions[i];
+                    if (!c.id.equals(mCurrentConditionId)) continue;
+                    if (c.state == Condition.STATE_TRUE || c.state == Condition.STATE_ERROR) {
+                        triggerExitLocked(c.state == Condition.STATE_ERROR);
+                        return;
+                    }
+                }
+            }
+        }
+    }
+
+    private void triggerExitLocked(boolean error) {
+        if (error) {
+            Slog.w(TAG, "Zen mode exit condition failed");
+        } else if (DEBUG) {
+            Slog.d(TAG, "Zen mode exit condition triggered");
+        }
+        mZenModeHelper.setZenMode(Settings.Global.ZEN_MODE_OFF);
+        unsubscribeLocked(mCurrentConditionId);
+        mCurrentConditionId = null;
+    }
+
+    public void setZenModeCondition(Uri conditionId) {
+        synchronized(mMutex) {
+            if (DEBUG) Slog.d(TAG, "setZenModeCondition " + conditionId);
+            if (Objects.equal(mCurrentConditionId, conditionId)) return;
+
+            if (mCurrentConditionId != null) {
+                unsubscribeLocked(mCurrentConditionId);
+            }
+            if (conditionId != null) {
+                final ManagedServiceInfo info = mConditions.get(conditionId);
+                final IConditionProvider provider = provider(info);
+                if (provider == null) return;
+                try {
+                    provider.onSubscribe(conditionId);
+                } catch (RemoteException e) {
+                    Slog.w(TAG, "Error subscribing to " + conditionId
+                            + " from " + info.component, e);
+                }
+            }
+            mCurrentConditionId = conditionId;
+        }
+    }
+
+    private void unsubscribeLocked(Uri conditionId) {
+        final ManagedServiceInfo info = mConditions.get(mCurrentConditionId);
+        final IConditionProvider provider = provider(info);
+        if (provider == null) return;
+        try {
+            provider.onUnsubscribe(conditionId);
+        } catch (RemoteException e) {
+            Slog.w(TAG, "Error unsubscribing to " + conditionId + " from " + info.component, e);
+        }
+    }
+
+    private static IConditionProvider provider(ManagedServiceInfo info) {
+        return info == null ? null : (IConditionProvider) info.service;
+    }
+
+    private void requestConditionsLocked(int flags) {
+        for (ManagedServiceInfo info : mServices) {
+            final IConditionProvider provider = provider(info);
+            if (provider == null) continue;
+            try {
+                provider.onRequestConditions(flags);
+            } catch (RemoteException e) {
+                Slog.w(TAG, "Error requesting conditions from " + info.component, e);
+            }
+        }
+    }
+
+    private class ZenModeHelperCallback extends ZenModeHelper.Callback {
+        @Override
+        void onZenModeChanged() {
+            final int mode = mZenModeHelper.getZenMode();
+            if (mode == Global.ZEN_MODE_OFF) {
+                synchronized (mMutex) {
+                    if (mCurrentConditionId != null) {
+                        if (DEBUG) Slog.d(TAG, "Zen mode off, forcing unsubscribe from "
+                                + mCurrentConditionId);
+                        unsubscribeLocked(mCurrentConditionId);
+                        mCurrentConditionId = null;
+                    }
+                }
+            }
+        }
+    }
+}
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
new file mode 100644
index 0000000..0621f58
--- /dev/null
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -0,0 +1,621 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.app.ActivityManager;
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.content.pm.UserInfo;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.IInterface;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.text.TextUtils;
+import android.util.ArraySet;
+import android.util.Slog;
+import android.util.SparseArray;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * Manages the lifecycle of application-provided services bound by system server.
+ *
+ * Services managed by this helper must have:
+ *  - An associated system settings value with a list of enabled component names.
+ *  - A well-known action for services to use in their intent-filter.
+ *  - A system permission for services to require in order to ensure system has exclusive binding.
+ *  - A settings page for user configuration of enabled services, and associated intent action.
+ *  - A remote interface definition (aidl) provided by the service used for communication.
+ */
+abstract public class ManagedServices {
+    protected final String TAG = getClass().getSimpleName();
+    protected static final boolean DEBUG = true;
+
+    private static final String ENABLED_SERVICES_SEPARATOR = ":";
+
+    private final Context mContext;
+    protected final Object mMutex;
+    private final UserProfiles mUserProfiles;
+    private final SettingsObserver mSettingsObserver;
+    private final Config mConfig;
+
+    // contains connections to all connected services, including app services
+    // and system services
+    protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
+    // things that will be put into mServices as soon as they're ready
+    private final ArrayList<String> mServicesBinding = new ArrayList<String>();
+    // lists the component names of all enabled (and therefore connected)
+    // app services for current profiles.
+    private ArraySet<ComponentName> mEnabledServicesForCurrentProfiles
+            = new ArraySet<ComponentName>();
+    // Just the packages from mEnabledServicesForCurrentProfiles
+    private ArraySet<String> mEnabledServicesPackageNames = new ArraySet<String>();
+
+    public ManagedServices(Context context, Handler handler, Object mutex,
+            UserProfiles userProfiles) {
+        mContext = context;
+        mMutex = mutex;
+        mUserProfiles = userProfiles;
+        mConfig = getConfig();
+        mSettingsObserver = new SettingsObserver(handler);
+    }
+
+    abstract protected Config getConfig();
+
+    private String getCaption() {
+        return mConfig.caption;
+    }
+
+    abstract protected IInterface asInterface(IBinder binder);
+
+    abstract protected void onServiceAdded(IInterface service);
+
+    protected void onServiceRemovedLocked(ManagedServiceInfo removed) { }
+
+    private ManagedServiceInfo newServiceInfo(IInterface service,
+            ComponentName component, int userid, boolean isSystem, ServiceConnection connection,
+            int targetSdkVersion) {
+        return new ManagedServiceInfo(service, component, userid, isSystem, connection,
+                targetSdkVersion);
+    }
+
+    public void onBootPhaseAppsCanStart() {
+        mSettingsObserver.observe();
+    }
+
+    public void dump(PrintWriter pw) {
+        pw.println("    All " + getCaption() + "s (" + mEnabledServicesForCurrentProfiles.size()
+                + ") enabled for current profiles:");
+        for (ComponentName cmpt : mEnabledServicesForCurrentProfiles) {
+            pw.println("      " + cmpt);
+        }
+
+        pw.println("    Live " + getCaption() + "s (" + mServices.size() + "):");
+        for (ManagedServiceInfo info : mServices) {
+            pw.println("      " + info.component
+                    + " (user " + info.userid + "): " + info.service
+                    + (info.isSystem?" SYSTEM":""));
+        }
+    }
+
+    public void onPackagesChanged(boolean queryReplace, String[] pkgList) {
+        if (DEBUG) Slog.d(TAG, "onPackagesChanged queryReplace=" + queryReplace
+                + " pkgList=" + (pkgList == null ? null : Arrays.asList(pkgList))
+                + " mEnabledServicesPackageNames=" + mEnabledServicesPackageNames);
+        boolean anyServicesInvolved = false;
+        if (pkgList != null && (pkgList.length > 0)) {
+            for (String pkgName : pkgList) {
+                if (mEnabledServicesPackageNames.contains(pkgName)) {
+                    anyServicesInvolved = true;
+                }
+            }
+        }
+
+        if (anyServicesInvolved) {
+            // if we're not replacing a package, clean up orphaned bits
+            if (!queryReplace) {
+                disableNonexistentServices();
+            }
+            // make sure we're still bound to any of our services who may have just upgraded
+            rebindServices();
+        }
+    }
+
+    public ManagedServiceInfo checkServiceTokenLocked(IInterface service) {
+        checkNotNull(service);
+        final IBinder token = service.asBinder();
+        final int N = mServices.size();
+        for (int i=0; i<N; i++) {
+            final ManagedServiceInfo info = mServices.get(i);
+            if (info.service.asBinder() == token) return info;
+        }
+        throw new SecurityException("Disallowed call from unknown " + getCaption() + ": "
+                + service);
+    }
+
+    public void unregisterService(IInterface service, int userid) {
+        checkNotNull(service);
+        // no need to check permissions; if your service binder is in the list,
+        // that's proof that you had permission to add it in the first place
+        unregisterServiceImpl(service, userid);
+    }
+
+    public void registerService(IInterface service, ComponentName component, int userid) {
+        checkNotNull(service);
+        registerServiceImpl(service, component, userid);
+    }
+
+    /**
+     * Remove access for any services that no longer exist.
+     */
+    private void disableNonexistentServices() {
+        int[] userIds = mUserProfiles.getCurrentProfileIds();
+        final int N = userIds.length;
+        for (int i = 0 ; i < N; ++i) {
+            disableNonexistentServices(userIds[i]);
+        }
+    }
+
+    private void disableNonexistentServices(int userId) {
+        String flatIn = Settings.Secure.getStringForUser(
+                mContext.getContentResolver(),
+                mConfig.secureSettingName,
+                userId);
+        if (!TextUtils.isEmpty(flatIn)) {
+            if (DEBUG) Slog.v(TAG, "flat before: " + flatIn);
+            PackageManager pm = mContext.getPackageManager();
+            List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
+                    new Intent(mConfig.serviceInterface),
+                    PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
+                    userId);
+            if (DEBUG) Slog.v(TAG, mConfig.serviceInterface + " services: " + installedServices);
+            Set<ComponentName> installed = new ArraySet<ComponentName>();
+            for (int i = 0, count = installedServices.size(); i < count; i++) {
+                ResolveInfo resolveInfo = installedServices.get(i);
+                ServiceInfo info = resolveInfo.serviceInfo;
+
+                if (!mConfig.bindPermission.equals(info.permission)) {
+                    Slog.w(TAG, "Skipping " + getCaption() + " service "
+                            + info.packageName + "/" + info.name
+                            + ": it does not require the permission "
+                            + mConfig.bindPermission);
+                    continue;
+                }
+                installed.add(new ComponentName(info.packageName, info.name));
+            }
+
+            String flatOut = "";
+            if (!installed.isEmpty()) {
+                String[] enabled = flatIn.split(ENABLED_SERVICES_SEPARATOR);
+                ArrayList<String> remaining = new ArrayList<String>(enabled.length);
+                for (int i = 0; i < enabled.length; i++) {
+                    ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]);
+                    if (installed.contains(enabledComponent)) {
+                        remaining.add(enabled[i]);
+                    }
+                }
+                flatOut = TextUtils.join(ENABLED_SERVICES_SEPARATOR, remaining);
+            }
+            if (DEBUG) Slog.v(TAG, "flat after: " + flatOut);
+            if (!flatIn.equals(flatOut)) {
+                Settings.Secure.putStringForUser(mContext.getContentResolver(),
+                        mConfig.secureSettingName,
+                        flatOut, userId);
+            }
+        }
+    }
+
+    /**
+     * Called whenever packages change, the user switches, or the secure setting
+     * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
+     */
+    private void rebindServices() {
+        if (DEBUG) Slog.d(TAG, "rebindServices");
+        final int[] userIds = mUserProfiles.getCurrentProfileIds();
+        final int nUserIds = userIds.length;
+
+        final SparseArray<String> flat = new SparseArray<String>();
+
+        for (int i = 0; i < nUserIds; ++i) {
+            flat.put(userIds[i], Settings.Secure.getStringForUser(
+                    mContext.getContentResolver(),
+                    mConfig.secureSettingName,
+                    userIds[i]));
+        }
+
+        ManagedServiceInfo[] toRemove = new ManagedServiceInfo[mServices.size()];
+        final SparseArray<ArrayList<ComponentName>> toAdd
+                = new SparseArray<ArrayList<ComponentName>>();
+
+        synchronized (mMutex) {
+            // unbind and remove all existing services
+            toRemove = mServices.toArray(toRemove);
+
+            final ArraySet<ComponentName> newEnabled = new ArraySet<ComponentName>();
+            final ArraySet<String> newPackages = new ArraySet<String>();
+
+            for (int i = 0; i < nUserIds; ++i) {
+                final ArrayList<ComponentName> add = new ArrayList<ComponentName>();
+                toAdd.put(userIds[i], add);
+
+                // decode the list of components
+                String toDecode = flat.get(userIds[i]);
+                if (toDecode != null) {
+                    String[] components = toDecode.split(ENABLED_SERVICES_SEPARATOR);
+                    for (int j = 0; j < components.length; j++) {
+                        final ComponentName component
+                                = ComponentName.unflattenFromString(components[j]);
+                        if (component != null) {
+                            newEnabled.add(component);
+                            add.add(component);
+                            newPackages.add(component.getPackageName());
+                        }
+                    }
+
+                }
+            }
+            mEnabledServicesForCurrentProfiles = newEnabled;
+            mEnabledServicesPackageNames = newPackages;
+        }
+
+        for (ManagedServiceInfo info : toRemove) {
+            final ComponentName component = info.component;
+            final int oldUser = info.userid;
+            Slog.v(TAG, "disabling " + getCaption() + " for user "
+                    + oldUser + ": " + component);
+            unregisterService(component, info.userid);
+        }
+
+        for (int i = 0; i < nUserIds; ++i) {
+            final ArrayList<ComponentName> add = toAdd.get(userIds[i]);
+            final int N = add.size();
+            for (int j = 0; j < N; j++) {
+                final ComponentName component = add.get(j);
+                Slog.v(TAG, "enabling " + getCaption() + " for user " + userIds[i] + ": "
+                        + component);
+                registerService(component, userIds[i]);
+            }
+        }
+    }
+
+    /**
+     * Version of registerService that takes the name of a service component to bind to.
+     */
+    private void registerService(final ComponentName name, final int userid) {
+        if (DEBUG) Slog.v(TAG, "registerService: " + name + " u=" + userid);
+
+        synchronized (mMutex) {
+            final String servicesBindingTag = name.toString() + "/" + userid;
+            if (mServicesBinding.contains(servicesBindingTag)) {
+                // stop registering this thing already! we're working on it
+                return;
+            }
+            mServicesBinding.add(servicesBindingTag);
+
+            final int N = mServices.size();
+            for (int i=N-1; i>=0; i--) {
+                final ManagedServiceInfo info = mServices.get(i);
+                if (name.equals(info.component)
+                        && info.userid == userid) {
+                    // cut old connections
+                    if (DEBUG) Slog.v(TAG, "    disconnecting old " + getCaption() + ": "
+                            + info.service);
+                    removeServiceLocked(i);
+                    if (info.connection != null) {
+                        mContext.unbindService(info.connection);
+                    }
+                }
+            }
+
+            Intent intent = new Intent(mConfig.serviceInterface);
+            intent.setComponent(name);
+
+            intent.putExtra(Intent.EXTRA_CLIENT_LABEL, mConfig.clientLabel);
+
+            final PendingIntent pendingIntent = PendingIntent.getActivity(
+                    mContext, 0, new Intent(mConfig.settingsAction), 0);
+            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
+
+            ApplicationInfo appInfo = null;
+            try {
+                appInfo = mContext.getPackageManager().getApplicationInfo(
+                        name.getPackageName(), 0);
+            } catch (NameNotFoundException e) {
+                // Ignore if the package doesn't exist we won't be able to bind to the service.
+            }
+            final int targetSdkVersion =
+                    appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
+
+            try {
+                if (DEBUG) Slog.v(TAG, "binding: " + intent);
+                if (!mContext.bindServiceAsUser(intent,
+                        new ServiceConnection() {
+                            IInterface mService;
+
+                            @Override
+                            public void onServiceConnected(ComponentName name, IBinder binder) {
+                                boolean added = false;
+                                synchronized (mMutex) {
+                                    mServicesBinding.remove(servicesBindingTag);
+                                    try {
+                                        mService = asInterface(binder);
+                                        ManagedServiceInfo info = newServiceInfo(mService, name,
+                                                userid, false /*isSystem*/, this, targetSdkVersion);
+                                        binder.linkToDeath(info, 0);
+                                        added = mServices.add(info);
+                                    } catch (RemoteException e) {
+                                        // already dead
+                                    }
+                                }
+                                if (added) {
+                                    onServiceAdded(mService);
+                                }
+                            }
+
+                            @Override
+                            public void onServiceDisconnected(ComponentName name) {
+                                Slog.v(TAG, getCaption() + " connection lost: " + name);
+                            }
+                        },
+                        Context.BIND_AUTO_CREATE,
+                        new UserHandle(userid)))
+                {
+                    mServicesBinding.remove(servicesBindingTag);
+                    Slog.w(TAG, "Unable to bind " + getCaption() + " service: " + intent);
+                    return;
+                }
+            } catch (SecurityException ex) {
+                Slog.e(TAG, "Unable to bind " + getCaption() + " service: " + intent, ex);
+                return;
+            }
+        }
+    }
+
+    /**
+     * Remove a service for the given user by ComponentName
+     */
+    private void unregisterService(ComponentName name, int userid) {
+        synchronized (mMutex) {
+            final int N = mServices.size();
+            for (int i=N-1; i>=0; i--) {
+                final ManagedServiceInfo info = mServices.get(i);
+                if (name.equals(info.component)
+                        && info.userid == userid) {
+                    removeServiceLocked(i);
+                    if (info.connection != null) {
+                        try {
+                            mContext.unbindService(info.connection);
+                        } catch (IllegalArgumentException ex) {
+                            // something happened to the service: we think we have a connection
+                            // but it's bogus.
+                            Slog.e(TAG, getCaption() + " " + name + " could not be unbound: " + ex);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /**
+     * Removes a service from the list but does not unbind
+     *
+     * @return the removed service.
+     */
+    private ManagedServiceInfo removeServiceImpl(IInterface service, final int userid) {
+        if (DEBUG) Slog.d(TAG, "removeServiceImpl service=" + service + " u=" + userid);
+        ManagedServiceInfo serviceInfo = null;
+        synchronized (mMutex) {
+            final int N = mServices.size();
+            for (int i=N-1; i>=0; i--) {
+                final ManagedServiceInfo info = mServices.get(i);
+                if (info.service.asBinder() == service.asBinder()
+                        && info.userid == userid) {
+                    if (DEBUG) Slog.d(TAG, "Removing active service " + info.component);
+                    serviceInfo = removeServiceLocked(i);
+                }
+            }
+        }
+        return serviceInfo;
+    }
+
+    private ManagedServiceInfo removeServiceLocked(int i) {
+        final ManagedServiceInfo info = mServices.remove(i);
+        onServiceRemovedLocked(info);
+        return info;
+    }
+
+    private void checkNotNull(IInterface service) {
+        if (service == null) {
+            throw new IllegalArgumentException(getCaption() + " must not be null");
+        }
+    }
+
+    private void registerServiceImpl(final IInterface service,
+            final ComponentName component, final int userid) {
+        synchronized (mMutex) {
+            try {
+                ManagedServiceInfo info = newServiceInfo(service, component, userid,
+                        true /*isSystem*/, null, Build.VERSION_CODES.L);
+                service.asBinder().linkToDeath(info, 0);
+                mServices.add(info);
+            } catch (RemoteException e) {
+                // already dead
+            }
+        }
+    }
+
+    /**
+     * Removes a service from the list and unbinds.
+     */
+    private void unregisterServiceImpl(IInterface service, int userid) {
+        ManagedServiceInfo info = removeServiceImpl(service, userid);
+        if (info != null && info.connection != null) {
+            mContext.unbindService(info.connection);
+        }
+    }
+
+    private class SettingsObserver extends ContentObserver {
+        private final Uri mSecureSettingsUri = Settings.Secure.getUriFor(mConfig.secureSettingName);
+
+        private SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        private void observe() {
+            ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(mSecureSettingsUri,
+                    false, this, UserHandle.USER_ALL);
+            update(null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            update(uri);
+        }
+
+        private void update(Uri uri) {
+            if (uri == null || mSecureSettingsUri.equals(uri)) {
+                rebindServices();
+            }
+        }
+    }
+
+    public class ManagedServiceInfo implements IBinder.DeathRecipient {
+        public IInterface service;
+        public ComponentName component;
+        public int userid;
+        public boolean isSystem;
+        public ServiceConnection connection;
+        public int targetSdkVersion;
+
+        public ManagedServiceInfo(IInterface service, ComponentName component,
+                int userid, boolean isSystem, ServiceConnection connection, int targetSdkVersion) {
+            this.service = service;
+            this.component = component;
+            this.userid = userid;
+            this.isSystem = isSystem;
+            this.connection = connection;
+            this.targetSdkVersion = targetSdkVersion;
+        }
+
+        @Override
+        public String toString() {
+            return new StringBuilder("ManagedServiceInfo[")
+                    .append("component=").append(component)
+                    .append(",userid=").append(userid)
+                    .append(",isSystem=").append(isSystem)
+                    .append(",targetSdkVersion=").append(targetSdkVersion)
+                    .append(",connection=").append(connection == null ? null : "<connection>")
+                    .append(",service=").append(service)
+                    .append(']').toString();
+        }
+
+        public boolean enabledAndUserMatches(int nid) {
+            if (!isEnabledForCurrentProfiles()) {
+                return false;
+            }
+            if (this.userid == UserHandle.USER_ALL) return true;
+            if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
+            return supportsProfiles() && mUserProfiles.isCurrentProfile(nid);
+        }
+
+        public boolean supportsProfiles() {
+            return targetSdkVersion >= Build.VERSION_CODES.L;
+        }
+
+        @Override
+        public void binderDied() {
+            if (DEBUG) Slog.d(TAG, "binderDied");
+            // Remove the service, but don't unbind from the service. The system will bring the
+            // service back up, and the onServiceConnected handler will readd the service with the
+            // new binding. If this isn't a bound service, and is just a registered
+            // service, just removing it from the list is all we need to do anyway.
+            removeServiceImpl(this.service, this.userid);
+        }
+
+        /** convenience method for looking in mEnabledServicesForCurrentProfiles */
+        public boolean isEnabledForCurrentProfiles() {
+            if (this.isSystem) return true;
+            if (this.connection == null) return false;
+            return mEnabledServicesForCurrentProfiles.contains(this.component);
+        }
+    }
+
+    public static class UserProfiles {
+        // Profiles of the current user.
+        private final SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
+
+        public void updateCache(Context context) {
+            UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
+            if (userManager != null) {
+                int currentUserId = ActivityManager.getCurrentUser();
+                List<UserInfo> profiles = userManager.getProfiles(currentUserId);
+                synchronized (mCurrentProfiles) {
+                    mCurrentProfiles.clear();
+                    for (UserInfo user : profiles) {
+                        mCurrentProfiles.put(user.id, user);
+                    }
+                }
+            }
+        }
+
+        public int[] getCurrentProfileIds() {
+            synchronized (mCurrentProfiles) {
+                int[] users = new int[mCurrentProfiles.size()];
+                final int N = mCurrentProfiles.size();
+                for (int i = 0; i < N; ++i) {
+                    users[i] = mCurrentProfiles.keyAt(i);
+                }
+                return users;
+            }
+        }
+
+        public boolean isCurrentProfile(int userId) {
+            synchronized (mCurrentProfiles) {
+                return mCurrentProfiles.get(userId) != null;
+            }
+        }
+    }
+
+    protected static class Config {
+        String caption;
+        String serviceInterface;
+        String secureSettingName;
+        String bindPermission;
+        String settingsAction;
+        int clientLabel;
+    }
+}
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index e0591a2..ce4c1ed 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -31,4 +31,6 @@
     void onPanelRevealed();
     void onPanelHidden();
     boolean allowDisable(int what, IBinder token, String pkg);
+    void onNotificationVisibilityChanged(
+            String[] newlyVisibleKeys, String[] noLongerVisibleKeys);
 }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 6534783..6e4eb56 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -36,14 +36,10 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.ServiceInfo;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.database.ContentObserver;
 import android.graphics.Bitmap;
@@ -51,26 +47,29 @@
 import android.media.IRingtonePlayer;
 import android.net.Uri;
 import android.os.Binder;
-import android.os.Build;
+import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
+import android.os.IInterface;
 import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
-import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
 import android.service.notification.INotificationListener;
+import android.service.notification.IConditionListener;
+import android.service.notification.IConditionProvider;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.StatusBarNotification;
+import android.service.notification.Condition;
+import android.service.notification.ZenModeConfig;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Log;
 import android.util.Slog;
-import android.util.SparseArray;
 import android.util.Xml;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityManager;
@@ -78,20 +77,27 @@
 
 import com.android.internal.R;
 import com.android.internal.notification.NotificationScorer;
+import com.android.internal.util.FastXmlSerializer;
 import com.android.server.EventLogTags;
-import com.android.server.notification.NotificationUsageStats.SingleNotificationStats;
-import com.android.server.statusbar.StatusBarManagerInternal;
 import com.android.server.SystemService;
 import com.android.server.lights.Light;
 import com.android.server.lights.LightsManager;
+import com.android.server.notification.ManagedServices.ManagedServiceInfo;
+import com.android.server.notification.ManagedServices.UserProfiles;
+import com.android.server.notification.NotificationUsageStats.SingleNotificationStats;
+import com.android.server.statusbar.StatusBarManagerInternal;
+
+import libcore.io.IoUtils;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
 import java.io.File;
 import java.io.FileDescriptor;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.lang.reflect.Array;
@@ -100,11 +106,7 @@
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.List;
 import java.util.NoSuchElementException;
-import java.util.Set;
-
-import libcore.io.IoUtils;
 
 /** {@hide} */
 public class NotificationManagerService extends SystemService {
@@ -115,6 +117,7 @@
 
     // message codes
     static final int MESSAGE_TIMEOUT = 2;
+    static final int MESSAGE_SAVE_POLICY_FILE = 3;
 
     static final int LONG_DELAY = 3500; // 3.5 seconds
     static final int SHORT_DELAY = 2000; // 2 seconds
@@ -137,8 +140,6 @@
     static final boolean ENABLE_BLOCKED_NOTIFICATIONS = true;
     static final boolean ENABLE_BLOCKED_TOASTS = true;
 
-    static final String ENABLED_NOTIFICATION_LISTENERS_SEPARATOR = ":";
-
     private IActivityManager mAm;
     AudioManager mAudioManager;
     StatusBarManagerInternal mStatusBar;
@@ -179,19 +180,6 @@
 
     private AppOpsManager mAppOps;
 
-    // contains connections to all connected listeners, including app services
-    // and system listeners
-    private ArrayList<NotificationListenerInfo> mListeners
-            = new ArrayList<NotificationListenerInfo>();
-    // things that will be put into mListeners as soon as they're ready
-    private ArrayList<String> mServicesBinding = new ArrayList<String>();
-    // lists the component names of all enabled (and therefore connected) listener
-    // app services for current profiles.
-    private HashSet<ComponentName> mEnabledListenersForCurrentProfiles
-            = new HashSet<ComponentName>();
-    // Just the packages from mEnabledListenersForCurrentProfiles
-    private HashSet<String> mEnabledListenerPackageNames = new HashSet<String>();
-
     // Notification control database. For now just contains disabled packages.
     private AtomicFile mPolicyFile;
     private HashSet<String> mBlockedPackages = new HashSet<String>();
@@ -207,22 +195,14 @@
 
     final ArrayList<NotificationScorer> mScorers = new ArrayList<NotificationScorer>();
 
+    private final UserProfiles mUserProfiles = new UserProfiles();
+    private NotificationListeners mListeners;
+    private ConditionProviders mConditionProviders;
+
     private final NotificationUsageStats mUsageStats = new NotificationUsageStats();
 
-    private int mZenMode;
-    // temporary, until we update apps to provide metadata
-    private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
-            "com.google.android.dialer",
-            "com.android.phone"
-            ));
-    private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
-            "com.google.android.deskclock"
-            ));
     private static final String EXTRA_INTERCEPT = "android.intercept";
 
-    // Profiles of the current user.
-    final protected SparseArray<UserInfo> mCurrentProfiles = new SparseArray<UserInfo>();
-
     private static final int MY_UID = Process.myUid();
     private static final int MY_PID = Process.myPid();
     private static final int REASON_DELEGATE_CLICK = 1;
@@ -237,85 +217,6 @@
     private static final int REASON_LISTENER_CANCEL = 10;
     private static final int REASON_LISTENER_CANCEL_ALL = 11;
 
-    private class NotificationListenerInfo implements IBinder.DeathRecipient {
-        INotificationListener listener;
-        ComponentName component;
-        int userid;
-        boolean isSystem;
-        ServiceConnection connection;
-        int targetSdkVersion;
-
-        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
-                int userid, boolean isSystem, int targetSdkVersion) {
-            this.listener = listener;
-            this.component = component;
-            this.userid = userid;
-            this.isSystem = isSystem;
-            this.connection = null;
-            this.targetSdkVersion = targetSdkVersion;
-        }
-
-        public NotificationListenerInfo(INotificationListener listener, ComponentName component,
-                int userid, ServiceConnection connection, int targetSdkVersion) {
-            this.listener = listener;
-            this.component = component;
-            this.userid = userid;
-            this.isSystem = false;
-            this.connection = connection;
-            this.targetSdkVersion = targetSdkVersion;
-        }
-
-        boolean enabledAndUserMatches(StatusBarNotification sbn) {
-            final int nid = sbn.getUserId();
-            if (!isEnabledForCurrentProfiles()) {
-                return false;
-            }
-            if (this.userid == UserHandle.USER_ALL) return true;
-            if (nid == UserHandle.USER_ALL || nid == this.userid) return true;
-            return supportsProfiles() && isCurrentProfile(nid);
-        }
-
-        boolean supportsProfiles() {
-            return targetSdkVersion >= Build.VERSION_CODES.L;
-        }
-
-        public void notifyPostedIfUserMatch(StatusBarNotification sbn) {
-            if (!enabledAndUserMatches(sbn)) {
-                return;
-            }
-            try {
-                listener.onNotificationPosted(sbn);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
-            }
-        }
-
-        public void notifyRemovedIfUserMatch(StatusBarNotification sbn) {
-            if (!enabledAndUserMatches(sbn)) return;
-            try {
-                listener.onNotificationRemoved(sbn);
-            } catch (RemoteException ex) {
-                Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
-            }
-        }
-
-        @Override
-        public void binderDied() {
-            // Remove the listener, but don't unbind from the service. The system will bring the
-            // service back up, and the onServiceConnected handler will readd the listener with the
-            // new binding. If this isn't a bound service, and is just a registered
-            // INotificationListener, just removing it from the list is all we need to do anyway.
-            removeListenerImpl(this.listener, this.userid);
-        }
-
-        /** convenience method for looking in mEnabledListenersForCurrentProfiles */
-        public boolean isEnabledForCurrentProfiles() {
-            if (this.isSystem) return true;
-            if (this.connection == null) return false;
-            return mEnabledListenersForCurrentProfiles.contains(this.component);
-        }
-    }
-
     private static class Archive {
         static final int BUFFER_SIZE = 250;
         ArrayDeque<StatusBarNotification> mBuffer = new ArrayDeque<StatusBarNotification>(BUFFER_SIZE);
@@ -421,53 +322,82 @@
 
     Archive mArchive = new Archive();
 
-    private void loadBlockDb() {
-        synchronized(mBlockedPackages) {
-            if (mPolicyFile == null) {
-                File dir = new File("/data/system");
-                mPolicyFile = new AtomicFile(new File(dir, "notification_policy.xml"));
+    private void loadPolicyFile() {
+        synchronized(mPolicyFile) {
+            mBlockedPackages.clear();
 
-                mBlockedPackages.clear();
+            FileInputStream infile = null;
+            try {
+                infile = mPolicyFile.openRead();
+                final XmlPullParser parser = Xml.newPullParser();
+                parser.setInput(infile, null);
 
-                FileInputStream infile = null;
-                try {
-                    infile = mPolicyFile.openRead();
-                    final XmlPullParser parser = Xml.newPullParser();
-                    parser.setInput(infile, null);
-
-                    int type;
-                    String tag;
-                    int version = DB_VERSION;
-                    while ((type = parser.next()) != END_DOCUMENT) {
-                        tag = parser.getName();
-                        if (type == START_TAG) {
-                            if (TAG_BODY.equals(tag)) {
-                                version = Integer.parseInt(
-                                        parser.getAttributeValue(null, ATTR_VERSION));
-                            } else if (TAG_BLOCKED_PKGS.equals(tag)) {
-                                while ((type = parser.next()) != END_DOCUMENT) {
-                                    tag = parser.getName();
-                                    if (TAG_PACKAGE.equals(tag)) {
-                                        mBlockedPackages.add(
-                                                parser.getAttributeValue(null, ATTR_NAME));
-                                    } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
-                                        break;
-                                    }
+                int type;
+                String tag;
+                int version = DB_VERSION;
+                while ((type = parser.next()) != END_DOCUMENT) {
+                    tag = parser.getName();
+                    if (type == START_TAG) {
+                        if (TAG_BODY.equals(tag)) {
+                            version = Integer.parseInt(
+                                    parser.getAttributeValue(null, ATTR_VERSION));
+                        } else if (TAG_BLOCKED_PKGS.equals(tag)) {
+                            while ((type = parser.next()) != END_DOCUMENT) {
+                                tag = parser.getName();
+                                if (TAG_PACKAGE.equals(tag)) {
+                                    mBlockedPackages.add(
+                                            parser.getAttributeValue(null, ATTR_NAME));
+                                } else if (TAG_BLOCKED_PKGS.equals(tag) && type == END_TAG) {
+                                    break;
                                 }
                             }
                         }
                     }
-                } catch (FileNotFoundException e) {
-                    // No data yet
-                } catch (IOException e) {
-                    Log.wtf(TAG, "Unable to read blocked notifications database", e);
-                } catch (NumberFormatException e) {
-                    Log.wtf(TAG, "Unable to parse blocked notifications database", e);
-                } catch (XmlPullParserException e) {
-                    Log.wtf(TAG, "Unable to parse blocked notifications database", e);
-                } finally {
-                    IoUtils.closeQuietly(infile);
+                    mZenModeHelper.readXml(parser);
                 }
+            } catch (FileNotFoundException e) {
+                // No data yet
+            } catch (IOException e) {
+                Log.wtf(TAG, "Unable to read notification policy", e);
+            } catch (NumberFormatException e) {
+                Log.wtf(TAG, "Unable to parse notification policy", e);
+            } catch (XmlPullParserException e) {
+                Log.wtf(TAG, "Unable to parse notification policy", e);
+            } finally {
+                IoUtils.closeQuietly(infile);
+            }
+        }
+    }
+
+    public void savePolicyFile() {
+        mHandler.removeMessages(MESSAGE_SAVE_POLICY_FILE);
+        mHandler.sendEmptyMessage(MESSAGE_SAVE_POLICY_FILE);
+    }
+
+    private void handleSavePolicyFile() {
+        Slog.d(TAG, "handleSavePolicyFile");
+        synchronized (mPolicyFile) {
+            final FileOutputStream stream;
+            try {
+                stream = mPolicyFile.startWrite();
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed to save policy file", e);
+                return;
+            }
+
+            try {
+                final XmlSerializer out = new FastXmlSerializer();
+                out.setOutput(stream, "utf-8");
+                out.startDocument(null, true);
+                out.startTag(null, TAG_BODY);
+                out.attribute(null, ATTR_VERSION, Integer.toString(DB_VERSION));
+                mZenModeHelper.writeXml(out);
+                out.endTag(null, TAG_BODY);
+                out.endDocument();
+                mPolicyFile.finishWrite(stream);
+            } catch (IOException e) {
+                Slog.w(TAG, "Failed to save policy file, restoring backup", e);
+                mPolicyFile.failWrite(stream);
             }
         }
     }
@@ -511,328 +441,6 @@
     }
 
 
-    /**
-     * Remove notification access for any services that no longer exist.
-     */
-    void disableNonexistentListeners() {
-        int[] userIds = getCurrentProfileIds();
-        final int N = userIds.length;
-        for (int i = 0 ; i < N; ++i) {
-            disableNonexistentListeners(userIds[i]);
-        }
-    }
-
-    void disableNonexistentListeners(int userId) {
-        String flatIn = Settings.Secure.getStringForUser(
-                getContext().getContentResolver(),
-                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                userId);
-        if (!TextUtils.isEmpty(flatIn)) {
-            if (DBG) Slog.v(TAG, "flat before: " + flatIn);
-            PackageManager pm = getContext().getPackageManager();
-            List<ResolveInfo> installedServices = pm.queryIntentServicesAsUser(
-                    new Intent(NotificationListenerService.SERVICE_INTERFACE),
-                    PackageManager.GET_SERVICES | PackageManager.GET_META_DATA,
-                    userId);
-
-            Set<ComponentName> installed = new HashSet<ComponentName>();
-            for (int i = 0, count = installedServices.size(); i < count; i++) {
-                ResolveInfo resolveInfo = installedServices.get(i);
-                ServiceInfo info = resolveInfo.serviceInfo;
-
-                if (!android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE.equals(
-                                info.permission)) {
-                    Slog.w(TAG, "Skipping notification listener service "
-                            + info.packageName + "/" + info.name
-                            + ": it does not require the permission "
-                            + android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
-                    continue;
-                }
-                installed.add(new ComponentName(info.packageName, info.name));
-            }
-
-            String flatOut = "";
-            if (!installed.isEmpty()) {
-                String[] enabled = flatIn.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
-                ArrayList<String> remaining = new ArrayList<String>(enabled.length);
-                for (int i = 0; i < enabled.length; i++) {
-                    ComponentName enabledComponent = ComponentName.unflattenFromString(enabled[i]);
-                    if (installed.contains(enabledComponent)) {
-                        remaining.add(enabled[i]);
-                    }
-                }
-                flatOut = TextUtils.join(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR, remaining);
-            }
-            if (DBG) Slog.v(TAG, "flat after: " + flatOut);
-            if (!flatIn.equals(flatOut)) {
-                Settings.Secure.putStringForUser(getContext().getContentResolver(),
-                        Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                        flatOut, userId);
-            }
-        }
-    }
-
-    /**
-     * Called whenever packages change, the user switches, or ENABLED_NOTIFICATION_LISTENERS
-     * is altered. (For example in response to USER_SWITCHED in our broadcast receiver)
-     */
-    void rebindListenerServices() {
-        final int[] userIds = getCurrentProfileIds();
-        final int nUserIds = userIds.length;
-
-        final SparseArray<String> flat = new SparseArray<String>();
-
-        for (int i = 0; i < nUserIds; ++i) {
-            flat.put(userIds[i], Settings.Secure.getStringForUser(
-                    getContext().getContentResolver(),
-                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                    userIds[i]));
-        }
-
-        NotificationListenerInfo[] toRemove = new NotificationListenerInfo[mListeners.size()];
-        final SparseArray<ArrayList<ComponentName>> toAdd
-                = new SparseArray<ArrayList<ComponentName>>();
-
-        synchronized (mNotificationList) {
-            // unbind and remove all existing listeners
-            toRemove = mListeners.toArray(toRemove);
-
-            final HashSet<ComponentName> newEnabled = new HashSet<ComponentName>();
-            final HashSet<String> newPackages = new HashSet<String>();
-
-            for (int i = 0; i < nUserIds; ++i) {
-                final ArrayList<ComponentName> add = new ArrayList<ComponentName>();
-                toAdd.put(userIds[i], add);
-
-                // decode the list of components
-                String toDecode = flat.get(userIds[i]);
-                if (toDecode != null) {
-                    String[] components = toDecode.split(ENABLED_NOTIFICATION_LISTENERS_SEPARATOR);
-                    for (int j = 0; j < components.length; j++) {
-                        final ComponentName component
-                                = ComponentName.unflattenFromString(components[j]);
-                        if (component != null) {
-                            newEnabled.add(component);
-                            add.add(component);
-                            newPackages.add(component.getPackageName());
-                        }
-                    }
-
-                }
-            }
-            mEnabledListenersForCurrentProfiles = newEnabled;
-            mEnabledListenerPackageNames = newPackages;
-        }
-
-        for (NotificationListenerInfo info : toRemove) {
-            final ComponentName component = info.component;
-            final int oldUser = info.userid;
-            Slog.v(TAG, "disabling notification listener for user "
-                    + oldUser + ": " + component);
-            unregisterListenerService(component, info.userid);
-        }
-
-        for (int i = 0; i < nUserIds; ++i) {
-            final ArrayList<ComponentName> add = toAdd.get(userIds[i]);
-            final int N = add.size();
-            for (int j = 0; j < N; j++) {
-                final ComponentName component = add.get(j);
-                Slog.v(TAG, "enabling notification listener for user " + userIds[i] + ": "
-                        + component);
-                registerListenerService(component, userIds[i]);
-            }
-        }
-    }
-
-
-    /**
-     * Version of registerListener that takes the name of a
-     * {@link android.service.notification.NotificationListenerService} to bind to.
-     *
-     * This is the mechanism by which third parties may subscribe to notifications.
-     */
-    private void registerListenerService(final ComponentName name, final int userid) {
-        checkCallerIsSystem();
-
-        if (DBG) Slog.v(TAG, "registerListenerService: " + name + " u=" + userid);
-
-        synchronized (mNotificationList) {
-            final String servicesBindingTag = name.toString() + "/" + userid;
-            if (mServicesBinding.contains(servicesBindingTag)) {
-                // stop registering this thing already! we're working on it
-                return;
-            }
-            mServicesBinding.add(servicesBindingTag);
-
-            final int N = mListeners.size();
-            for (int i=N-1; i>=0; i--) {
-                final NotificationListenerInfo info = mListeners.get(i);
-                if (name.equals(info.component)
-                        && info.userid == userid) {
-                    // cut old connections
-                    if (DBG) Slog.v(TAG, "    disconnecting old listener: " + info.listener);
-                    mListeners.remove(i);
-                    if (info.connection != null) {
-                        getContext().unbindService(info.connection);
-                    }
-                }
-            }
-
-            Intent intent = new Intent(NotificationListenerService.SERVICE_INTERFACE);
-            intent.setComponent(name);
-
-            intent.putExtra(Intent.EXTRA_CLIENT_LABEL,
-                    R.string.notification_listener_binding_label);
-
-            final PendingIntent pendingIntent = PendingIntent.getActivity(
-                    getContext(), 0, new Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS), 0);
-            intent.putExtra(Intent.EXTRA_CLIENT_INTENT, pendingIntent);
-
-            ApplicationInfo appInfo = null;
-            try {
-                appInfo = getContext().getPackageManager().getApplicationInfo(
-                        name.getPackageName(), 0);
-            } catch (NameNotFoundException e) {
-                // Ignore if the package doesn't exist we won't be able to bind to the service.
-            }
-            final int targetSdkVersion =
-                    appInfo != null ? appInfo.targetSdkVersion : Build.VERSION_CODES.BASE;
-
-            try {
-                if (DBG) Slog.v(TAG, "binding: " + intent);
-                if (!getContext().bindServiceAsUser(intent,
-                        new ServiceConnection() {
-                            INotificationListener mListener;
-
-                            @Override
-                            public void onServiceConnected(ComponentName name, IBinder service) {
-                                boolean added = false;
-                                synchronized (mNotificationList) {
-                                    mServicesBinding.remove(servicesBindingTag);
-                                    try {
-                                        mListener = INotificationListener.Stub.asInterface(service);
-                                        NotificationListenerInfo info
-                                                = new NotificationListenerInfo(
-                                                        mListener, name, userid, this,
-                                                        targetSdkVersion);
-                                        service.linkToDeath(info, 0);
-                                        added = mListeners.add(info);
-                                    } catch (RemoteException e) {
-                                        // already dead
-                                    }
-                                }
-                                if (added) {
-                                    final String[] keys =
-                                            getActiveNotificationKeysFromListener(mListener);
-                                    try {
-                                        mListener.onListenerConnected(keys);
-                                    } catch (RemoteException e) {
-                                        // we tried
-                                    }
-                                }
-                            }
-
-                            @Override
-                            public void onServiceDisconnected(ComponentName name) {
-                                Slog.v(TAG, "notification listener connection lost: " + name);
-                            }
-                        },
-                        Context.BIND_AUTO_CREATE,
-                        new UserHandle(userid)))
-                {
-                    mServicesBinding.remove(servicesBindingTag);
-                    Slog.w(TAG, "Unable to bind listener service: " + intent);
-                    return;
-                }
-            } catch (SecurityException ex) {
-                Slog.e(TAG, "Unable to bind listener service: " + intent, ex);
-                return;
-            }
-        }
-    }
-
-
-    /**
-     * Remove a listener service for the given user by ComponentName
-     */
-    private void unregisterListenerService(ComponentName name, int userid) {
-        checkCallerIsSystem();
-
-        synchronized (mNotificationList) {
-            final int N = mListeners.size();
-            for (int i=N-1; i>=0; i--) {
-                final NotificationListenerInfo info = mListeners.get(i);
-                if (name.equals(info.component)
-                        && info.userid == userid) {
-                    mListeners.remove(i);
-                    if (info.connection != null) {
-                        try {
-                            getContext().unbindService(info.connection);
-                        } catch (IllegalArgumentException ex) {
-                            // something happened to the service: we think we have a connection
-                            // but it's bogus.
-                            Slog.e(TAG, "Listener " + name + " could not be unbound: " + ex);
-                        }
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * asynchronously notify all listeners about a new notification
-     */
-    void notifyPostedLocked(NotificationRecord n) {
-        // make a copy in case changes are made to the underlying Notification object
-        final StatusBarNotification sbn = n.sbn.clone();
-        for (final NotificationListenerInfo info : mListeners) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    info.notifyPostedIfUserMatch(sbn);
-                }});
-        }
-    }
-
-    /**
-     * asynchronously notify all listeners about a removed notification
-     */
-    void notifyRemovedLocked(NotificationRecord n) {
-        // make a copy in case changes are made to the underlying Notification object
-        // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the notification
-        final StatusBarNotification sbn_light = n.sbn.cloneLight();
-
-        for (final NotificationListenerInfo info : mListeners) {
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    info.notifyRemovedIfUserMatch(sbn_light);
-                }});
-        }
-    }
-
-    // -- APIs to support listeners clicking/clearing notifications --
-
-    private void checkNullListener(INotificationListener listener) {
-        if (listener == null) {
-            throw new IllegalArgumentException("Listener must not be null");
-        }
-    }
-
-    private NotificationListenerInfo checkListenerTokenLocked(INotificationListener listener) {
-        checkNullListener(listener);
-        final IBinder token = listener.asBinder();
-        final int N = mListeners.size();
-        for (int i=0; i<N; i++) {
-            final NotificationListenerInfo info = mListeners.get(i);
-            if (info.listener.asBinder() == token) return info;
-        }
-        throw new SecurityException("Disallowed call from unknown listener: " + listener);
-    }
-
-
-
-    // -- end of listener APIs --
 
     public static final class NotificationRecord
     {
@@ -1066,10 +674,17 @@
 
         @Override
         public boolean allowDisable(int what, IBinder token, String pkg) {
-            if (isCall(pkg, null)) {
-                return mZenMode == Settings.Global.ZEN_MODE_OFF;
-            }
-            return true;
+            return mZenModeHelper.allowDisable(what, token, pkg);
+        }
+
+        @Override
+        public void onNotificationVisibilityChanged(
+                String[] newlyVisibleKeys, String[] noLongerVisibleKeys) {
+            // Using ';' as separator since eventlogs uses ',' to separate
+            // args.
+            EventLogTags.writeNotificationVisibilityChanged(
+                    TextUtils.join(";", newlyVisibleKeys),
+                    TextUtils.join(";", noLongerVisibleKeys));
         }
     };
 
@@ -1092,7 +707,7 @@
                 String pkgList[] = null;
                 boolean queryReplace = queryRemove &&
                         intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
-                if (DBG) Slog.i(TAG, "queryReplace=" + queryReplace);
+                if (DBG) Slog.i(TAG, "action=" + action + " queryReplace=" + queryReplace);
                 if (action.equals(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
                 } else if (queryRestart) {
@@ -1126,28 +741,16 @@
                     pkgList = new String[]{pkgName};
                 }
 
-                boolean anyListenersInvolved = false;
                 if (pkgList != null && (pkgList.length > 0)) {
                     for (String pkgName : pkgList) {
                         if (cancelNotifications) {
                             cancelAllNotificationsInt(MY_UID, MY_PID, pkgName, 0, 0, !queryRestart,
                                     UserHandle.USER_ALL, REASON_PACKAGE_CHANGED, null);
                         }
-                        if (mEnabledListenerPackageNames.contains(pkgName)) {
-                            anyListenersInvolved = true;
-                        }
                     }
                 }
-
-                if (anyListenersInvolved) {
-                    // if we're not replacing a package, clean up orphaned bits
-                    if (!queryReplace) {
-                        disableNonexistentListeners();
-                    }
-                    // make sure we're still bound to any of our
-                    // listeners who may have just upgraded
-                    rebindListenerServices();
-                }
+                mListeners.onPackagesChanged(queryReplace, pkgList);
+                mConditionProviders.onPackagesChanged(queryReplace, pkgList);
             } else if (action.equals(Intent.ACTION_SCREEN_ON)) {
                 // Keep track of screen on/off state, but do not turn off the notification light
                 // until user passes through the lock screen or views the notification.
@@ -1170,9 +773,9 @@
             } else if (action.equals(Intent.ACTION_USER_SWITCHED)) {
                 // reload per-user settings
                 mSettingsObserver.update(null);
-                updateCurrentProfilesCache(context);
+                mUserProfiles.updateCache(context);
             } else if (action.equals(Intent.ACTION_USER_ADDED)) {
-                updateCurrentProfilesCache(context);
+                mUserProfiles.updateCache(context);
             }
         }
     };
@@ -1181,12 +784,6 @@
         private final Uri NOTIFICATION_LIGHT_PULSE_URI
                 = Settings.System.getUriFor(Settings.System.NOTIFICATION_LIGHT_PULSE);
 
-        private final Uri ENABLED_NOTIFICATION_LISTENERS_URI
-                = Settings.Secure.getUriFor(Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
-
-        private final Uri ZEN_MODE
-                = Settings.Global.getUriFor(Settings.Global.ZEN_MODE);
-
         SettingsObserver(Handler handler) {
             super(handler);
         }
@@ -1195,10 +792,6 @@
             ContentResolver resolver = getContext().getContentResolver();
             resolver.registerContentObserver(NOTIFICATION_LIGHT_PULSE_URI,
                     false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(ENABLED_NOTIFICATION_LISTENERS_URI,
-                    false, this, UserHandle.USER_ALL);
-            resolver.registerContentObserver(ZEN_MODE,
-                    false, this);
             update(null);
         }
 
@@ -1216,16 +809,11 @@
                     updateNotificationPulse();
                 }
             }
-            if (uri == null || ENABLED_NOTIFICATION_LISTENERS_URI.equals(uri)) {
-                rebindListenerServices();
-            }
-            if (ZEN_MODE.equals(uri)) {
-                updateZenMode();
-            }
         }
     }
 
     private SettingsObserver mSettingsObserver;
+    private ZenModeHelper mZenModeHelper;
 
     static long[] getLongArray(Resources r, int resid, int maxlen, long[] def) {
         int[] ar = r.getIntArray(resid);
@@ -1251,9 +839,21 @@
         mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
 
         mHandler = new WorkerHandler();
+        mZenModeHelper = new ZenModeHelper(getContext(), mHandler);
+        mZenModeHelper.addCallback(new ZenModeHelper.Callback() {
+            @Override
+            public void onConfigChanged() {
+                savePolicyFile();
+            }
+        });
+        final File systemDir = new File(Environment.getDataDirectory(), "system");
+        mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
 
         importOldBlockDb();
 
+        mListeners = new NotificationListeners();
+        mConditionProviders = new ConditionProviders(getContext(),
+                mHandler, mUserProfiles, mZenModeHelper);
         mStatusBar = getLocalService(StatusBarManagerInternal.class);
         mStatusBar.setNotificationDelegate(mNotificationDelegate);
 
@@ -1287,9 +887,9 @@
                     Settings.Global.DEVICE_PROVISIONED, 0)) {
             mDisableNotificationAlerts = true;
         }
-        updateZenMode();
+        mZenModeHelper.updateZenMode();
 
-        updateCurrentProfilesCache(getContext());
+        mUserProfiles.updateCache(getContext());
 
         // register for various Intents
         IntentFilter filter = new IntentFilter();
@@ -1340,7 +940,7 @@
      * Read the old XML-based app block database and import those blockages into the AppOps system.
      */
     private void importOldBlockDb() {
-        loadBlockDb();
+        loadPolicyFile();
 
         PackageManager pm = getContext().getPackageManager();
         for (String pkg : mBlockedPackages) {
@@ -1353,9 +953,6 @@
             }
         }
         mBlockedPackages.clear();
-        if (mPolicyFile != null) {
-            mPolicyFile.delete();
-        }
     }
 
     @Override
@@ -1371,6 +968,8 @@
             // This observer will force an update when observe is called, causing us to
             // bind to listener services.
             mSettingsObserver.observe();
+            mListeners.onBootPhaseAppsCanStart();
+            mConditionProviders.onBootPhaseAppsCanStart();
         }
     }
 
@@ -1487,9 +1086,9 @@
         }
 
         @Override
-        public void enqueueNotificationWithTag(String pkg, String basePkg, String tag, int id,
+        public void enqueueNotificationWithTag(String pkg, String opPkg, String tag, int id,
                 Notification notification, int[] idOut, int userId) throws RemoteException {
-            enqueueNotificationInternal(pkg, basePkg, Binder.getCallingUid(),
+            enqueueNotificationInternal(pkg, opPkg, Binder.getCallingUid(),
                     Binder.getCallingPid(), tag, id, notification, idOut, userId);
         }
 
@@ -1600,8 +1199,7 @@
         public void registerListener(final INotificationListener listener,
                 final ComponentName component, final int userid) {
             checkCallerIsSystem();
-            checkNullListener(listener);
-            registerListenerImpl(listener, component, userid);
+            mListeners.registerService(listener, component, userid);
         }
 
         /**
@@ -1609,10 +1207,7 @@
          */
         @Override
         public void unregisterListener(INotificationListener listener, int userid) {
-            checkNullListener(listener);
-            // no need to check permissions; if your listener binder is in the list,
-            // that's proof that you had permission to add it in the first place
-            unregisterListenerImpl(listener, userid);
+            mListeners.unregisterService(listener, userid);
         }
 
         /**
@@ -1629,16 +1224,16 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                     if (keys != null) {
                         final int N = keys.length;
                         for (int i = 0; i < N; i++) {
                             NotificationRecord r = mNotificationsByKey.get(keys[i]);
                             final int userId = r.sbn.getUserId();
                             if (userId != info.userid && userId != UserHandle.USER_ALL &&
-                                    !isCurrentProfile(userId)) {
+                                    !mUserProfiles.isCurrentProfile(userId)) {
                                 throw new SecurityException("Disallowed call from listener: "
-                                        + info.listener);
+                                        + info.service);
                             }
                             if (r != null) {
                                 cancelNotificationFromListenerLocked(info, callingUid, callingPid,
@@ -1656,7 +1251,7 @@
             }
         }
 
-        private void cancelNotificationFromListenerLocked(NotificationListenerInfo info,
+        private void cancelNotificationFromListenerLocked(ManagedServiceInfo info,
                 int callingUid, int callingPid, String pkg, String tag, int id, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
                     Notification.FLAG_ONGOING_EVENT | Notification.FLAG_FOREGROUND_SERVICE,
@@ -1679,7 +1274,7 @@
             long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mNotificationList) {
-                    final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                     if (info.supportsProfiles()) {
                         Log.e(TAG, "Ignoring deprecated cancelNotification(pkg, tag, id) "
                                 + "from " + info.component
@@ -1705,14 +1300,14 @@
         public StatusBarNotification[] getActiveNotificationsFromListener(
                 INotificationListener token, String[] keys) {
             synchronized (mNotificationList) {
-                final NotificationListenerInfo info = checkListenerTokenLocked(token);
+                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                 final ArrayList<StatusBarNotification> list
                         = new ArrayList<StatusBarNotification>();
                 if (keys == null) {
                     final int N = mNotificationList.size();
                     for (int i=0; i<N; i++) {
                         StatusBarNotification sbn = mNotificationList.get(i).sbn;
-                        if (info.enabledAndUserMatches(sbn)) {
+                        if (info.enabledAndUserMatches(sbn.getUserId())) {
                             list.add(sbn);
                         }
                     }
@@ -1720,7 +1315,7 @@
                     final int N = keys.length;
                     for (int i=0; i<N; i++) {
                         NotificationRecord r = mNotificationsByKey.get(keys[i]);
-                        if (r != null && info.enabledAndUserMatches(r.sbn)) {
+                        if (r != null && info.enabledAndUserMatches(r.sbn.getUserId())) {
                             list.add(r.sbn);
                         }
                     }
@@ -1735,6 +1330,49 @@
         }
 
         @Override
+        public ZenModeConfig getZenModeConfig() {
+            checkCallerIsSystem();
+            return mZenModeHelper.getConfig();
+        }
+
+        @Override
+        public boolean setZenModeConfig(ZenModeConfig config) {
+            checkCallerIsSystem();
+            return mZenModeHelper.setConfig(config);
+        }
+
+        @Override
+        public void notifyConditions(String pkg, IConditionProvider provider,
+                Condition[] conditions) {
+            final ManagedServiceInfo info = mConditionProviders.checkServiceToken(provider);
+            checkCallerIsSystemOrSameApp(pkg);
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                mConditionProviders.notifyConditions(pkg, info, conditions);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void requestZenModeConditions(IConditionListener callback, boolean requested) {
+            enforceSystemOrSystemUI("INotificationManager.requestZenModeConditions");
+            mConditionProviders.requestZenModeConditions(callback, requested);
+        }
+
+        @Override
+        public void setZenModeCondition(Uri conditionId) {
+            enforceSystemOrSystemUI("INotificationManager.setZenModeCondition");
+            mConditionProviders.setZenModeCondition(conditionId);
+        }
+
+        private void enforceSystemOrSystemUI(String message) {
+            if (isCallerSystem()) return;
+            getContext().enforceCallingPermission(android.Manifest.permission.STATUS_BAR_SERVICE,
+                    message);
+        }
+
+        @Override
         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
                     != PackageManager.PERMISSION_GRANTED) {
@@ -1750,12 +1388,12 @@
 
     private String[] getActiveNotificationKeysFromListener(INotificationListener token) {
         synchronized (mNotificationList) {
-            final NotificationListenerInfo info = checkListenerTokenLocked(token);
+            final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
             final ArrayList<String> keys = new ArrayList<String>();
             final int N = mNotificationList.size();
             for (int i=0; i<N; i++) {
                 final StatusBarNotification sbn = mNotificationList.get(i).sbn;
-                if (info.enabledAndUserMatches(sbn)) {
+                if (info.enabledAndUserMatches(sbn.getUserId())) {
                     keys.add(sbn.getKey());
                 }
             }
@@ -1766,19 +1404,6 @@
     void dumpImpl(PrintWriter pw) {
         pw.println("Current Notification Manager state:");
 
-        pw.println("  Listeners (" + mEnabledListenersForCurrentProfiles.size()
-                + ") enabled for current profiles:");
-        for (ComponentName cmpt : mEnabledListenersForCurrentProfiles) {
-            pw.println("    " + cmpt);
-        }
-
-        pw.println("  Live listeners (" + mListeners.size() + "):");
-        for (NotificationListenerInfo info : mListeners) {
-            pw.println("    " + info.component
-                    + " (user " + info.userid + "): " + info.listener
-                    + (info.isSystem?" SYSTEM":""));
-        }
-
         int N;
 
         synchronized (mToastQueue) {
@@ -1815,7 +1440,6 @@
             pw.println("  mSoundNotification=" + mSoundNotification);
             pw.println("  mVibrateNotification=" + mVibrateNotification);
             pw.println("  mDisableNotificationAlerts=" + mDisableNotificationAlerts);
-            pw.println("  mZenMode=" + Settings.Global.zenModeToString(mZenMode));
             pw.println("  mSystemReady=" + mSystemReady);
             pw.println("  mArchive=" + mArchive.toString());
             Iterator<StatusBarNotification> iter = mArchive.descendingIterator();
@@ -1831,6 +1455,14 @@
             pw.println("\n  Usage Stats:");
             mUsageStats.dump(pw, "    ");
 
+            pw.println("\n  Zen Mode:");
+            mZenModeHelper.dump(pw, "    ");
+
+            pw.println("\n  Notification listeners:");
+            mListeners.dump(pw);
+
+            pw.println("\n  Condition providers:");
+            mConditionProviders.dump(pw);
         }
     }
 
@@ -1839,14 +1471,14 @@
      */
     private final NotificationManagerInternal mInternalService = new NotificationManagerInternal() {
         @Override
-        public void enqueueNotification(String pkg, String basePkg, int callingUid, int callingPid,
+        public void enqueueNotification(String pkg, String opPkg, int callingUid, int callingPid,
                 String tag, int id, Notification notification, int[] idReceived, int userId) {
-            enqueueNotificationInternal(pkg, basePkg, callingUid, callingPid, tag, id, notification,
+            enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
                     idReceived, userId);
         }
     };
 
-    void enqueueNotificationInternal(final String pkg, String basePkg, final int callingUid,
+    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
             final int callingPid, final String tag, final int id, final Notification notification,
             int[] idOut, int incomingUserId) {
         if (DBG) {
@@ -1963,7 +1595,7 @@
                 }
 
                 // Is this notification intercepted by zen mode?
-                final boolean intercept = shouldIntercept(pkg, notification);
+                final boolean intercept = mZenModeHelper.shouldIntercept(pkg, notification);
                 notification.extras.putBoolean(EXTRA_INTERCEPT, intercept);
 
                 // Should this notification make noise, vibe, or use the LED?
@@ -1971,7 +1603,8 @@
                 if (DBG) Slog.v(TAG, "canInterrupt=" + canInterrupt + " intercept=" + intercept);
                 synchronized (mNotificationList) {
                     final StatusBarNotification n = new StatusBarNotification(
-                            pkg, id, tag, callingUid, callingPid, score, notification, user);
+                            pkg, opPkg, id, tag, callingUid, callingPid, score, notification,
+                            user);
                     NotificationRecord r = new NotificationRecord(n);
                     NotificationRecord old = null;
 
@@ -2035,7 +1668,7 @@
                             sendAccessibilityEvent(notification, pkg);
                         }
 
-                        notifyPostedLocked(r);
+                        mListeners.notifyPostedLocked(r.sbn);
                     } else {
                         Slog.e(TAG, "Not posting notification with icon==0: " + notification);
                         if (old != null && old.statusBarKey != null) {
@@ -2046,7 +1679,7 @@
                                 Binder.restoreCallingIdentity(identity);
                             }
 
-                            notifyRemovedLocked(r);
+                            mListeners.notifyRemovedLocked(r.sbn);
                         }
                         // ATTENTION: in a future release we will bail out here
                         // so that we do not play sounds, show lights, etc. for invalid
@@ -2061,7 +1694,7 @@
                                 && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                             && (r.getUserId() == UserHandle.USER_ALL ||
                                 (r.getUserId() == userId && r.getUserId() == currentUser) ||
-                                isCurrentProfile(r.getUserId()))
+                                mUserProfiles.isCurrentProfile(r.getUserId()))
                             && canInterrupt
                             && mSystemReady
                             && mAudioManager != null) {
@@ -2147,7 +1780,7 @@
                                 // notifying app does not have the VIBRATE permission.
                                 long identity = Binder.clearCallingIdentity();
                                 try {
-                                    mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+                                    mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
                                         useDefaultVibrate ? mDefaultVibrationPattern
                                             : mFallbackVibrationPattern,
                                         ((notification.flags & Notification.FLAG_INSISTENT) != 0)
@@ -2158,7 +1791,7 @@
                             } else if (notification.vibrate.length > 1) {
                                 // If you want your own vibration pattern, you need the VIBRATE
                                 // permission
-                                mVibrator.vibrate(r.sbn.getUid(), r.sbn.getBasePkg(),
+                                mVibrator.vibrate(r.sbn.getUid(), r.sbn.getOpPkg(),
                                         notification.vibrate,
                                     ((notification.flags & Notification.FLAG_INSISTENT) != 0)
                                             ? 0: -1, notification.audioStreamType);
@@ -2192,52 +1825,6 @@
         idOut[0] = id;
     }
 
-     void registerListenerImpl(final INotificationListener listener,
-            final ComponentName component, final int userid) {
-        synchronized (mNotificationList) {
-            try {
-                NotificationListenerInfo info
-                        = new NotificationListenerInfo(listener, component, userid,
-                        /*isSystem*/ true, Build.VERSION_CODES.L);
-                listener.asBinder().linkToDeath(info, 0);
-                mListeners.add(info);
-            } catch (RemoteException e) {
-                // already dead
-            }
-        }
-    }
-
-    /**
-     * Removes a listener from the list and unbinds from its service.
-     */
-    void unregisterListenerImpl(final INotificationListener listener, final int userid) {
-        NotificationListenerInfo info = removeListenerImpl(listener, userid);
-        if (info != null && info.connection != null) {
-            getContext().unbindService(info.connection);
-        }
-    }
-
-    /**
-     * Removes a listener from the list but does not unbind from the listener's service.
-     *
-     * @return the removed listener.
-     */
-    NotificationListenerInfo removeListenerImpl(
-            final INotificationListener listener, final int userid) {
-        NotificationListenerInfo listenerInfo = null;
-        synchronized (mNotificationList) {
-            final int N = mListeners.size();
-            for (int i=N-1; i>=0; i--) {
-                final NotificationListenerInfo info = mListeners.get(i);
-                if (info.listener.asBinder() == listener.asBinder()
-                        && info.userid == userid) {
-                    listenerInfo = mListeners.remove(i);
-                }
-            }
-        }
-        return listenerInfo;
-    }
-
     void showNextToastLocked() {
         ToastRecord record = mToastQueue.get(0);
         while (record != null) {
@@ -2347,6 +1934,9 @@
                 case MESSAGE_TIMEOUT:
                     handleTimeout((ToastRecord)msg.obj);
                     break;
+                case MESSAGE_SAVE_POLICY_FILE:
+                    handleSavePolicyFile();
+                    break;
             }
         }
     }
@@ -2400,7 +1990,7 @@
                 Binder.restoreCallingIdentity(identity);
             }
             r.statusBarKey = null;
-            notifyRemovedLocked(r);
+            mListeners.notifyRemovedLocked(r.sbn);
         }
 
         // sound
@@ -2467,7 +2057,7 @@
     void cancelNotification(final int callingUid, final int callingPid,
             final String pkg, final String tag, final int id,
             final int mustHaveFlags, final int mustNotHaveFlags, final boolean sendDelete,
-            final int userId, final int reason, final NotificationListenerInfo listener) {
+            final int userId, final int reason, final ManagedServiceInfo listener) {
         // In enqueueNotificationInternal notifications are added by scheduling the
         // work on the worker handler. Hence, we also schedule the cancel on this
         // handler to avoid a scenario where an add notification call followed by a
@@ -2529,7 +2119,7 @@
      */
     private boolean notificationMatchesCurrentProfiles(NotificationRecord r, int userId) {
         return notificationMatchesUserId(r, userId)
-                || isCurrentProfile(r.getUserId());
+                || mUserProfiles.isCurrentProfile(r.getUserId());
     }
 
     /**
@@ -2538,7 +2128,7 @@
      */
     boolean cancelAllNotificationsInt(int callingUid, int callingPid, String pkg, int mustHaveFlags,
             int mustNotHaveFlags, boolean doit, int userId, int reason,
-            NotificationListenerInfo listener) {
+            ManagedServiceInfo listener) {
         EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
                 pkg, userId, mustHaveFlags, mustNotHaveFlags, reason,
                 listener == null ? null : listener.component.toShortString());
@@ -2579,46 +2169,8 @@
         }
     }
 
-
-
-    // Return true if the UID is a system or phone UID and therefore should not have
-    // any notifications or toasts blocked.
-    boolean isUidSystem(int uid) {
-        final int appid = UserHandle.getAppId(uid);
-        return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
-    }
-
-    // same as isUidSystem(int, int) for the Binder caller's UID.
-    boolean isCallerSystem() {
-        return isUidSystem(Binder.getCallingUid());
-    }
-
-    void checkCallerIsSystem() {
-        if (isCallerSystem()) {
-            return;
-        }
-        throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
-    }
-
-    void checkCallerIsSystemOrSameApp(String pkg) {
-        if (isCallerSystem()) {
-            return;
-        }
-        final int uid = Binder.getCallingUid();
-        try {
-            ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
-                    pkg, 0, UserHandle.getCallingUserId());
-            if (!UserHandle.isSameApp(ai.uid, uid)) {
-                throw new SecurityException("Calling uid " + uid + " gave package"
-                        + pkg + " which is owned by uid " + ai.uid);
-            }
-        } catch (RemoteException re) {
-            throw new SecurityException("Unknown package " + pkg + "\n" + re);
-        }
-    }
-
     void cancelAllLocked(int callingUid, int callingPid, int userId, int reason,
-            NotificationListenerInfo listener, boolean includeCurrentProfiles) {
+            ManagedServiceInfo listener, boolean includeCurrentProfiles) {
         EventLogTags.writeNotificationCancelAll(callingUid, callingPid,
                 null, userId, 0, 0, reason,
                 listener == null ? null : listener.component.toShortString());
@@ -2711,85 +2263,130 @@
         }
     }
 
-    private void updateZenMode() {
-        final int mode = Settings.Global.getInt(getContext().getContentResolver(),
-                Settings.Global.ZEN_MODE, Settings.Global.ZEN_MODE_OFF);
-        if (mode != mZenMode) {
-            Slog.d(TAG, String.format("updateZenMode: %s -> %s",
-                    Settings.Global.zenModeToString(mZenMode),
-                    Settings.Global.zenModeToString(mode)));
-        }
-        mZenMode = mode;
-
-        final String[] exceptionPackages = null; // none (for now)
-
-        // call restrictions
-        final boolean muteCalls = mZenMode != Settings.Global.ZEN_MODE_OFF;
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_RING,
-                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_RING,
-                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-
-        // alarm restrictions
-        final boolean muteAlarms = false; // TODO until we save user config
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_ALARM,
-                muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_ALARM,
-                muteAlarms ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
-
-        // restrict vibrations with no hints
-        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.USE_DEFAULT_STREAM_TYPE,
-                (muteAlarms || muteCalls) ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
-                exceptionPackages);
+    private static boolean isUidSystem(int uid) {
+        final int appid = UserHandle.getAppId(uid);
+        return (appid == Process.SYSTEM_UID || appid == Process.PHONE_UID || uid == 0);
     }
 
-    private void updateCurrentProfilesCache(Context context) {
-        UserManager userManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
-        if (userManager != null) {
-            int currentUserId = ActivityManager.getCurrentUser();
-            List<UserInfo> profiles = userManager.getProfiles(currentUserId);
-            synchronized (mCurrentProfiles) {
-                mCurrentProfiles.clear();
-                for (UserInfo user : profiles) {
-                    mCurrentProfiles.put(user.id, user);
-                }
+    private static boolean isCallerSystem() {
+        return isUidSystem(Binder.getCallingUid());
+    }
+
+    private static void checkCallerIsSystem() {
+        if (isCallerSystem()) {
+            return;
+        }
+        throw new SecurityException("Disallowed call for uid " + Binder.getCallingUid());
+    }
+
+    private static void checkCallerIsSystemOrSameApp(String pkg) {
+        if (isCallerSystem()) {
+            return;
+        }
+        final int uid = Binder.getCallingUid();
+        try {
+            ApplicationInfo ai = AppGlobals.getPackageManager().getApplicationInfo(
+                    pkg, 0, UserHandle.getCallingUserId());
+            if (!UserHandle.isSameApp(ai.uid, uid)) {
+                throw new SecurityException("Calling uid " + uid + " gave package"
+                        + pkg + " which is owned by uid " + ai.uid);
+            }
+        } catch (RemoteException re) {
+            throw new SecurityException("Unknown package " + pkg + "\n" + re);
+        }
+    }
+
+    public class NotificationListeners extends ManagedServices {
+
+        public NotificationListeners() {
+            super(getContext(), mHandler, mNotificationList, mUserProfiles);
+        }
+
+        @Override
+        protected Config getConfig() {
+            Config c = new Config();
+            c.caption = "notification listener";
+            c.serviceInterface = NotificationListenerService.SERVICE_INTERFACE;
+            c.secureSettingName = Settings.Secure.ENABLED_NOTIFICATION_LISTENERS;
+            c.bindPermission = android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
+            c.settingsAction = Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS;
+            c.clientLabel = R.string.notification_listener_binding_label;
+            return c;
+        }
+
+        @Override
+        protected IInterface asInterface(IBinder binder) {
+            return INotificationListener.Stub.asInterface(binder);
+        }
+
+        @Override
+        public void onServiceAdded(IInterface service) {
+            final INotificationListener listener = (INotificationListener) service;
+            final String[] keys = getActiveNotificationKeysFromListener(listener);
+            try {
+                listener.onListenerConnected(keys);
+            } catch (RemoteException e) {
+                // we tried
             }
         }
-    }
 
-    private int[] getCurrentProfileIds() {
-        synchronized (mCurrentProfiles) {
-            int[] users = new int[mCurrentProfiles.size()];
-            final int N = mCurrentProfiles.size();
-            for (int i = 0; i < N; ++i) {
-                users[i] = mCurrentProfiles.keyAt(i);
+        /**
+         * asynchronously notify all listeners about a new notification
+         */
+        public void notifyPostedLocked(StatusBarNotification sbn) {
+            // make a copy in case changes are made to the underlying Notification object
+            final StatusBarNotification sbnClone = sbn.clone();
+            for (final ManagedServiceInfo info : mServices) {
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        notifyPostedIfUserMatch(info, sbnClone);
+                    }
+                });
             }
-            return users;
         }
-    }
 
-    private boolean isCurrentProfile(int userId) {
-        synchronized (mCurrentProfiles) {
-            return mCurrentProfiles.get(userId) != null;
+        /**
+         * asynchronously notify all listeners about a removed notification
+         */
+        public void notifyRemovedLocked(StatusBarNotification sbn) {
+            // make a copy in case changes are made to the underlying Notification object
+            // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
+            // notification
+            final StatusBarNotification sbnLight = sbn.cloneLight();
+            for (ManagedServiceInfo serviceInfo : mServices) {
+                final ManagedServiceInfo info = (ManagedServiceInfo) serviceInfo;
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        notifyRemovedIfUserMatch(info, sbnLight);
+                    }
+                });
+            }
         }
-    }
 
-    private boolean isCall(String pkg, Notification n) {
-        return CALL_PACKAGES.contains(pkg);
-    }
-
-    private boolean isAlarm(String pkg, Notification n) {
-        return ALARM_PACKAGES.contains(pkg);
-    }
-
-    private boolean shouldIntercept(String pkg, Notification n) {
-        if (mZenMode != Settings.Global.ZEN_MODE_OFF) {
-            return !isAlarm(pkg, n);
+        private void notifyPostedIfUserMatch(ManagedServiceInfo info, StatusBarNotification sbn) {
+            if (!info.enabledAndUserMatches(sbn.getUserId())) {
+                return;
+            }
+            final INotificationListener listener = (INotificationListener)info.service;
+            try {
+                listener.onNotificationPosted(sbn);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unable to notify listener (posted): " + listener, ex);
+            }
         }
-        return false;
+
+        private void notifyRemovedIfUserMatch(ManagedServiceInfo info, StatusBarNotification sbn) {
+            if (!info.enabledAndUserMatches(sbn.getUserId())) {
+                return;
+            }
+            final INotificationListener listener = (INotificationListener)info.service;
+            try {
+                listener.onNotificationRemoved(sbn);
+            } catch (RemoteException ex) {
+                Log.e(TAG, "unable to notify listener (removed): " + listener, ex);
+            }
+        }
     }
 }
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
new file mode 100644
index 0000000..154ac96
--- /dev/null
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -0,0 +1,345 @@
+/**
+ * Copyright (c) 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.notification;
+
+import android.app.AlarmManager;
+import android.app.AppOpsManager;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.res.Resources;
+import android.content.res.XmlResourceParser;
+import android.database.ContentObserver;
+import android.media.AudioManager;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.IBinder;
+import android.provider.Settings.Global;
+import android.service.notification.ZenModeConfig;
+import android.util.Slog;
+
+import com.android.internal.R;
+
+import libcore.io.IoUtils;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * NotificationManagerService helper for functionality related to zen mode.
+ */
+public class ZenModeHelper {
+    private static final String TAG = "ZenModeHelper";
+
+    private static final String ACTION_ENTER_ZEN = "enter_zen";
+    private static final int REQUEST_CODE_ENTER = 100;
+    private static final String ACTION_EXIT_ZEN = "exit_zen";
+    private static final int REQUEST_CODE_EXIT = 101;
+    private static final String EXTRA_TIME = "time";
+
+    private final Context mContext;
+    private final Handler mHandler;
+    private final SettingsObserver mSettingsObserver;
+    private final AppOpsManager mAppOps;
+    private final ZenModeConfig mDefaultConfig;
+    private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
+
+    private int mZenMode;
+    private ZenModeConfig mConfig;
+
+    // temporary, until we update apps to provide metadata
+    private static final Set<String> CALL_PACKAGES = new HashSet<String>(Arrays.asList(
+            "com.google.android.dialer",
+            "com.android.phone"
+            ));
+    private static final Set<String> MESSAGE_PACKAGES = new HashSet<String>(Arrays.asList(
+            "com.google.android.talk",
+            "com.android.mms"
+            ));
+    private static final Set<String> ALARM_PACKAGES = new HashSet<String>(Arrays.asList(
+            "com.google.android.deskclock"
+            ));
+
+    public ZenModeHelper(Context context, Handler handler) {
+        mContext = context;
+        mHandler = handler;
+        mAppOps = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        mDefaultConfig = readDefaultConfig(context.getResources());
+        mConfig = mDefaultConfig;
+        mSettingsObserver = new SettingsObserver(mHandler);
+        mSettingsObserver.observe();
+
+        final IntentFilter filter = new IntentFilter();
+        filter.addAction(ACTION_ENTER_ZEN);
+        filter.addAction(ACTION_EXIT_ZEN);
+        mContext.registerReceiver(new ZenBroadcastReceiver(), filter);
+    }
+
+    public static ZenModeConfig readDefaultConfig(Resources resources) {
+        XmlResourceParser parser = null;
+        try {
+            parser = resources.getXml(R.xml.default_zen_mode_config);
+            while (parser.next() != XmlPullParser.END_DOCUMENT) {
+                final ZenModeConfig config = ZenModeConfig.readXml(parser);
+                if (config != null) return config;
+            }
+        } catch (Exception e) {
+            Slog.w(TAG, "Error reading default zen mode config from resource", e);
+        } finally {
+            IoUtils.closeQuietly(parser);
+        }
+        return new ZenModeConfig();
+    }
+
+    public void addCallback(Callback callback) {
+        mCallbacks.add(callback);
+    }
+
+    public boolean shouldIntercept(String pkg, Notification n) {
+        if (mZenMode != Global.ZEN_MODE_OFF) {
+            if (isAlarm(pkg, n)) {
+                return false;
+            }
+            if (isCall(pkg, n)) {
+                return !mConfig.allowCalls;
+            }
+            if (isMessage(pkg, n)) {
+                return !mConfig.allowMessages;
+            }
+            return true;
+        }
+        return false;
+    }
+
+    public int getZenMode() {
+        return mZenMode;
+    }
+
+    public void setZenMode(int zenModeValue) {
+        Global.putInt(mContext.getContentResolver(), Global.ZEN_MODE, zenModeValue);
+    }
+
+    public void updateZenMode() {
+        final int mode = Global.getInt(mContext.getContentResolver(),
+                Global.ZEN_MODE, Global.ZEN_MODE_OFF);
+        if (mode != mZenMode) {
+            Slog.d(TAG, String.format("updateZenMode: %s -> %s",
+                    Global.zenModeToString(mZenMode),
+                    Global.zenModeToString(mode)));
+        }
+        mZenMode = mode;
+        final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
+        final String[] exceptionPackages = null; // none (for now)
+
+        // call restrictions
+        final boolean muteCalls = zen && !mConfig.allowCalls;
+        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.STREAM_RING,
+                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                exceptionPackages);
+        mAppOps.setRestriction(AppOpsManager.OP_PLAY_AUDIO, AudioManager.STREAM_RING,
+                muteCalls ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                exceptionPackages);
+
+        // restrict vibrations with no hints
+        mAppOps.setRestriction(AppOpsManager.OP_VIBRATE, AudioManager.USE_DEFAULT_STREAM_TYPE,
+                zen ? AppOpsManager.MODE_IGNORED : AppOpsManager.MODE_ALLOWED,
+                exceptionPackages);
+        dispatchOnZenModeChanged();
+    }
+
+    public boolean allowDisable(int what, IBinder token, String pkg) {
+        if (isCall(pkg, null)) {
+            return mZenMode == Global.ZEN_MODE_OFF || mConfig.allowCalls;
+        }
+        return true;
+    }
+
+    public void dump(PrintWriter pw, String prefix) {
+        pw.print(prefix); pw.print("mZenMode=");
+        pw.println(Global.zenModeToString(mZenMode));
+        pw.print(prefix); pw.print("mConfig="); pw.println(mConfig);
+        pw.print(prefix); pw.print("mDefaultConfig="); pw.println(mDefaultConfig);
+    }
+
+    public void readXml(XmlPullParser parser) throws XmlPullParserException, IOException {
+        final ZenModeConfig config = ZenModeConfig.readXml(parser);
+        if (config != null) {
+            setConfig(config);
+        }
+    }
+
+    public void writeXml(XmlSerializer out) throws IOException {
+        mConfig.writeXml(out);
+    }
+
+    public ZenModeConfig getConfig() {
+        return mConfig;
+    }
+
+    public boolean setConfig(ZenModeConfig config) {
+        if (config == null || !config.isValid()) return false;
+        if (config.equals(mConfig)) return true;
+        mConfig = config;
+        Slog.d(TAG, "mConfig=" + mConfig);
+        dispatchOnConfigChanged();
+        final String val = Integer.toString(mConfig.hashCode());
+        Global.putString(mContext.getContentResolver(), Global.ZEN_MODE_CONFIG_ETAG, val);
+        updateAlarms();
+        updateZenMode();
+        return true;
+    }
+
+    private void dispatchOnConfigChanged() {
+        for (Callback callback : mCallbacks) {
+            callback.onConfigChanged();
+        }
+    }
+
+    private void dispatchOnZenModeChanged() {
+        for (Callback callback : mCallbacks) {
+            callback.onZenModeChanged();
+        }
+    }
+
+    private boolean isAlarm(String pkg, Notification n) {
+        return ALARM_PACKAGES.contains(pkg);
+    }
+
+    private boolean isCall(String pkg, Notification n) {
+        return CALL_PACKAGES.contains(pkg);
+    }
+
+    private boolean isMessage(String pkg, Notification n) {
+        return MESSAGE_PACKAGES.contains(pkg);
+    }
+
+    private void updateAlarms() {
+        updateAlarm(ACTION_ENTER_ZEN, REQUEST_CODE_ENTER,
+                mConfig.sleepStartHour, mConfig.sleepStartMinute);
+        updateAlarm(ACTION_EXIT_ZEN, REQUEST_CODE_EXIT,
+                mConfig.sleepEndHour, mConfig.sleepEndMinute);
+    }
+
+    private void updateAlarm(String action, int requestCode, int hr, int min) {
+        final AlarmManager alarms = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
+        final long now = System.currentTimeMillis();
+        final Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(now);
+        c.set(Calendar.HOUR_OF_DAY, hr);
+        c.set(Calendar.MINUTE, min);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+        if (c.getTimeInMillis() <= now) {
+            c.add(Calendar.DATE, 1);
+        }
+        final long time = c.getTimeInMillis();
+        final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, requestCode,
+                new Intent(action).putExtra(EXTRA_TIME, time), PendingIntent.FLAG_UPDATE_CURRENT);
+        alarms.cancel(pendingIntent);
+        if (mConfig.sleepMode != null) {
+            Slog.d(TAG, String.format("Scheduling %s for %s, %s in the future, now=%s",
+                    action, ts(time), time - now, ts(now)));
+            alarms.setExact(AlarmManager.RTC_WAKEUP, time, pendingIntent);
+        }
+    }
+
+    private static String ts(long time) {
+        return new Date(time) + " (" + time + ")";
+    }
+
+    public static boolean isWeekend(long time, int offsetDays) {
+        final Calendar c = Calendar.getInstance();
+        c.setTimeInMillis(time);
+        if (offsetDays != 0) {
+            c.add(Calendar.DATE, offsetDays);
+        }
+        final int day = c.get(Calendar.DAY_OF_WEEK);
+        return day == Calendar.SATURDAY || day == Calendar.SUNDAY;
+    }
+
+    private class SettingsObserver extends ContentObserver {
+        private final Uri ZEN_MODE = Global.getUriFor(Global.ZEN_MODE);
+
+        public SettingsObserver(Handler handler) {
+            super(handler);
+        }
+
+        public void observe() {
+            final ContentResolver resolver = mContext.getContentResolver();
+            resolver.registerContentObserver(ZEN_MODE, false /*notifyForDescendents*/, this);
+            update(null);
+        }
+
+        @Override
+        public void onChange(boolean selfChange, Uri uri) {
+            update(uri);
+        }
+
+        public void update(Uri uri) {
+            if (ZEN_MODE.equals(uri)) {
+                updateZenMode();
+            }
+        }
+    }
+
+    private class ZenBroadcastReceiver extends BroadcastReceiver {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (ACTION_ENTER_ZEN.equals(intent.getAction())) {
+                setZenMode(intent, 1, Global.ZEN_MODE_ON);
+            } else if (ACTION_EXIT_ZEN.equals(intent.getAction())) {
+                setZenMode(intent, 0, Global.ZEN_MODE_OFF);
+            }
+        }
+
+        private void setZenMode(Intent intent, int wkendOffsetDays, int zenModeValue) {
+            final long schTime = intent.getLongExtra(EXTRA_TIME, 0);
+            final long now = System.currentTimeMillis();
+            Slog.d(TAG, String.format("%s scheduled for %s, fired at %s, delta=%s",
+                    intent.getAction(), ts(schTime), ts(now), now - schTime));
+
+            final boolean skip = ZenModeConfig.SLEEP_MODE_WEEKNIGHTS.equals(mConfig.sleepMode) &&
+                    isWeekend(schTime, wkendOffsetDays);
+
+            if (skip) {
+                Slog.d(TAG, "Skipping zen mode update for the weekend");
+            } else {
+                ZenModeHelper.this.setZenMode(zenModeValue);
+            }
+            updateAlarms();
+        }
+    }
+
+    public static class Callback {
+        void onConfigChanged() {}
+        void onZenModeChanged() {}
+    }
+}
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentFilter.java b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
new file mode 100644
index 0000000..aba796b
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ForwardingIntentFilter.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import com.android.internal.util.XmlUtils;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+import android.content.IntentFilter;
+import android.util.Log;
+import java.io.IOException;
+import android.os.UserHandle;
+
+/**
+ * The {@link PackageManagerService} maintains some {@link ForwardingIntentFilter}s for every user.
+ * If an {@link Intent} matches the {@link ForwardingIntentFilter}, then it can be forwarded to the
+ * {@link #mUserIdDest}.
+ */
+class ForwardingIntentFilter extends IntentFilter {
+    private static final String ATTR_USER_ID_DEST = "userIdDest";
+    private static final String ATTR_FILTER = "filter";
+
+    private static final String TAG = "ForwardingIntentFilter";
+
+    // If the intent matches the IntentFilter, then it can be forwarded to this userId.
+    final int mUserIdDest;
+
+    ForwardingIntentFilter(IntentFilter filter, int userIdDest) {
+        super(filter);
+        mUserIdDest = userIdDest;
+    }
+
+    public int getUserIdDest() {
+        return mUserIdDest;
+    }
+
+    ForwardingIntentFilter(XmlPullParser parser) throws XmlPullParserException, IOException {
+        String userIdDestString = parser.getAttributeValue(null, ATTR_USER_ID_DEST);
+        if (userIdDestString == null) {
+            String msg = "Missing element under " + TAG +": " + ATTR_USER_ID_DEST + " at " +
+                    parser.getPositionDescription();
+            PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+            mUserIdDest = UserHandle.USER_NULL;
+        } else {
+            mUserIdDest = Integer.parseInt(userIdDestString);
+        }
+        int outerDepth = parser.getDepth();
+        String tagName = parser.getName();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            tagName = parser.getName();
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            } else if (type == XmlPullParser.START_TAG) {
+                if (tagName.equals(ATTR_FILTER)) {
+                    break;
+                } else {
+                    String msg = "Unknown element under " + Settings.TAG_FORWARDING_INTENT_FILTERS
+                            + ": " + tagName + " at " + parser.getPositionDescription();
+                    PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+                    XmlUtils.skipCurrentTag(parser);
+                }
+            }
+        }
+        if (tagName.equals(ATTR_FILTER)) {
+            readFromXml(parser);
+        } else {
+            String msg = "Missing element under " + TAG + ": " + ATTR_FILTER +
+                    " at " + parser.getPositionDescription();
+            PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+            XmlUtils.skipCurrentTag(parser);
+        }
+    }
+
+    public void writeToXml(XmlSerializer serializer) throws IOException {
+        serializer.attribute(null, ATTR_USER_ID_DEST, Integer.toString(mUserIdDest));
+        serializer.startTag(null, ATTR_FILTER);
+            super.writeToXml(serializer);
+        serializer.endTag(null, ATTR_FILTER);
+    }
+
+    @Override
+    public String toString() {
+        return "ForwardingIntentFilter{0x" + Integer.toHexString(System.identityHashCode(this))
+                + " " + Integer.toString(mUserIdDest) + "}";
+    }
+}
diff --git a/services/core/java/com/android/server/pm/ForwardingIntentResolver.java b/services/core/java/com/android/server/pm/ForwardingIntentResolver.java
new file mode 100644
index 0000000..1616395
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ForwardingIntentResolver.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2014, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.android.server.pm;
+
+
+import java.io.PrintWriter;
+import com.android.server.IntentResolver;
+import java.util.List;
+
+/**
+ * Used to find a list of {@link ForwardingIntentFilter}s that match an intent.
+ */
+class ForwardingIntentResolver
+        extends IntentResolver<ForwardingIntentFilter, ForwardingIntentFilter> {
+    @Override
+    protected ForwardingIntentFilter[] newArray(int size) {
+        return new ForwardingIntentFilter[size];
+    }
+
+    @Override
+    protected boolean isPackageForFilter(String packageName, ForwardingIntentFilter filter) {
+        return false;
+    }
+
+    @Override
+    protected void sortResults(List<ForwardingIntentFilter> results) {
+        //We don't sort the results
+    }
+}
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index ff816ea..82d3f53 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -211,7 +211,7 @@
         return execute(builder.toString());
     }
 
-    public int dexopt(String apkPath, int uid, boolean isPublic) {
+    public int dexopt(String apkPath, int uid, boolean isPublic, String instructionSet) {
         StringBuilder builder = new StringBuilder("dexopt");
         builder.append(' ');
         builder.append(apkPath);
@@ -219,10 +219,13 @@
         builder.append(uid);
         builder.append(isPublic ? " 1" : " 0");
         builder.append(" *");         // No pkgName arg present
+        builder.append(' ');
+        builder.append(instructionSet);
         return execute(builder.toString());
     }
 
-    public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName) {
+    public int dexopt(String apkPath, int uid, boolean isPublic, String pkgName,
+            String instructionSet) {
         StringBuilder builder = new StringBuilder("dexopt");
         builder.append(' ');
         builder.append(apkPath);
@@ -231,6 +234,8 @@
         builder.append(isPublic ? " 1" : " 0");
         builder.append(' ');
         builder.append(pkgName);
+        builder.append(' ');
+        builder.append(instructionSet);
         return execute(builder.toString());
     }
 
@@ -245,19 +250,23 @@
         return execute(builder.toString());
     }
 
-    public int movedex(String srcPath, String dstPath) {
+    public int movedex(String srcPath, String dstPath, String instructionSet) {
         StringBuilder builder = new StringBuilder("movedex");
         builder.append(' ');
         builder.append(srcPath);
         builder.append(' ');
         builder.append(dstPath);
+        builder.append(' ');
+        builder.append(instructionSet);
         return execute(builder.toString());
     }
 
-    public int rmdex(String codePath) {
+    public int rmdex(String codePath, String instructionSet) {
         StringBuilder builder = new StringBuilder("rmdex");
         builder.append(' ');
         builder.append(codePath);
+        builder.append(' ');
+        builder.append(instructionSet);
         return execute(builder.toString());
     }
 
@@ -344,7 +353,7 @@
     }
 
     public int getSizeInfo(String pkgName, int persona, String apkPath, String libDirPath,
-            String fwdLockApkPath, String asecPath, PackageStats pStats) {
+            String fwdLockApkPath, String asecPath, String instructionSet, PackageStats pStats) {
         StringBuilder builder = new StringBuilder("getsize");
         builder.append(' ');
         builder.append(pkgName);
@@ -358,6 +367,8 @@
         builder.append(fwdLockApkPath != null ? fwdLockApkPath : "!");
         builder.append(' ');
         builder.append(asecPath != null ? asecPath : "!");
+        builder.append(' ');
+        builder.append(instructionSet);
 
         String s = transaction(builder.toString());
         String res[] = s.split(" ");
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index 27c7b39..ab63c9c 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -16,14 +16,18 @@
 
 package com.android.server.pm;
 
+import android.app.AppGlobals;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
 import android.content.pm.ILauncherApps;
 import android.content.pm.IOnAppsChangedListener;
+import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageInfo;
 import android.content.pm.ResolveInfo;
 import android.content.pm.UserInfo;
 import android.graphics.Rect;
@@ -144,6 +148,7 @@
 
         final Intent mainIntent = new Intent(Intent.ACTION_MAIN, null);
         mainIntent.addCategory(Intent.CATEGORY_LAUNCHER);
+        mainIntent.setPackage(packageName);
         long ident = Binder.clearCallingIdentity();
         try {
             List<ResolveInfo> apps = mPm.queryIntentActivitiesAsUser(mainIntent, 0,
@@ -169,6 +174,34 @@
     }
 
     @Override
+    public boolean isPackageEnabled(String packageName, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot check package for unrelated profile " + user);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            PackageInfo info = pm.getPackageInfo(packageName, 0, user.getIdentifier());
+            return info != null && info.applicationInfo.enabled;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
+    public boolean isActivityEnabled(ComponentName component, UserHandle user)
+            throws RemoteException {
+        ensureInUserProfiles(user, "Cannot check component for unrelated profile " + user);
+        long ident = Binder.clearCallingIdentity();
+        try {
+            IPackageManager pm = AppGlobals.getPackageManager();
+            ActivityInfo info = pm.getActivityInfo(component, 0, user.getIdentifier());
+            return info != null && info.isEnabled();
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+    }
+
+    @Override
     public void startActivityAsUser(ComponentName component, Rect sourceBounds,
             Bundle opts, UserHandle user) throws RemoteException {
         ensureInUserProfiles(user, "Cannot start activity for unrelated profile " + user);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index ff90cae..a133d42 100755
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -23,14 +23,17 @@
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER;
 import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_ENABLED;
+import static android.system.OsConstants.S_IRWXU;
+import static android.system.OsConstants.S_IRGRP;
+import static android.system.OsConstants.S_IXGRP;
+import static android.system.OsConstants.S_IROTH;
+import static android.system.OsConstants.S_IXOTH;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_USER_OWNER;
+import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
 import static com.android.internal.util.ArrayUtils.appendInt;
 import static com.android.internal.util.ArrayUtils.removeInt;
-import static libcore.io.OsConstants.S_IRWXU;
-import static libcore.io.OsConstants.S_IRGRP;
-import static libcore.io.OsConstants.S_IXGRP;
-import static libcore.io.OsConstants.S_IROTH;
-import static libcore.io.OsConstants.S_IXOTH;
 
+import android.content.pm.PackageParser.*;
 import com.android.internal.app.IMediaContainerService;
 import com.android.internal.app.ResolverActivity;
 import com.android.internal.content.NativeLibraryHelper;
@@ -60,8 +63,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.IntentSender;
-import android.content.ServiceConnection;
 import android.content.IntentSender.SendIntentException;
+import android.content.ServiceConnection;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
 import android.content.pm.ContainerEncryptionParams;
@@ -74,14 +77,14 @@
 import android.content.pm.IPackageMoveObserver;
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstrumentationInfo;
+import android.content.pm.ManifestDigest;
 import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageInfoLite;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageParser;
-import android.content.pm.PackageUserState;
-import android.content.pm.PackageParser.ActivityIntentInfo;
 import android.content.pm.PackageStats;
+import android.content.pm.PackageUserState;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
@@ -89,7 +92,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
-import android.content.pm.ManifestDigest;
 import android.content.pm.VerificationParams;
 import android.content.pm.VerifierDeviceIdentity;
 import android.content.pm.VerifierInfo;
@@ -100,10 +102,10 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Environment;
+import android.os.Environment.UserEnvironment;
 import android.os.FileObserver;
 import android.os.FileUtils;
 import android.os.Handler;
-import android.os.HandlerThread;
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
@@ -116,10 +118,12 @@
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.UserHandle;
-import android.os.Environment.UserEnvironment;
 import android.os.UserManager;
 import android.security.KeyStore;
 import android.security.SystemKeyStore;
+import android.system.ErrnoException;
+import android.system.Os;
+import android.system.StructStat;
 import android.text.TextUtils;
 import android.util.DisplayMetrics;
 import android.util.EventLog;
@@ -143,6 +147,8 @@
 import java.io.PrintWriter;
 import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
 import java.security.cert.CertificateException;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
@@ -158,12 +164,11 @@
 import java.util.Map;
 import java.util.Set;
 
-import libcore.io.ErrnoException;
+import dalvik.system.VMRuntime;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
-import libcore.io.StructStat;
 
 import com.android.internal.R;
+import com.android.server.pm.Settings.DatabaseVersion;
 import com.android.server.storage.DeviceStorageMonitorInternal;
 
 /**
@@ -199,8 +204,6 @@
     private static final int BLUETOOTH_UID = Process.BLUETOOTH_UID;
     private static final int SHELL_UID = Process.SHELL_UID;
 
-    private static final boolean GET_CERTIFICATES = true;
-
     // Cap the size of permission trees that 3rd party apps can define
     private static final int MAX_PERMISSION_TREE_FOOTPRINT = 32768;     // characters of text
 
@@ -264,11 +267,14 @@
     private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
 
     private static final String LIB_DIR_NAME = "lib";
+    private static final String LIB64_DIR_NAME = "lib64";
 
     private static final String VENDOR_OVERLAY_DIR = "/vendor/overlay";
 
     static final String mTempContainerPrefix = "smdl2tmp";
 
+    private static String sPreferredInstructionSet;
+
     final ServiceThread mHandlerThread;
 
     private static final String IDMAP_PREFIX = "/data/resource-cache/";
@@ -277,8 +283,6 @@
     final PackageHandler mHandler;
 
     final int mSdkVersion = Build.VERSION.SDK_INT;
-    final String mSdkCodename = "REL".equals(Build.VERSION.CODENAME)
-            ? null : Build.VERSION.CODENAME;
 
     final Context mContext;
     final boolean mFactoryTest;
@@ -1243,27 +1247,38 @@
 
             boolean didDexOpt = false;
 
+            final List<String> instructionSets = getAllInstructionSets();
+
             /**
              * Ensure all external libraries have had dexopt run on them.
              */
             if (mSharedLibraries.size() > 0) {
-                Iterator<SharedLibraryEntry> libs = mSharedLibraries.values().iterator();
-                while (libs.hasNext()) {
-                    String lib = libs.next().path;
-                    if (lib == null) {
-                        continue;
-                    }
-                    try {
-                        if (dalvik.system.DexFile.isDexOptNeededInternal(lib, null, false)) {
-                            alreadyDexOpted.add(lib);
-                            mInstaller.dexopt(lib, Process.SYSTEM_UID, true);
-                            didDexOpt = true;
+                // NOTE: For now, we're compiling these system "shared libraries"
+                // (and framework jars) into all available architectures. It's possible
+                // to compile them only when we come across an app that uses them (there's
+                // already logic for that in scanPackageLI) but that adds some complexity.
+                for (String instructionSet : instructionSets) {
+                    for (SharedLibraryEntry libEntry : mSharedLibraries.values()) {
+                        final String lib = libEntry.path;
+                        if (lib == null) {
+                            continue;
                         }
-                    } catch (FileNotFoundException e) {
-                        Slog.w(TAG, "Library not found: " + lib);
-                    } catch (IOException e) {
-                        Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
-                                + e.getMessage());
+
+                        try {
+                            if (dalvik.system.DexFile.isDexOptNeededInternal(
+                                    lib, null, instructionSet, false)) {
+                                alreadyDexOpted.add(lib);
+
+                                // The list of "shared libraries" we have at this point is
+                                mInstaller.dexopt(lib, Process.SYSTEM_UID, true, instructionSet);
+                                didDexOpt = true;
+                            }
+                        } catch (FileNotFoundException e) {
+                            Slog.w(TAG, "Library not found: " + lib);
+                        } catch (IOException e) {
+                            Slog.w(TAG, "Cannot dexopt " + lib + "; is it an APK or JAR? "
+                                    + e.getMessage());
+                        }
                     }
                 }
             }
@@ -1286,49 +1301,37 @@
              */
             String[] frameworkFiles = frameworkDir.list();
             if (frameworkFiles != null) {
-                for (int i=0; i<frameworkFiles.length; i++) {
-                    File libPath = new File(frameworkDir, frameworkFiles[i]);
-                    String path = libPath.getPath();
-                    // Skip the file if we alrady did it.
-                    if (alreadyDexOpted.contains(path)) {
-                        continue;
-                    }
-                    // Skip the file if it is not a type we want to dexopt.
-                    if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
-                        continue;
-                    }
-                    try {
-                        if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, false)) {
-                            mInstaller.dexopt(path, Process.SYSTEM_UID, true);
-                            didDexOpt = true;
+                // TODO: We could compile these only for the most preferred ABI. We should
+                // first double check that the dex files for these commands are not referenced
+                // by other system apps.
+                for (String instructionSet : instructionSets) {
+                    for (int i=0; i<frameworkFiles.length; i++) {
+                        File libPath = new File(frameworkDir, frameworkFiles[i]);
+                        String path = libPath.getPath();
+                        // Skip the file if we already did it.
+                        if (alreadyDexOpted.contains(path)) {
+                            continue;
                         }
-                    } catch (FileNotFoundException e) {
-                        Slog.w(TAG, "Jar not found: " + path);
-                    } catch (IOException e) {
-                        Slog.w(TAG, "Exception reading jar: " + path, e);
+                        // Skip the file if it is not a type we want to dexopt.
+                        if (!path.endsWith(".apk") && !path.endsWith(".jar")) {
+                            continue;
+                        }
+                        try {
+                            if (dalvik.system.DexFile.isDexOptNeededInternal(path, null, instructionSet, false)) {
+                                mInstaller.dexopt(path, Process.SYSTEM_UID, true, instructionSet);
+                                didDexOpt = true;
+                            }
+                        } catch (FileNotFoundException e) {
+                            Slog.w(TAG, "Jar not found: " + path);
+                        } catch (IOException e) {
+                            Slog.w(TAG, "Exception reading jar: " + path, e);
+                        }
                     }
                 }
             }
 
             if (didDexOpt) {
-                File dalvikCacheDir = new File(dataDir, "dalvik-cache");
-
-                // If we had to do a dexopt of one of the previous
-                // things, then something on the system has changed.
-                // Consider this significant, and wipe away all other
-                // existing dexopt files to ensure we don't leave any
-                // dangling around.
-                String[] files = dalvikCacheDir.list();
-                if (files != null) {
-                    for (int i=0; i<files.length; i++) {
-                        String fn = files[i];
-                        if (fn.startsWith("data@app@")
-                                || fn.startsWith("data@app-private@")) {
-                            Slog.i(TAG, "Pruning dalvik file: " + fn);
-                            (new File(dalvikCacheDir, fn)).delete();
-                        }
-                    }
-                }
+                pruneDexFiles(new File(dataDir, "dalvik-cache"));
             }
 
             // Collect vendor overlay packages.
@@ -1506,6 +1509,12 @@
             // the correct library paths.
             updateAllSharedLibrariesLPw();
 
+
+            for (SharedUserSetting setting : mSettings.getAllSharedUsersLPw()) {
+                adjustCpuAbisForSharedUserLPw(setting.packages, true /* do dexopt */,
+                        false /* force dexopt */, false /* defer dexopt */);
+            }
+
             EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_SCAN_END,
                     SystemClock.uptimeMillis());
             Slog.i(TAG, "Time to scan packages: "
@@ -1536,6 +1545,9 @@
                 mSettings.readDefaultPreferredAppsLPw(this, 0);
             }
 
+            // All the changes are done during package scanning.
+            mSettings.updateInternalDatabaseVersion();
+
             // can downgrade to reader
             mSettings.writeLPr();
 
@@ -1552,6 +1564,37 @@
         } // synchronized (mInstallLock)
     }
 
+    private static void pruneDexFiles(File cacheDir) {
+        // If we had to do a dexopt of one of the previous
+        // things, then something on the system has changed.
+        // Consider this significant, and wipe away all other
+        // existing dexopt files to ensure we don't leave any
+        // dangling around.
+        //
+        // Additionally, delete all dex files from the root directory
+        // since there shouldn't be any there anyway.
+        File[] files = cacheDir.listFiles();
+        if (files != null) {
+            for (File file : files) {
+                if (!file.isDirectory()) {
+                    Slog.i(TAG, "Pruning dalvik file: " + file.getAbsolutePath());
+                    file.delete();
+                } else {
+                    File[] subDirList = file.listFiles();
+                    if (subDirList != null) {
+                        for (File subDirFile : subDirList) {
+                            final String fn = subDirFile.getName();
+                            if (fn.startsWith("data@app@") || fn.startsWith("data@app-private@")) {
+                                Slog.i(TAG, "Pruning dalvik file: " + fn);
+                                subDirFile.delete();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     public boolean isFirstBoot() {
         return !mRestoredSettings;
     }
@@ -1841,7 +1884,6 @@
 
     PackageInfo generatePackageInfo(PackageParser.Package p, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
-        PackageInfo pi;
         final PackageSetting ps = (PackageSetting) p.mExtras;
         if (ps == null) {
             return null;
@@ -2054,6 +2096,7 @@
                 pkg.applicationInfo.dataDir =
                         getDataPathForPackage(packageName, 0).getPath();
                 pkg.applicationInfo.nativeLibraryDir = ps.nativeLibraryPathString;
+                pkg.applicationInfo.requiredCpuAbi = ps.requiredCpuAbiString;
             }
             return generatePackageInfo(pkg, flags, userId);
         }
@@ -2163,6 +2206,24 @@
     }
 
     @Override
+    public boolean activitySupportsIntent(ComponentName component, Intent intent,
+            String resolvedType) {
+        synchronized (mPackages) {
+            PackageParser.Activity a = mActivities.mActivities.get(component);
+            if (a == null) {
+                return false;
+            }
+            for (int i=0; i<a.intents.size(); i++) {
+                if (a.intents.get(i).match(intent.getAction(), resolvedType, intent.getScheme(),
+                        intent.getData(), intent.getCategories(), TAG) >= 0) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    @Override
     public ActivityInfo getReceiverInfo(ComponentName component, int flags, int userId) {
         if (!sUserManager.exists(userId)) return null;
         enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "get receiver info");
@@ -2700,6 +2761,59 @@
         return PackageManager.SIGNATURE_NO_MATCH;
     }
 
+    /**
+     * If the database version for this type of package (internal storage or
+     * external storage) is less than the version where package signatures
+     * were updated, return true.
+     */
+    private boolean isCompatSignatureUpdateNeeded(PackageParser.Package scannedPkg) {
+        return (isExternal(scannedPkg) && mSettings.isExternalDatabaseVersionOlderThan(
+                DatabaseVersion.SIGNATURE_END_ENTITY))
+                || (!isExternal(scannedPkg) && mSettings.isInternalDatabaseVersionOlderThan(
+                        DatabaseVersion.SIGNATURE_END_ENTITY));
+    }
+
+    /**
+     * Used for backward compatibility to make sure any packages with
+     * certificate chains get upgraded to the new style. {@code existingSigs}
+     * will be in the old format (since they were stored on disk from before the
+     * system upgrade) and {@code scannedSigs} will be in the newer format.
+     */
+    private int compareSignaturesCompat(PackageSignatures existingSigs,
+            PackageParser.Package scannedPkg) {
+        if (!isCompatSignatureUpdateNeeded(scannedPkg)) {
+            return PackageManager.SIGNATURE_NO_MATCH;
+        }
+
+        HashSet<Signature> existingSet = new HashSet<Signature>();
+        for (Signature sig : existingSigs.mSignatures) {
+            existingSet.add(sig);
+        }
+        HashSet<Signature> scannedCompatSet = new HashSet<Signature>();
+        for (Signature sig : scannedPkg.mSignatures) {
+            try {
+                Signature[] chainSignatures = sig.getChainSignatures();
+                for (Signature chainSig : chainSignatures) {
+                    scannedCompatSet.add(chainSig);
+                }
+            } catch (CertificateEncodingException e) {
+                scannedCompatSet.add(sig);
+            }
+        }
+        /*
+         * Make sure the expanded scanned set contains all signatures in the
+         * existing one.
+         */
+        if (scannedCompatSet.equals(existingSet)) {
+            // Migrate the old signatures to the new scheme.
+            existingSigs.assignSignatures(scannedPkg.mSignatures);
+            // The new KeySets will be re-added later in the scanning process.
+            mSettings.mKeySetManager.removeAppKeySetData(scannedPkg.packageName);
+            return PackageManager.SIGNATURE_MATCH;
+        }
+        return PackageManager.SIGNATURE_NO_MATCH;
+    }
+
     public String[] getPackagesForUid(int uid) {
         uid = UserHandle.getAppId(uid);
         // reader
@@ -3050,6 +3164,33 @@
         return null;
     }
 
+    /*
+     * Returns if intent can be forwarded from the userId from to dest
+     */
+    @Override
+    public boolean canForwardTo(Intent intent, String resolvedType, int userIdFrom, int userIdDest) {
+        mContext.enforceCallingOrSelfPermission(
+                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, null);
+        List<ForwardingIntentFilter> matches =
+                getMatchingForwardingIntentFilters(intent, resolvedType, userIdFrom);
+        if (matches != null) {
+            int size = matches.size();
+            for (int i = 0; i < size; i++) {
+                if (matches.get(i).getUserIdDest() == userIdDest) return true;
+            }
+        }
+        return false;
+    }
+
+    private List<ForwardingIntentFilter> getMatchingForwardingIntentFilters(Intent intent,
+            String resolvedType, int userId) {
+        ForwardingIntentResolver fir = mSettings.mForwardingIntentResolvers.get(userId);
+        if (fir != null) {
+            return fir.queryIntent(intent, resolvedType, false, userId);
+        }
+        return null;
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivities(Intent intent,
             String resolvedType, int flags, int userId) {
@@ -3078,7 +3219,38 @@
         synchronized (mPackages) {
             final String pkgName = intent.getPackage();
             if (pkgName == null) {
-                return mActivities.queryIntent(intent, resolvedType, flags, userId);
+                List<ResolveInfo> result =
+                        mActivities.queryIntent(intent, resolvedType, flags, userId);
+                // Checking if we can forward the intent to another user
+                List<ForwardingIntentFilter> fifs =
+                        getMatchingForwardingIntentFilters(intent, resolvedType, userId);
+                if (fifs != null) {
+                    ForwardingIntentFilter forwardingIntentFilterWithResult = null;
+                    HashSet<Integer> alreadyTriedUserIds = new HashSet<Integer>();
+                    for (ForwardingIntentFilter fif : fifs) {
+                        int userIdDest = fif.getUserIdDest();
+                        // Two {@link ForwardingIntentFilter}s can have the same userIdDest and
+                        // match the same an intent. For performance reasons, it is better not to
+                        // run queryIntent twice for the same userId
+                        if (!alreadyTriedUserIds.contains(userIdDest)) {
+                            List<ResolveInfo> resultUser = mActivities.queryIntent(intent,
+                                    resolvedType, flags, userIdDest);
+                            if (resultUser != null) {
+                                forwardingIntentFilterWithResult = fif;
+                                // As soon as there is a match in another user, we add the
+                                // intentForwarderActivity to the list of ResolveInfo.
+                                break;
+                            }
+                            alreadyTriedUserIds.add(userIdDest);
+                        }
+                    }
+                    if (forwardingIntentFilterWithResult != null) {
+                        ResolveInfo forwardingResolveInfo = createForwardingResolveInfo(
+                                forwardingIntentFilterWithResult, userId);
+                        result.add(forwardingResolveInfo);
+                    }
+                }
+                return result;
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
@@ -3089,6 +3261,28 @@
         }
     }
 
+    private ResolveInfo createForwardingResolveInfo(ForwardingIntentFilter fif, int userIdFrom) {
+        String className;
+        int userIdDest = fif.getUserIdDest();
+        if (userIdDest == UserHandle.USER_OWNER) {
+            className = FORWARD_INTENT_TO_USER_OWNER;
+        } else {
+            className = FORWARD_INTENT_TO_MANAGED_PROFILE;
+        }
+        ComponentName forwardingActivityComponentName = new ComponentName(
+                mAndroidApplication.packageName, className);
+        ActivityInfo forwardingActivityInfo = getActivityInfo(forwardingActivityComponentName, 0,
+                userIdFrom);
+        ResolveInfo forwardingResolveInfo = new ResolveInfo();
+        forwardingResolveInfo.activityInfo = forwardingActivityInfo;
+        forwardingResolveInfo.priority = 0;
+        forwardingResolveInfo.preferredOrder = 0;
+        forwardingResolveInfo.match = 0;
+        forwardingResolveInfo.isDefault = true;
+        forwardingResolveInfo.filter = fif;
+        return forwardingResolveInfo;
+    }
+
     @Override
     public List<ResolveInfo> queryIntentActivityOptions(ComponentName caller,
             Intent[] specifics, String[] specificTypes, Intent intent,
@@ -3781,27 +3975,26 @@
 
     private boolean collectCertificatesLI(PackageParser pp, PackageSetting ps,
             PackageParser.Package pkg, File srcFile, int parseFlags) {
-        if (GET_CERTIFICATES) {
-            if (ps != null
-                    && ps.codePath.equals(srcFile)
-                    && ps.timeStamp == srcFile.lastModified()) {
-                if (ps.signatures.mSignatures != null
-                        && ps.signatures.mSignatures.length != 0) {
-                    // Optimization: reuse the existing cached certificates
-                    // if the package appears to be unchanged.
-                    pkg.mSignatures = ps.signatures.mSignatures;
-                    return true;
-                }
-                
-                Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures.  Collecting certs again to recover them.");
-            } else {
-                Log.i(TAG, srcFile.toString() + " changed; collecting certs");
+        if (ps != null
+                && ps.codePath.equals(srcFile)
+                && ps.timeStamp == srcFile.lastModified()
+                && !isCompatSignatureUpdateNeeded(pkg)) {
+            if (ps.signatures.mSignatures != null
+                    && ps.signatures.mSignatures.length != 0) {
+                // Optimization: reuse the existing cached certificates
+                // if the package appears to be unchanged.
+                pkg.mSignatures = ps.signatures.mSignatures;
+                return true;
             }
-            
-            if (!pp.collectCertificates(pkg, parseFlags)) {
-                mLastScanError = pp.getParseError();
-                return false;
-            }
+
+            Slog.w(TAG, "PackageSetting for " + ps.name + " is missing signatures.  Collecting certs again to recover them.");
+        } else {
+            Log.i(TAG, srcFile.toString() + " changed; collecting certs");
+        }
+
+        if (!pp.collectCertificates(pkg, parseFlags)) {
+            mLastScanError = pp.getParseError();
+            return false;
         }
         return true;
     }
@@ -3896,7 +4089,8 @@
                             + " better than installed " + ps.versionCode);
 
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
-                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
+                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
+                            getAppInstructionSetFromSettings(ps));
                     synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
@@ -3960,7 +4154,8 @@
                             + ps.codePathString + ": new version " + pkg.mVersionCode
                             + " better than installed " + ps.versionCode);
                     InstallArgs args = createInstallArgs(packageFlagsToInstallFlags(ps),
-                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString);
+                            ps.codePathString, ps.resourcePathString, ps.nativeLibraryPathString,
+                            getAppInstructionSetFromSettings(ps));
                     synchronized (mInstallLock) {
                         args.cleanUpResourcesLI();
                     }
@@ -4033,22 +4228,32 @@
         return processName;
     }
 
-    private boolean verifySignaturesLP(PackageSetting pkgSetting,
-            PackageParser.Package pkg) {
+    private boolean verifySignaturesLP(PackageSetting pkgSetting, PackageParser.Package pkg) {
         if (pkgSetting.signatures.mSignatures != null) {
             // Already existing package. Make sure signatures match
-            if (compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures) !=
-                PackageManager.SIGNATURE_MATCH) {
-                    Slog.e(TAG, "Package " + pkg.packageName
-                            + " signatures do not match the previously installed version; ignoring!");
-                    mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
-                    return false;
-                }
+            boolean match = compareSignatures(pkgSetting.signatures.mSignatures, pkg.mSignatures)
+                    == PackageManager.SIGNATURE_MATCH;
+            if (!match) {
+                match = compareSignaturesCompat(pkgSetting.signatures, pkg)
+                        == PackageManager.SIGNATURE_MATCH;
+            }
+            if (!match) {
+                Slog.e(TAG, "Package " + pkg.packageName
+                        + " signatures do not match the previously installed version; ignoring!");
+                mLastScanError = PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
+                return false;
+            }
         }
         // Check for shared user signatures
         if (pkgSetting.sharedUser != null && pkgSetting.sharedUser.signatures.mSignatures != null) {
-            if (compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
-                    pkg.mSignatures) != PackageManager.SIGNATURE_MATCH) {
+            // Already existing package. Make sure signatures match
+            boolean match = compareSignatures(pkgSetting.sharedUser.signatures.mSignatures,
+                    pkg.mSignatures) == PackageManager.SIGNATURE_MATCH;
+            if (!match) {
+                match = compareSignaturesCompat(pkgSetting.sharedUser.signatures, pkg)
+                        == PackageManager.SIGNATURE_MATCH;
+            }
+            if (!match) {
                 Slog.e(TAG, "Package " + pkg.packageName
                         + " has no signatures that match those in shared user "
                         + pkgSetting.sharedUser.name + "; ignoring!");
@@ -4073,12 +4278,16 @@
         }
     }
 
+    @Override
     public void performBootDexOpt() {
-        HashSet<PackageParser.Package> pkgs = null;
+        enforceSystemOrRoot("Only the system can request dexopt be performed");
+
+        final HashSet<PackageParser.Package> pkgs;
         synchronized (mPackages) {
             pkgs = mDeferredDexOpt;
             mDeferredDexOpt = null;
         }
+
         if (pkgs != null) {
             int i = 0;
             for (PackageParser.Package pkg : pkgs) {
@@ -4095,16 +4304,17 @@
                 PackageParser.Package p = pkg;
                 synchronized (mInstallLock) {
                     if (!p.mDidDexOpt) {
-                        performDexOptLI(p, false, false, true);
+                        performDexOptLI(p, false /* force dex */, false /* defer */,
+                                true /* include dependencies */);
                     }
                 }
             }
         }
     }
 
+    @Override
     public boolean performDexOpt(String packageName) {
         enforceSystemOrRoot("Only the system can request dexopt be performed");
-
         if (!mNoDexOpt) {
             return false;
         }
@@ -4117,12 +4327,13 @@
             }
         }
         synchronized (mInstallLock) {
-            return performDexOptLI(p, false, false, true) == DEX_OPT_PERFORMED;
+            return performDexOptLI(p, false /* force dex */, false /* defer */,
+                    true /* include dependencies */) == DEX_OPT_PERFORMED;
         }
     }
 
-    private void performDexOptLibsLI(ArrayList<String> libs, boolean forceDex, boolean defer,
-            HashSet<String> done) {
+    private void performDexOptLibsLI(ArrayList<String> libs, String instructionSet, boolean forceDex,
+            boolean defer, HashSet<String> done) {
         for (int i=0; i<libs.size(); i++) {
             PackageParser.Package libPkg;
             String libName;
@@ -4136,7 +4347,7 @@
                 }
             }
             if (libPkg != null && !done.contains(libName)) {
-                performDexOptLI(libPkg, forceDex, defer, done);
+                performDexOptLI(libPkg, instructionSet, forceDex, defer, done);
             }
         }
     }
@@ -4146,24 +4357,29 @@
     static final int DEX_OPT_DEFERRED = 2;
     static final int DEX_OPT_FAILED = -1;
 
-    private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
-            HashSet<String> done) {
-        boolean performed = false;
+    private int performDexOptLI(PackageParser.Package pkg, String instructionSetOverride,
+            boolean forceDex,
+            boolean defer, HashSet<String> done) {
+        final String instructionSet = instructionSetOverride != null ?
+                instructionSetOverride : getAppInstructionSet(pkg.applicationInfo);
+
         if (done != null) {
             done.add(pkg.packageName);
             if (pkg.usesLibraries != null) {
-                performDexOptLibsLI(pkg.usesLibraries, forceDex, defer, done);
+                performDexOptLibsLI(pkg.usesLibraries, instructionSet, forceDex, defer, done);
             }
             if (pkg.usesOptionalLibraries != null) {
-                performDexOptLibsLI(pkg.usesOptionalLibraries, forceDex, defer, done);
+                performDexOptLibsLI(pkg.usesOptionalLibraries, instructionSet, forceDex, defer, done);
             }
         }
+
+        boolean performed = false;
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
             String path = pkg.mScanPath;
             int ret = 0;
             try {
-                if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path, pkg.packageName,
-                                                                             defer)) {
+                if (forceDex || dalvik.system.DexFile.isDexOptNeededInternal(path,
+                        pkg.packageName, instructionSet, defer)) {
                     if (!forceDex && defer) {
                         if (mDeferredDexOpt == null) {
                             mDeferredDexOpt = new HashSet<PackageParser.Package>();
@@ -4171,10 +4387,12 @@
                         mDeferredDexOpt.add(pkg);
                         return DEX_OPT_DEFERRED;
                     } else {
-                        Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName);
+                        Log.i(TAG, "Running dexopt on: " + pkg.applicationInfo.packageName +
+                                " (instructionSet=" + instructionSet + ")");
+
                         final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid);
                         ret = mInstaller.dexopt(path, sharedGid, !isForwardLocked(pkg),
-                                                pkg.packageName);
+                                                pkg.packageName, instructionSet);
                         pkg.mDidDexOpt = true;
                         performed = true;
                     }
@@ -4201,17 +4419,58 @@
         return performed ? DEX_OPT_PERFORMED : DEX_OPT_SKIPPED;
     }
 
+    private String getAppInstructionSet(ApplicationInfo info) {
+        String instructionSet = getPreferredInstructionSet();
+
+        if (info.requiredCpuAbi != null) {
+            instructionSet = VMRuntime.getInstructionSet(info.requiredCpuAbi);
+        }
+
+        return instructionSet;
+    }
+
+    private String getAppInstructionSetFromSettings(PackageSetting ps) {
+        String instructionSet = getPreferredInstructionSet();
+
+        if (ps.requiredCpuAbiString != null) {
+            instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString);
+        }
+
+        return instructionSet;
+    }
+
+    private static String getPreferredInstructionSet() {
+        if (sPreferredInstructionSet == null) {
+            sPreferredInstructionSet = VMRuntime.getInstructionSet(Build.SUPPORTED_ABIS[0]);
+        }
+
+        return sPreferredInstructionSet;
+    }
+
+    private static List<String> getAllInstructionSets() {
+        final String[] allAbis = Build.SUPPORTED_ABIS;
+        final List<String> allInstructionSets = new ArrayList<String>(allAbis.length);
+
+        for (String abi : allAbis) {
+            final String instructionSet = VMRuntime.getInstructionSet(abi);
+            if (!allInstructionSets.contains(instructionSet)) {
+                allInstructionSets.add(instructionSet);
+            }
+        }
+
+        return allInstructionSets;
+    }
+
     private int performDexOptLI(PackageParser.Package pkg, boolean forceDex, boolean defer,
             boolean inclDependencies) {
         HashSet<String> done;
-        boolean performed = false;
         if (inclDependencies && (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null)) {
             done = new HashSet<String>();
             done.add(pkg.packageName);
         } else {
             done = null;
         }
-        return performDexOptLI(pkg, forceDex, defer, done);
+        return performDexOptLI(pkg, null /* instruction set override */,  forceDex, defer, done);
     }
 
     private boolean verifyPackageUpdateLPr(PackageSetting oldPkg, PackageParser.Package newPkg) {
@@ -4315,6 +4574,14 @@
 
     private boolean updateSharedLibrariesLPw(PackageParser.Package pkg,
             PackageParser.Package changingLib) {
+        // We might be upgrading from a version of the platform that did not
+        // provide per-package native library directories for system apps.
+        // Fix that up here.
+        if (isSystemApp(pkg)) {
+            PackageSetting ps = mSettings.mPackages.get(pkg.applicationInfo.packageName);
+            setInternalAppNativeLibraryPath(pkg, ps);
+        }
+
         if (pkg.usesLibraries != null || pkg.usesOptionalLibraries != null) {
             if (mTmpSharedLibraries == null ||
                     mTmpSharedLibraries.length < mSharedLibraries.size()) {
@@ -4480,17 +4747,6 @@
 
         // writer
         synchronized (mPackages) {
-            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
-                // Check all shared libraries and map to their actual file path.
-                // We only do this here for apps not on a system dir, because those
-                // are the only ones that can fail an install due to this.  We
-                // will take care of the system apps by updating all of their
-                // library paths after the scan is done.
-                if (!updateSharedLibrariesLPw(pkg, null)) {
-                    return null;
-                }
-            }
-
             if (pkg.mSharedUserId != null) {
                 suid = mSettings.getSharedUserLPw(pkg.mSharedUserId, 0, true);
                 if (suid == null) {
@@ -4565,6 +4821,7 @@
             // the PkgSetting exists already and doesn't have to be created.
             pkgSetting = mSettings.getPackageLPw(pkg, origPackage, realName, suid, destCodeFile,
                     destResourceFile, pkg.applicationInfo.nativeLibraryDir,
+                    pkg.applicationInfo.requiredCpuAbi,
                     pkg.applicationInfo.flags, user, false);
             if (pkgSetting == null) {
                 Slog.w(TAG, "Creating application package " + pkg.packageName + " failed");
@@ -4600,6 +4857,17 @@
                 pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
             }
 
+            if ((parseFlags&PackageParser.PARSE_IS_SYSTEM_DIR) == 0) {
+                // Check all shared libraries and map to their actual file path.
+                // We only do this here for apps not on a system dir, because those
+                // are the only ones that can fail an install due to this.  We
+                // will take care of the system apps by updating all of their
+                // library paths after the scan is done.
+                if (!updateSharedLibrariesLPw(pkg, null)) {
+                    return null;
+                }
+            }
+
             if (mFoundPolicyFile) {
                 SELinuxMMAC.assignSeinfoValue(pkg);
             }
@@ -4700,7 +4968,7 @@
             if (dataPath.exists()) {
                 int currentUid = 0;
                 try {
-                    StructStat stat = Libcore.os.stat(dataPath.getPath());
+                    StructStat stat = Os.stat(dataPath.getPath());
                     currentUid = stat.st_uid;
                 } catch (ErrnoException e) {
                     Slog.e(TAG, "Couldn't stat path " + dataPath.getPath(), e);
@@ -4826,7 +5094,6 @@
                     pkg.applicationInfo.nativeLibraryDir = pkgSetting.nativeLibraryPathString;
                 }
             }
-
             pkgSetting.uidError = uidError;
         }
 
@@ -4858,6 +5125,8 @@
                         Log.i(TAG, "removed obsolete native libraries for system package "
                                 + path);
                     }
+
+                    setInternalAppAbi(pkg, pkgSetting);
                 } else {
                     if (!isForwardLocked(pkg) && !isExternal(pkg)) {
                         /*
@@ -4870,16 +5139,47 @@
                         }
 
                         try {
-                            if (copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir) != PackageManager.INSTALL_SUCCEEDED) {
+                            int copyRet = copyNativeLibrariesForInternalApp(scanFile, nativeLibraryDir);
+                            if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                                 Slog.e(TAG, "Unable to copy native libraries");
                                 mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                                 return null;
                             }
+
+                            // We've successfully copied native libraries across, so we make a
+                            // note of what ABI we're using
+                            if (copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
+                                pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[copyRet];
+                            } else {
+                                pkg.applicationInfo.requiredCpuAbi = null;
+                            }
                         } catch (IOException e) {
                             Slog.e(TAG, "Unable to copy native libraries", e);
                             mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
                             return null;
                         }
+                    } else {
+                        // We don't have to copy the shared libraries if we're in the ASEC container
+                        // but we still need to scan the file to figure out what ABI the app needs.
+                        //
+                        // TODO: This duplicates work done in the default container service. It's possible
+                        // to clean this up but we'll need to change the interface between this service
+                        // and IMediaContainerService (but doing so will spread this logic out, rather
+                        // than centralizing it).
+                        final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
+                        final int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+                        if (abi >= 0) {
+                            pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_ABIS[abi];
+                        } else if (abi == PackageManager.NO_NATIVE_LIBRARIES) {
+                            // Note that (non upgraded) system apps will not have any native
+                            // libraries bundled in their APK, but we're guaranteed not to be
+                            // such an app at this point.
+                            pkg.applicationInfo.requiredCpuAbi = null;
+                        } else {
+                            mLastScanError = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
+                            return null;
+                        }
+                        handle.close();
                     }
 
                     if (DEBUG_INSTALL) Slog.i(TAG, "Linking native library dir for " + path);
@@ -4956,8 +5256,7 @@
                         }
                         if (allowed) {
                             if (!mSharedLibraries.containsKey(name)) {
-                                mSharedLibraries.put(name, new SharedLibraryEntry(null,
-                                        pkg.packageName));
+                                mSharedLibraries.put(name, new SharedLibraryEntry(null, pkg.packageName));
                             } else if (!name.equals(pkg.packageName)) {
                                 Slog.w(TAG, "Package " + pkg.packageName + " library "
                                         + name + " already exists; skipping");
@@ -5030,6 +5329,12 @@
 
         // writer
         synchronized (mPackages) {
+            if ((scanMode&SCAN_BOOTING) == 0 && pkgSetting.sharedUser != null) {
+                // We don't do this here during boot because we can do it all
+                // at once after scanning all existing packages.
+                adjustCpuAbisForSharedUserLPw(pkgSetting.sharedUser.packages,
+                        true, forceDex, (scanMode & SCAN_DEFER_DEX) != 0);
+            }
             // We don't expect installation to fail beyond this point,
             if ((scanMode&SCAN_MONITOR) != 0) {
                 mAppDirs.put(pkg.mPath, pkg);
@@ -5374,6 +5679,55 @@
         return pkg;
     }
 
+    public void adjustCpuAbisForSharedUserLPw(Set<PackageSetting> packagesForUser,
+            boolean doDexOpt, boolean forceDexOpt, boolean deferDexOpt) {
+        String requiredInstructionSet = null;
+        PackageSetting requirer = null;
+        for (PackageSetting ps : packagesForUser) {
+            if (ps.requiredCpuAbiString != null) {
+                final String instructionSet = VMRuntime.getInstructionSet(ps.requiredCpuAbiString);
+                if (requiredInstructionSet != null) {
+                    if (!instructionSet.equals(requiredInstructionSet)) {
+                        // We have a mismatch between instruction sets (say arm vs arm64).
+                        //
+                        // TODO: We should rescan all the packages in a shared UID to check if
+                        // they do contain shared libs for other ABIs in addition to the ones we've
+                        // already extracted. For example, the package might contain both arm64-v8a
+                        // and armeabi-v7a shared libs, and we'd have chosen arm64-v8a on 64 bit
+                        // devices.
+                        String errorMessage = "Instruction set mismatch, " + requirer.pkg.packageName
+                                + " requires " + requiredInstructionSet + " whereas " + ps.pkg.packageName
+                                + " requires " + instructionSet;
+                        Slog.e(TAG, errorMessage);
+
+                        reportSettingsProblem(Log.WARN, errorMessage);
+                        // Give up, don't bother making any other changes to the package settings.
+                        return;
+                    }
+                } else {
+                    requiredInstructionSet = instructionSet;
+                    requirer = ps;
+                }
+            }
+        }
+
+        if (requiredInstructionSet != null) {
+            for (PackageSetting ps : packagesForUser) {
+                if (ps.requiredCpuAbiString == null) {
+                    ps.requiredCpuAbiString = requirer.requiredCpuAbiString;
+                    if (ps.pkg != null) {
+                        ps.pkg.applicationInfo.requiredCpuAbi = requirer.requiredCpuAbiString;
+                        Slog.i(TAG, "Adjusting ABI for : " + ps.name + " to " + ps.requiredCpuAbiString);
+                        if (doDexOpt) {
+                            performDexOptLI(ps.pkg, forceDexOpt, deferDexOpt, true);
+                            mInstaller.rmdex(ps.codePathString, getPreferredInstructionSet());
+                        }
+                    }
+                }
+            }
+        }
+    }
+
     private void setUpCustomResolverActivity(PackageParser.Package pkg) {
         synchronized (mPackages) {
             mResolverReplaced = true;
@@ -5398,14 +5752,86 @@
         }
     }
 
+    private String calculateApkRoot(final String codePathString) {
+        final File codePath = new File(codePathString);
+        final File codeRoot;
+        if (FileUtils.contains(Environment.getRootDirectory(), codePath)) {
+            codeRoot = Environment.getRootDirectory();
+        } else if (FileUtils.contains(Environment.getOemDirectory(), codePath)) {
+            codeRoot = Environment.getOemDirectory();
+        } else if (FileUtils.contains(Environment.getVendorDirectory(), codePath)) {
+            codeRoot = Environment.getVendorDirectory();
+        } else {
+            // Unrecognized code path; take its top real segment as the apk root:
+            // e.g. /something/app/blah.apk => /something
+            try {
+                File f = codePath.getCanonicalFile();
+                File parent = f.getParentFile();    // non-null because codePath is a file
+                File tmp;
+                while ((tmp = parent.getParentFile()) != null) {
+                    f = parent;
+                    parent = tmp;
+                }
+                codeRoot = f;
+                Slog.w(TAG, "Unrecognized code path "
+                        + codePath + " - using " + codeRoot);
+            } catch (IOException e) {
+                // Can't canonicalize the lib path -- shenanigans?
+                Slog.w(TAG, "Can't canonicalize code path " + codePath);
+                return Environment.getRootDirectory().getPath();
+            }
+        }
+        return codeRoot.getPath();
+    }
+
+    // This is the initial scan-time determination of how to handle a given
+    // package for purposes of native library location.
     private void setInternalAppNativeLibraryPath(PackageParser.Package pkg,
             PackageSetting pkgSetting) {
-        final String apkLibPath = getApkName(pkgSetting.codePathString);
-        final String nativeLibraryPath = new File(mAppLibInstallDir, apkLibPath).getPath();
+        // "bundled" here means system-installed with no overriding update
+        final boolean bundledApk = isSystemApp(pkg) && !isUpdatedSystemApp(pkg);
+        final String apkName = getApkName(pkg.applicationInfo.sourceDir);
+        final File libDir;
+        if (bundledApk) {
+            // If "/system/lib64/apkname" exists, assume that is the per-package
+            // native library directory to use; otherwise use "/system/lib/apkname".
+            String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+            File lib64 = new File(apkRoot, LIB64_DIR_NAME);
+            File packLib64 = new File(lib64, apkName);
+            libDir = (packLib64.exists()) ? lib64 : new File(apkRoot, LIB_DIR_NAME);
+        } else {
+            libDir = mAppLibInstallDir;
+        }
+        final String nativeLibraryPath = (new File(libDir, apkName)).getPath();
         pkg.applicationInfo.nativeLibraryDir = nativeLibraryPath;
         pkgSetting.nativeLibraryPathString = nativeLibraryPath;
     }
 
+    // Deduces the required ABI of an upgraded system app.
+    private void setInternalAppAbi(PackageParser.Package pkg, PackageSetting pkgSetting) {
+        final String apkRoot = calculateApkRoot(pkg.applicationInfo.sourceDir);
+        final String apkName = getApkName(pkg.applicationInfo.sourceDir);
+
+        // This is of the form "/system/lib64/<packagename>", "/vendor/lib64/<packagename>"
+        // or similar.
+        final File lib64 = new File(apkRoot, new File(LIB64_DIR_NAME, apkName).getPath());
+        final File lib = new File(apkRoot, new File(LIB_DIR_NAME, apkName).getPath());
+
+        // Assume that the bundled native libraries always correspond to the
+        // most preferred 32 or 64 bit ABI.
+        if (lib64.exists()) {
+            pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_64_BIT_ABIS[0];
+            pkgSetting.requiredCpuAbiString = Build.SUPPORTED_64_BIT_ABIS[0];
+        } else if (lib.exists()) {
+            pkg.applicationInfo.requiredCpuAbi = Build.SUPPORTED_32_BIT_ABIS[0];
+            pkgSetting.requiredCpuAbiString = Build.SUPPORTED_32_BIT_ABIS[0];
+        } else {
+            // This is the case where the app has no native code.
+            pkg.applicationInfo.requiredCpuAbi = null;
+            pkgSetting.requiredCpuAbiString = null;
+        }
+    }
+
     private static int copyNativeLibrariesForInternalApp(File scanFile, final File nativeLibraryDir)
             throws IOException {
         if (!nativeLibraryDir.isDirectory()) {
@@ -5416,8 +5842,7 @@
             }
 
             try {
-                Libcore.os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH
-                        | S_IXOTH);
+                Os.chmod(nativeLibraryDir.getPath(), S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH);
             } catch (ErrnoException e) {
                 throw new IOException("Cannot chmod native library directory "
                         + nativeLibraryDir.getPath(), e);
@@ -5430,7 +5855,21 @@
          * If this is an internal application or our nativeLibraryPath points to
          * the app-lib directory, unpack the libraries if necessary.
          */
-        return NativeLibraryHelper.copyNativeBinariesIfNeededLI(scanFile, nativeLibraryDir);
+        final NativeLibraryHelper.ApkHandle handle = new NativeLibraryHelper.ApkHandle(scanFile);
+        try {
+            int abi = NativeLibraryHelper.findSupportedAbi(handle, Build.SUPPORTED_ABIS);
+            if (abi >= 0) {
+                int copyRet = NativeLibraryHelper.copyNativeBinariesIfNeededLI(handle,
+                        nativeLibraryDir, Build.SUPPORTED_ABIS[abi]);
+                if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+                    return copyRet;
+                }
+            }
+
+            return abi;
+        } finally {
+            handle.close();
+        }
     }
 
     private void killApplication(String pkgName, int appId, String reason) {
@@ -8035,7 +8474,8 @@
         int mRet;
 
         MoveParams(InstallArgs srcArgs, IPackageMoveObserver observer, int flags,
-                String packageName, String dataDir, int uid, UserHandle user) {
+                String packageName, String dataDir, String instructionSet,
+                int uid, UserHandle user) {
             super(user);
             this.srcArgs = srcArgs;
             this.observer = observer;
@@ -8044,7 +8484,7 @@
             this.uid = uid;
             if (srcArgs != null) {
                 Uri packageUri = Uri.fromFile(new File(srcArgs.getCodePath()));
-                targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir);
+                targetArgs = createInstallArgs(packageUri, flags, packageName, dataDir, instructionSet);
             } else {
                 targetArgs = null;
             }
@@ -8153,7 +8593,7 @@
     }
 
     private InstallArgs createInstallArgs(int flags, String fullCodePath, String fullResourcePath,
-            String nativeLibraryPath) {
+            String nativeLibraryPath, String instructionSet) {
         final boolean isInAsec;
         if (installOnSd(flags)) {
             /* Apps on SD card are always in ASEC containers. */
@@ -8171,21 +8611,23 @@
 
         if (isInAsec) {
             return new AsecInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
-                    installOnSd(flags), installForwardLocked(flags));
+                    instructionSet, installOnSd(flags), installForwardLocked(flags));
         } else {
-            return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath);
+            return new FileInstallArgs(fullCodePath, fullResourcePath, nativeLibraryPath,
+                    instructionSet);
         }
     }
 
     // Used by package mover
-    private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir) {
+    private InstallArgs createInstallArgs(Uri packageURI, int flags, String pkgName, String dataDir,
+            String instructionSet) {
         if (installOnSd(flags) || installForwardLocked(flags)) {
             String cid = getNextCodePath(packageURI.getPath(), pkgName, "/"
                     + AsecInstallArgs.RES_FILE_NAME);
-            return new AsecInstallArgs(packageURI, cid, installOnSd(flags),
+            return new AsecInstallArgs(packageURI, cid, instructionSet, installOnSd(flags),
                     installForwardLocked(flags));
         } else {
-            return new FileInstallArgs(packageURI, pkgName, dataDir);
+            return new FileInstallArgs(packageURI, pkgName, dataDir, instructionSet);
         }
     }
 
@@ -8198,11 +8640,12 @@
         final String installerPackageName;
         final ManifestDigest manifestDigest;
         final UserHandle user;
+        final String instructionSet;
 
         InstallArgs(Uri packageURI,
                 IPackageInstallObserver observer, IPackageInstallObserver2 observer2,
                 int flags, String installerPackageName, ManifestDigest manifestDigest,
-                UserHandle user) {
+                UserHandle user, String instructionSet) {
             this.packageURI = packageURI;
             this.flags = flags;
             this.observer = observer;
@@ -8210,6 +8653,7 @@
             this.installerPackageName = installerPackageName;
             this.manifestDigest = manifestDigest;
             this.user = user;
+            this.instructionSet = instructionSet;
         }
 
         abstract void createCopyFile();
@@ -8265,11 +8709,12 @@
         FileInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.observer2, params.flags,
                     params.installerPackageName, params.getManifestDigest(),
-                    params.getUser());
+                    params.getUser(), null /* instruction set */);
         }
 
-        FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath) {
-            super(null, null, null, 0, null, null, null);
+        FileInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
+                String instructionSet) {
+            super(null, null, null, 0, null, null, null, instructionSet);
             File codeFile = new File(fullCodePath);
             installDir = codeFile.getParentFile();
             codeFileName = fullCodePath;
@@ -8277,8 +8722,8 @@
             libraryPath = nativeLibraryPath;
         }
 
-        FileInstallArgs(Uri packageURI, String pkgName, String dataDir) {
-            super(packageURI, null, null, 0, null, null, null);
+        FileInstallArgs(Uri packageURI, String pkgName, String dataDir, String instructionSet) {
+            super(packageURI, null, null, 0, null, null, null, instructionSet);
             installDir = isFwdLocked() ? mDrmAppPrivateInstallDir : mAppInstallDir;
             String apkName = getNextCodePath(null, pkgName, ".apk");
             codeFileName = new File(installDir, apkName + ".apk").getPath();
@@ -8384,7 +8829,7 @@
             }
             try {
                 int copyRet = copyNativeLibrariesForInternalApp(codeFile, nativeLibraryFile);
-                if (copyRet != PackageManager.INSTALL_SUCCEEDED) {
+                if (copyRet < 0 && copyRet != PackageManager.NO_NATIVE_LIBRARIES) {
                     return copyRet;
                 }
             } catch (IOException e) {
@@ -8537,7 +8982,10 @@
         void cleanUpResourcesLI() {
             String sourceDir = getCodePath();
             if (cleanUp()) {
-                int retCode = mInstaller.rmdex(sourceDir);
+                if (instructionSet == null) {
+                    throw new IllegalStateException("instructionSet == null");
+                }
+                int retCode = mInstaller.rmdex(sourceDir, instructionSet);
                 if (retCode < 0) {
                     Slog.w(TAG, "Couldn't remove dex file for package: "
                             +  " at location "
@@ -8601,14 +9049,14 @@
         AsecInstallArgs(InstallParams params) {
             super(params.getPackageUri(), params.observer, params.observer2, params.flags,
                     params.installerPackageName, params.getManifestDigest(),
-                    params.getUser());
+                    params.getUser(), null /* instruction set */);
         }
 
         AsecInstallArgs(String fullCodePath, String fullResourcePath, String nativeLibraryPath,
-                boolean isExternal, boolean isForwardLocked) {
+                String instructionSet, boolean isExternal, boolean isForwardLocked) {
             super(null, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null);
+                    null, null, null, instructionSet);
             // Extract cid from fullCodePath
             int eidx = fullCodePath.lastIndexOf("/");
             String subStr1 = fullCodePath.substring(0, eidx);
@@ -8617,18 +9065,19 @@
             setCachePath(subStr1);
         }
 
-        AsecInstallArgs(String cid, boolean isForwardLocked) {
+        AsecInstallArgs(String cid, String instructionSet, boolean isForwardLocked) {
             super(null, null, null, (isAsecExternal(cid) ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null);
+                    null, null, null, instructionSet);
             this.cid = cid;
             setCachePath(PackageHelper.getSdDir(cid));
         }
 
-        AsecInstallArgs(Uri packageURI, String cid, boolean isExternal, boolean isForwardLocked) {
+        AsecInstallArgs(Uri packageURI, String cid, String instructionSet,
+                boolean isExternal, boolean isForwardLocked) {
             super(packageURI, null, null, (isExternal ? PackageManager.INSTALL_EXTERNAL : 0)
                     | (isForwardLocked ? PackageManager.INSTALL_FORWARD_LOCK : 0),
-                    null, null, null);
+                    null, null, null, instructionSet);
             this.cid = cid;
         }
 
@@ -8809,7 +9258,10 @@
         void cleanUpResourcesLI() {
             String sourceFile = getCodePath();
             // Remove dex file
-            int retCode = mInstaller.rmdex(sourceFile);
+            if (instructionSet == null) {
+                throw new IllegalStateException("instructionSet == null");
+            }
+            int retCode = mInstaller.rmdex(sourceFile, instructionSet);
             if (retCode < 0) {
                 Slog.w(TAG, "Couldn't remove dex file for package: "
                         + " at location "
@@ -9194,7 +9646,8 @@
                 res.removedInfo.args = createInstallArgs(0,
                         deletedPackage.applicationInfo.sourceDir,
                         deletedPackage.applicationInfo.publicSourceDir,
-                        deletedPackage.applicationInfo.nativeLibraryDir);
+                        deletedPackage.applicationInfo.nativeLibraryDir,
+                        getAppInstructionSet(deletedPackage.applicationInfo));
             } else {
                 res.removedInfo.args = null;
             }
@@ -9254,7 +9707,8 @@
     private int moveDexFilesLI(PackageParser.Package newPackage) {
         int retCode;
         if ((newPackage.applicationInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0) {
-            retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath);
+            retCode = mInstaller.movedex(newPackage.mScanPath, newPackage.mPath,
+                    getAppInstructionSet(newPackage.applicationInfo));
             if (retCode != 0) {
                 if (mNoDexOpt) {
                     /*
@@ -9370,7 +9824,7 @@
                 return;
             }
         }
-        if (GET_CERTIFICATES && !pp.collectCertificates(pkg, parseFlags)) {
+        if (!pp.collectCertificates(pkg, parseFlags)) {
             res.returnCode = pp.getParseError();
             return;
         }
@@ -9899,13 +10353,14 @@
         }
         // writer
         synchronized (mPackages) {
+            PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
+            setInternalAppNativeLibraryPath(newPkg, ps);
             updatePermissionsLPw(newPkg.packageName, newPkg,
                     UPDATE_PERMISSIONS_ALL | UPDATE_PERMISSIONS_REPLACE_PKG);
             if (applyUserRestrictions) {
                 if (DEBUG_REMOVE) {
                     Slog.d(TAG, "Propagating install state across reinstall");
                 }
-                PackageSetting ps = mSettings.mPackages.get(newPkg.packageName);
                 for (int i = 0; i < allUserHandles.length; i++) {
                     if (DEBUG_REMOVE) {
                         Slog.d(TAG, "    user " + allUserHandles[i]
@@ -9939,7 +10394,8 @@
         // Delete application code and resources
         if (deleteCodeAndResources && (outInfo != null)) {
             outInfo.args = createInstallArgs(packageFlagsToInstallFlags(ps), ps.codePathString,
-                    ps.resourcePathString, ps.nativeLibraryPathString);
+                    ps.resourcePathString, ps.nativeLibraryPathString,
+                    getAppInstructionSetFromSettings(ps));
         }
         return true;
     }
@@ -10309,9 +10765,10 @@
         boolean dataOnly = false;
         String libDirPath = null;
         String asecPath = null;
+        PackageSetting ps = null;
         synchronized (mPackages) {
             p = mPackages.get(packageName);
-            PackageSetting ps = mSettings.mPackages.get(packageName);
+            ps = mSettings.mPackages.get(packageName);
             if(p == null) {
                 dataOnly = true;
                 if((ps == null) || (ps.pkg == null)) {
@@ -10342,7 +10799,8 @@
             }
         }
         int res = mInstaller.getSizeInfo(packageName, userHandle, p.mPath, libDirPath,
-                publicSrcDir, asecPath, pStats);
+                publicSrcDir, asecPath, getAppInstructionSetFromSettings(ps),
+                pStats);
         if (res < 0) {
             return false;
         }
@@ -10654,6 +11112,47 @@
         }
     }
 
+    /*
+     * For filters that are added with this method:
+     * if an intent for the user whose id is userIdOrig matches the filter, then this intent can
+     * also be resolved in the user whose id is userIdDest.
+     */
+    @Override
+    public void addForwardingIntentFilter(IntentFilter filter, int userIdOrig, int userIdDest) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "addForwardingIntentFilter can only be run by the system");
+        }
+        if (filter.countActions() == 0) {
+            Slog.w(TAG, "Cannot set a forwarding intent filter with no filter actions");
+            return;
+        }
+        synchronized (mPackages) {
+            mSettings.editForwardingIntentResolverLPw(userIdOrig).addFilter(
+                    new ForwardingIntentFilter(filter, userIdDest));
+            mSettings.writePackageRestrictionsLPr(userIdOrig);
+        }
+    }
+
+    @Override
+    public void clearForwardingIntentFilters(int userIdOrig) {
+        int callingUid = Binder.getCallingUid();
+        if (callingUid != Process.SYSTEM_UID) {
+            throw new SecurityException(
+                    "clearForwardingIntentFilter can only be run by the system");
+        }
+        synchronized (mPackages) {
+            ForwardingIntentResolver fir = mSettings.editForwardingIntentResolverLPw(userIdOrig);
+            HashSet<ForwardingIntentFilter> set =
+                    new HashSet<ForwardingIntentFilter>(fir.filterSet());
+            for (ForwardingIntentFilter fif : set) {
+                fir.removeFilter(fif);
+            }
+            mSettings.writePackageRestrictionsLPr(userIdOrig);
+        }
+    }
+
     @Override
     public ComponentName getHomeActivities(List<ResolveInfo> allHomeCandidates) {
         Intent intent = new Intent(Intent.ACTION_MAIN);
@@ -10980,6 +11479,8 @@
 
         public static final int DUMP_KEYSETS = 1 << 11;
 
+        public static final int DUMP_VERSION = 1 << 12;
+
         public static final int OPTION_SHOW_FILTERS = 1 << 0;
 
         private int mTypes;
@@ -11078,6 +11579,7 @@
                 pw.println("    s[hared-users]: dump shared user IDs");
                 pw.println("    m[essages]: print collected runtime messages");
                 pw.println("    v[erifiers]: print package verifier info");
+                pw.println("    version: print database version info");
                 pw.println("    <package.name>: info about given package");
                 pw.println("    k[eysets]: print known keysets");
                 return;
@@ -11126,6 +11628,8 @@
                 dumpState.setDump(DumpState.DUMP_MESSAGES);
             } else if ("v".equals(cmd) || "verifiers".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_VERIFIERS);
+            } else if ("version".equals(cmd)) {
+                dumpState.setDump(DumpState.DUMP_VERSION);
             } else if ("k".equals(cmd) || "keysets".equals(cmd)) {
                 dumpState.setDump(DumpState.DUMP_KEYSETS);
             }
@@ -11137,6 +11641,24 @@
 
         // reader
         synchronized (mPackages) {
+            if (dumpState.isDumping(DumpState.DUMP_VERSION) && packageName == null) {
+                if (!checkin) {
+                    if (dumpState.onTitlePrinted())
+                        pw.println();
+                    pw.println("Database versions:");
+                    pw.print("  SDK Version:");
+                    pw.print(" internal=");
+                    pw.print(mSettings.mInternalSdkPlatform);
+                    pw.print(" external=");
+                    pw.println(mSettings.mExternalSdkPlatform);
+                    pw.print("  DB Version:");
+                    pw.print(" internal=");
+                    pw.print(mSettings.mInternalDatabaseVersion);
+                    pw.print(" external=");
+                    pw.println(mSettings.mExternalDatabaseVersion);
+                }
+            }
+
             if (dumpState.isDumping(DumpState.DUMP_VERIFIERS) && packageName == null) {
                 if (!checkin) {
                     if (dumpState.onTitlePrinted())
@@ -11508,7 +12030,9 @@
                         continue;
                     }
 
-                    final AsecInstallArgs args = new AsecInstallArgs(cid, isForwardLocked(ps));
+                    final AsecInstallArgs args = new AsecInstallArgs(cid,
+                            getAppInstructionSetFromSettings(ps),
+                            isForwardLocked(ps));
                     // The package status is changed only if the code path
                     // matches between settings and the container id.
                     if (ps.codePathString != null && ps.codePathString.equals(args.getCodePath())) {
@@ -11667,6 +12191,9 @@
                     | (regrantPermissions
                             ? (UPDATE_PERMISSIONS_REPLACE_PKG|UPDATE_PERMISSIONS_REPLACE_ALL)
                             : 0));
+
+            mSettings.updateExternalDatabaseVersion();
+
             // can downgrade to reader
             // Persist settings
             mSettings.writeLPr();
@@ -11823,15 +12350,17 @@
              * anyway.
              */
             if (returnCode != PackageManager.MOVE_SUCCEEDED) {
-                processPendingMove(new MoveParams(null, observer, 0, packageName,
+                processPendingMove(new MoveParams(null, observer, 0, packageName, null,
                         null, -1, user),
                         returnCode);
             } else {
                 Message msg = mHandler.obtainMessage(INIT_COPY);
+                final String instructionSet = getAppInstructionSet(pkg.applicationInfo);
                 InstallArgs srcArgs = createInstallArgs(currFlags, pkg.applicationInfo.sourceDir,
-                        pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir);
+                        pkg.applicationInfo.publicSourceDir, pkg.applicationInfo.nativeLibraryDir,
+                        instructionSet);
                 MoveParams mp = new MoveParams(srcArgs, observer, newFlags, packageName,
-                        pkg.applicationInfo.dataDir, pkg.applicationInfo.uid, user);
+                        pkg.applicationInfo.dataDir, instructionSet, pkg.applicationInfo.uid, user);
                 msg.obj = mp;
                 mHandler.sendMessage(msg);
             }
@@ -11898,8 +12427,17 @@
                                     final File newNativeDir = new File(newNativePath);
 
                                     if (!isForwardLocked(pkg) && !isExternal(pkg)) {
-                                        NativeLibraryHelper.copyNativeBinariesIfNeededLI(
-                                                new File(newCodePath), newNativeDir);
+                                        // NOTE: We do not report any errors from the APK scan and library
+                                        // copy at this point.
+                                        NativeLibraryHelper.ApkHandle handle =
+                                                new NativeLibraryHelper.ApkHandle(newCodePath);
+                                        final int abi = NativeLibraryHelper.findSupportedAbi(
+                                                handle, Build.SUPPORTED_ABIS);
+                                        if (abi >= 0) {
+                                            NativeLibraryHelper.copyNativeBinariesIfNeededLI(
+                                                    handle, newNativeDir, Build.SUPPORTED_ABIS[abi]);
+                                        }
+                                        handle.close();
                                     }
                                     final int[] users = sUserManager.getUserIds();
                                     for (int user : users) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index b447861..15df3d2 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -30,8 +30,8 @@
     SharedUserSetting sharedUser;
 
     PackageSetting(String name, String realName, File codePath, File resourcePath,
-            String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
-        super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
+            String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) {
+        super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode,
                 pkgFlags);
     }
 
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index 2a5698b9..c8af9d1 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -50,6 +50,7 @@
     File resourcePath;
     String resourcePathString;
     String nativeLibraryPathString;
+    String requiredCpuAbiString;
     long timeStamp;
     long firstInstallTime;
     long lastUpdateTime;
@@ -77,11 +78,11 @@
     /* package name of the app that installed this package */
     String installerPackageName;
     PackageSettingBase(String name, String realName, File codePath, File resourcePath,
-            String nativeLibraryPathString, int pVersionCode, int pkgFlags) {
+            String nativeLibraryPathString, String requiredCpuAbiString, int pVersionCode, int pkgFlags) {
         super(pkgFlags);
         this.name = name;
         this.realName = realName;
-        init(codePath, resourcePath, nativeLibraryPathString, pVersionCode);
+        init(codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode);
     }
 
     /**
@@ -98,6 +99,7 @@
         resourcePath = base.resourcePath;
         resourcePathString = base.resourcePathString;
         nativeLibraryPathString = base.nativeLibraryPathString;
+        requiredCpuAbiString = base.requiredCpuAbiString;
         timeStamp = base.timeStamp;
         firstInstallTime = base.firstInstallTime;
         lastUpdateTime = base.lastUpdateTime;
@@ -125,12 +127,13 @@
     }
 
     void init(File codePath, File resourcePath, String nativeLibraryPathString,
-            int pVersionCode) {
+            String requiredCpuAbiString, int pVersionCode) {
         this.codePath = codePath;
         this.codePathString = codePath.toString();
         this.resourcePath = resourcePath;
         this.resourcePathString = resourcePath.toString();
         this.nativeLibraryPathString = nativeLibraryPathString;
+        this.requiredCpuAbiString = requiredCpuAbiString;
         this.versionCode = pVersionCode;
     }
 
@@ -161,6 +164,7 @@
         grantedPermissions = base.grantedPermissions;
         gids = base.gids;
 
+        requiredCpuAbiString = base.requiredCpuAbiString;
         timeStamp = base.timeStamp;
         firstInstallTime = base.firstInstallTime;
         lastUpdateTime = base.lastUpdateTime;
diff --git a/services/core/java/com/android/server/pm/PendingPackage.java b/services/core/java/com/android/server/pm/PendingPackage.java
index c17cc46..36c3a34 100644
--- a/services/core/java/com/android/server/pm/PendingPackage.java
+++ b/services/core/java/com/android/server/pm/PendingPackage.java
@@ -22,8 +22,8 @@
     final int sharedId;
 
     PendingPackage(String name, String realName, File codePath, File resourcePath,
-            String nativeLibraryPathString, int sharedId, int pVersionCode, int pkgFlags) {
-        super(name, realName, codePath, resourcePath, nativeLibraryPathString, pVersionCode,
+            String nativeLibraryPathString, String requiredCpuAbiString, int sharedId, int pVersionCode, int pkgFlags) {
+        super(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString, pVersionCode,
                 pkgFlags);
         this.sharedId = sharedId;
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d1e34a1..599d2a7 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -36,6 +36,7 @@
 import com.android.internal.util.XmlUtils;
 import com.android.server.pm.PackageManagerService.DumpState;
 
+import java.util.Collection;
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
@@ -89,6 +90,34 @@
 final class Settings {
     private static final String TAG = "PackageSettings";
 
+    /**
+     * Current version of the package database. Set it to the latest version in
+     * the {@link DatabaseVersion} class below to ensure the database upgrade
+     * doesn't happen repeatedly.
+     * <p>
+     * Note that care should be taken to make sure all database upgrades are
+     * idempotent.
+     */
+    private static final int CURRENT_DATABASE_VERSION = DatabaseVersion.SIGNATURE_END_ENTITY;
+
+    /**
+     * This class contains constants that can be referred to from upgrade code.
+     * Insert constant values here that describe the upgrade reason. The version
+     * code must be monotonically increasing.
+     */
+    public static class DatabaseVersion {
+        /**
+         * The initial version of the database.
+         */
+        public static final int FIRST_VERSION = 1;
+
+        /**
+         * Migrating the Signature array from the entire certificate chain to
+         * just the signing certificate.
+         */
+        public static final int SIGNATURE_END_ENTITY = 2;
+    }
+
     private static final boolean DEBUG_STOPPED = false;
     private static final boolean DEBUG_MU = false;
 
@@ -102,6 +131,8 @@
     private static final String TAG_PACKAGE = "pkg";
     private static final String TAG_PERSISTENT_PREFERRED_ACTIVITIES =
             "persistent-preferred-activities";
+    static final String TAG_FORWARDING_INTENT_FILTERS =
+            "forwarding-intent-filters";
 
     private static final String ATTR_NAME = "name";
     private static final String ATTR_USER = "user";
@@ -133,6 +164,14 @@
     int mInternalSdkPlatform;
     int mExternalSdkPlatform;
 
+    /**
+     * The current database version for apps on internal storage. This is
+     * used to upgrade the format of the packages.xml database not necessarily
+     * tied to an SDK version.
+     */
+    int mInternalDatabaseVersion;
+    int mExternalDatabaseVersion;
+
     Boolean mReadExternalStorageEnforced;
 
     /** Device identity for the purpose of package verification. */
@@ -148,6 +187,10 @@
     final SparseArray<PersistentPreferredIntentResolver> mPersistentPreferredActivities =
             new SparseArray<PersistentPreferredIntentResolver>();
 
+    // For every user, it is used to find to which other users the intent can be forwarded.
+    final SparseArray<ForwardingIntentResolver> mForwardingIntentResolvers =
+            new SparseArray<ForwardingIntentResolver>();
+
     final HashMap<String, SharedUserSetting> mSharedUsers =
             new HashMap<String, SharedUserSetting>();
     private final ArrayList<Object> mUserIds = new ArrayList<Object>();
@@ -217,10 +260,10 @@
 
     PackageSetting getPackageLPw(PackageParser.Package pkg, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
-            String nativeLibraryPathString, int pkgFlags, UserHandle user, boolean add) {
+            String nativeLibraryPathString, String requiredCpuAbiString, int pkgFlags, UserHandle user, boolean add) {
         final String name = pkg.packageName;
         PackageSetting p = getPackageLPw(name, origPackage, realName, sharedUser, codePath,
-                resourcePath, nativeLibraryPathString, pkg.mVersionCode, pkgFlags,
+                resourcePath, nativeLibraryPathString, requiredCpuAbiString, pkg.mVersionCode, pkgFlags,
                 user, add, true /* allowInstall */);
         return p;
     }
@@ -266,6 +309,11 @@
         return s;
     }
 
+    Collection<SharedUserSetting> getAllSharedUsersLPw() {
+        return mSharedUsers.values();
+    }
+
+
     boolean disableSystemPackageLPw(String name) {
         final PackageSetting p = mPackages.get(name);
         if(p == null) {
@@ -302,7 +350,7 @@
             p.pkg.applicationInfo.flags &= ~ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
         PackageSetting ret = addPackageLPw(name, p.realName, p.codePath, p.resourcePath,
-                p.nativeLibraryPathString, p.appId, p.versionCode, p.pkgFlags);
+                p.nativeLibraryPathString, p.requiredCpuAbiString, p.appId, p.versionCode, p.pkgFlags);
         mDisabledSysPackages.remove(name);
         return ret;
     }
@@ -316,7 +364,7 @@
     }
 
     PackageSetting addPackageLPw(String name, String realName, File codePath, File resourcePath,
-            String nativeLibraryPathString, int uid, int vc, int pkgFlags) {
+            String nativeLibraryPathString, String requiredCpuAbiString, int uid, int vc, int pkgFlags) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
             if (p.appId == uid) {
@@ -326,7 +374,7 @@
                     "Adding duplicate package, keeping first: " + name);
             return null;
         }
-        p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString,
+        p = new PackageSetting(name, realName, codePath, resourcePath, nativeLibraryPathString, requiredCpuAbiString,
                 vc, pkgFlags);
         p.appId = uid;
         if (addUserIdLPw(uid, p, name)) {
@@ -395,10 +443,11 @@
 
     private PackageSetting getPackageLPw(String name, PackageSetting origPackage,
             String realName, SharedUserSetting sharedUser, File codePath, File resourcePath,
-            String nativeLibraryPathString, int vc, int pkgFlags,
+            String nativeLibraryPathString, String requiredCpuAbiString, int vc, int pkgFlags,
             UserHandle installUser, boolean add, boolean allowInstall) {
         PackageSetting p = mPackages.get(name);
         if (p != null) {
+            p.requiredCpuAbiString = requiredCpuAbiString;
             if (!p.codePath.equals(codePath)) {
                 // Check to see if its a disabled system app
                 if ((p.pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0) {
@@ -442,7 +491,7 @@
             if (origPackage != null) {
                 // We are consuming the data from an existing package.
                 p = new PackageSetting(origPackage.name, name, codePath, resourcePath,
-                        nativeLibraryPathString, vc, pkgFlags);
+                        nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags);
                 if (PackageManagerService.DEBUG_UPGRADE) Log.v(PackageManagerService.TAG, "Package "
                         + name + " is adopting original package " + origPackage.name);
                 // Note that we will retain the new package's signature so
@@ -459,7 +508,7 @@
                 p.setTimeStamp(codePath.lastModified());
             } else {
                 p = new PackageSetting(name, realName, codePath, resourcePath,
-                        nativeLibraryPathString, vc, pkgFlags);
+                        nativeLibraryPathString, requiredCpuAbiString, vc, pkgFlags);
                 p.setTimeStamp(codePath.lastModified());
                 p.sharedUser = sharedUser;
                 // If this is not a system app, it starts out stopped.
@@ -585,6 +634,8 @@
                 && !nativeLibraryPath.equalsIgnoreCase(p.nativeLibraryPathString)) {
             p.nativeLibraryPathString = nativeLibraryPath;
         }
+        // Update the required Cpu Abi
+        p.requiredCpuAbiString = pkg.applicationInfo.requiredCpuAbi;
         // Update version code if needed
         if (pkg.mVersionCode != p.versionCode) {
             p.versionCode = pkg.mVersionCode;
@@ -792,6 +843,15 @@
         return ppir;
     }
 
+    ForwardingIntentResolver editForwardingIntentResolverLPw(int userId) {
+        ForwardingIntentResolver fir = mForwardingIntentResolvers.get(userId);
+        if (fir == null) {
+            fir = new ForwardingIntentResolver();
+            mForwardingIntentResolvers.put(userId, fir);
+        }
+        return fir;
+    }
+
     private File getUserPackagesStateFile(int userId) {
         return new File(Environment.getUserSystemDirectory(userId), "package-restrictions.xml");
     }
@@ -822,6 +882,40 @@
         }
     }
 
+    /**
+     * Returns whether the current database has is older than {@code version}
+     * for apps on internal storage.
+     */
+    public boolean isInternalDatabaseVersionOlderThan(int version) {
+        return mInternalDatabaseVersion < version;
+    }
+
+    /**
+     * Returns whether the current database has is older than {@code version}
+     * for apps on external storage.
+     */
+    public boolean isExternalDatabaseVersionOlderThan(int version) {
+        return mExternalDatabaseVersion < version;
+    }
+
+    /**
+     * Updates the database version for apps on internal storage. Called after
+     * call the updates to the database format are done for apps on internal
+     * storage after the initial start-up scan.
+     */
+    public void updateInternalDatabaseVersion() {
+        mInternalDatabaseVersion = CURRENT_DATABASE_VERSION;
+    }
+
+    /**
+     * Updates the database version for apps on internal storage. Called after
+     * call the updates to the database format are done for apps on internal
+     * storage after the initial start-up scan.
+     */
+    public void updateExternalDatabaseVersion() {
+        mExternalDatabaseVersion = CURRENT_DATABASE_VERSION;
+    }
+
     private void readPreferredActivitiesLPw(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
         int outerDepth = parser.getDepth();
@@ -873,6 +967,28 @@
         }
     }
 
+    private void readForwardingIntentFiltersLPw(XmlPullParser parser, int userId)
+            throws XmlPullParserException, IOException {
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type == XmlPullParser.END_TAG || type == XmlPullParser.TEXT) {
+                continue;
+            }
+            String tagName = parser.getName();
+            if (tagName.equals(TAG_ITEM)) {
+                ForwardingIntentFilter fif = new ForwardingIntentFilter(parser);
+                editForwardingIntentResolverLPw(userId).addFilter(fif);
+            } else {
+                String msg = "Unknown element under " +  TAG_FORWARDING_INTENT_FILTERS + ": " +
+                        parser.getName();
+                PackageManagerService.reportSettingsProblem(Log.WARN, msg);
+                XmlUtils.skipCurrentTag(parser);
+            }
+        }
+    }
+
     void readPackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Reading package restrictions for user=" + userId);
@@ -1001,6 +1117,8 @@
                     readPreferredActivitiesLPw(parser, userId);
                 } else if (tagName.equals(TAG_PERSISTENT_PREFERRED_ACTIVITIES)) {
                     readPersistentPreferredActivitiesLPw(parser, userId);
+                } else if (tagName.equals(TAG_FORWARDING_INTENT_FILTERS)) {
+                    readForwardingIntentFiltersLPw(parser, userId);
                 } else {
                     Slog.w(PackageManagerService.TAG, "Unknown element under <stopped-packages>: "
                           + parser.getName());
@@ -1078,6 +1196,20 @@
         serializer.endTag(null, TAG_PERSISTENT_PREFERRED_ACTIVITIES);
     }
 
+    void writeForwardingIntentFiltersLPr(XmlSerializer serializer, int userId)
+            throws IllegalArgumentException, IllegalStateException, IOException {
+        serializer.startTag(null, TAG_FORWARDING_INTENT_FILTERS);
+        ForwardingIntentResolver fir = mForwardingIntentResolvers.get(userId);
+        if (fir != null) {
+            for (final ForwardingIntentFilter fif : fir.filterSet()) {
+                serializer.startTag(null, TAG_ITEM);
+                fif.writeToXml(serializer);
+                serializer.endTag(null, TAG_ITEM);
+            }
+        }
+        serializer.endTag(null, TAG_FORWARDING_INTENT_FILTERS);
+    }
+
     void writePackageRestrictionsLPr(int userId) {
         if (DEBUG_MU) {
             Log.i(TAG, "Writing package restrictions for user=" + userId);
@@ -1176,6 +1308,8 @@
 
             writePersistentPreferredActivitiesLPr(serializer, userId);
 
+            writeForwardingIntentFiltersLPr(serializer, userId);
+
             serializer.endTag(null, TAG_PACKAGE_RESTRICTIONS);
 
             serializer.endDocument();
@@ -1352,6 +1486,11 @@
             serializer.attribute(null, "external", Integer.toString(mExternalSdkPlatform));
             serializer.endTag(null, "last-platform-version");
 
+            serializer.startTag(null, "database-version");
+            serializer.attribute(null, "internal", Integer.toString(mInternalDatabaseVersion));
+            serializer.attribute(null, "external", Integer.toString(mExternalDatabaseVersion));
+            serializer.endTag(null, "database-version");
+
             if (mVerifierDeviceIdentity != null) {
                 serializer.startTag(null, "verifier");
                 serializer.attribute(null, "device", mVerifierDeviceIdentity.toString());
@@ -1551,6 +1690,9 @@
         if (pkg.nativeLibraryPathString != null) {
             serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
         }
+        if (pkg.requiredCpuAbiString != null) {
+           serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString);
+        }
         if (pkg.sharedUser == null) {
             serializer.attribute(null, "userId", Integer.toString(pkg.appId));
         } else {
@@ -1593,6 +1735,9 @@
         if (pkg.nativeLibraryPathString != null) {
             serializer.attribute(null, "nativeLibraryPath", pkg.nativeLibraryPathString);
         }
+        if (pkg.requiredCpuAbiString != null) {
+           serializer.attribute(null, "requiredCpuAbi", pkg.requiredCpuAbiString);
+        }
         serializer.attribute(null, "flags", Integer.toString(pkg.pkgFlags));
         serializer.attribute(null, "ft", Long.toHexString(pkg.timeStamp));
         serializer.attribute(null, "it", Long.toHexString(pkg.firstInstallTime));
@@ -1782,6 +1927,10 @@
                     // TODO: check whether this is okay! as it is very
                     // similar to how preferred-activities are treated
                     readPersistentPreferredActivitiesLPw(parser, 0);
+                } else if (tagName.equals(TAG_FORWARDING_INTENT_FILTERS)) {
+                    // TODO: check whether this is okay! as it is very
+                    // similar to how preferred-activities are treated
+                    readForwardingIntentFiltersLPw(parser, 0);
                 } else if (tagName.equals("updated-package")) {
                     readDisabledSysPackageLPw(parser);
                 } else if (tagName.equals("cleaning-package")) {
@@ -1821,6 +1970,19 @@
                         }
                     } catch (NumberFormatException e) {
                     }
+                } else if (tagName.equals("database-version")) {
+                    mInternalDatabaseVersion = mExternalDatabaseVersion = 0;
+                    try {
+                        String internalDbVersionString = parser.getAttributeValue(null, "internal");
+                        if (internalDbVersionString != null) {
+                            mInternalDatabaseVersion = Integer.parseInt(internalDbVersionString);
+                        }
+                        String externalDbVersionString = parser.getAttributeValue(null, "external");
+                        if (externalDbVersionString != null) {
+                            mExternalDatabaseVersion = Integer.parseInt(externalDbVersionString);
+                        }
+                    } catch (NumberFormatException ignored) {
+                    }
                 } else if (tagName.equals("verifier")) {
                     final String deviceIdentity = parser.getAttributeValue(null, "device");
                     try {
@@ -1861,7 +2023,7 @@
             if (idObj != null && idObj instanceof SharedUserSetting) {
                 PackageSetting p = getPackageLPw(pp.name, null, pp.realName,
                         (SharedUserSetting) idObj, pp.codePath, pp.resourcePath,
-                        pp.nativeLibraryPathString, pp.versionCode, pp.pkgFlags,
+                        pp.nativeLibraryPathString, pp.requiredCpuAbiString, pp.versionCode, pp.pkgFlags,
                         null, true /* add */, false /* allowInstall */);
                 if (p == null) {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
@@ -2281,6 +2443,8 @@
         String codePathStr = parser.getAttributeValue(null, "codePath");
         String resourcePathStr = parser.getAttributeValue(null, "resourcePath");
         String nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
+        String requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
+
         if (resourcePathStr == null) {
             resourcePathStr = codePathStr;
         }
@@ -2300,7 +2464,7 @@
             pkgFlags |= ApplicationInfo.FLAG_PRIVILEGED;
         }
         PackageSetting ps = new PackageSetting(name, realName, codePathFile,
-                new File(resourcePathStr), nativeLibraryPathStr, versionCode, pkgFlags);
+                new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, versionCode, pkgFlags);
         String timeStampStr = parser.getAttributeValue(null, "ft");
         if (timeStampStr != null) {
             try {
@@ -2367,6 +2531,7 @@
         String codePathStr = null;
         String resourcePathStr = null;
         String nativeLibraryPathStr = null;
+        String requiredCpuAbiString = null;
         String systemStr = null;
         String installerPackageName = null;
         String uidError = null;
@@ -2386,6 +2551,8 @@
             codePathStr = parser.getAttributeValue(null, "codePath");
             resourcePathStr = parser.getAttributeValue(null, "resourcePath");
             nativeLibraryPathStr = parser.getAttributeValue(null, "nativeLibraryPath");
+            requiredCpuAbiString = parser.getAttributeValue(null, "requiredCpuAbi");
+
             version = parser.getAttributeValue(null, "version");
             if (version != null) {
                 try {
@@ -2462,7 +2629,7 @@
                                 + parser.getPositionDescription());
             } else if (userId > 0) {
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
-                        new File(resourcePathStr), nativeLibraryPathStr, userId, versionCode,
+                        new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId, versionCode,
                         pkgFlags);
                 if (PackageManagerService.DEBUG_SETTINGS)
                     Log.i(PackageManagerService.TAG, "Reading package " + name + ": userId="
@@ -2480,7 +2647,7 @@
                 userId = sharedIdStr != null ? Integer.parseInt(sharedIdStr) : 0;
                 if (userId > 0) {
                     packageSetting = new PendingPackage(name.intern(), realName, new File(
-                            codePathStr), new File(resourcePathStr), nativeLibraryPathStr, userId,
+                            codePathStr), new File(resourcePathStr), nativeLibraryPathStr, requiredCpuAbiString, userId,
                             versionCode, pkgFlags);
                     packageSetting.setTimeStamp(timeStamp);
                     packageSetting.firstInstallTime = firstInstallTime;
@@ -2509,6 +2676,7 @@
             packageSetting.uidError = "true".equals(uidError);
             packageSetting.installerPackageName = installerPackageName;
             packageSetting.nativeLibraryPathString = nativeLibraryPathStr;
+            packageSetting.requiredCpuAbiString = requiredCpuAbiString;
             // Handle legacy string here for single-user mode
             final String enabledStr = parser.getAttributeValue(null, ATTR_ENABLED);
             if (enabledStr != null) {
@@ -3008,6 +3176,7 @@
         pw.print(prefix); pw.print("  codePath="); pw.println(ps.codePathString);
         pw.print(prefix); pw.print("  resourcePath="); pw.println(ps.resourcePathString);
         pw.print(prefix); pw.print("  nativeLibraryPath="); pw.println(ps.nativeLibraryPathString);
+        pw.print(prefix); pw.print("  requiredCpuAbi="); pw.println(ps.requiredCpuAbiString);
         pw.print(prefix); pw.print("  versionCode="); pw.print(ps.versionCode);
         if (ps.pkg != null) {
             pw.print(" targetSdk="); pw.print(ps.pkg.applicationInfo.targetSdkVersion);
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index 32515b5..14df347 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -257,24 +257,37 @@
     }
 
     @Override
-    public List<UserInfo> getProfiles(int userId) {
+    public List<UserInfo> getProfiles(int userId, boolean enabledOnly) {
         if (userId != UserHandle.getCallingUserId()) {
             checkManageUsersPermission("getting profiles related to user " + userId);
         }
-        synchronized (mPackagesLock) {
-            UserInfo user = getUserInfoLocked(userId);
-            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
-            for (int i = 0; i < mUsers.size(); i++) {
-                UserInfo profile = mUsers.valueAt(i);
-                if (!isProfileOf(user, profile)) {
-                    continue;
-                }
-                users.add(profile);
+        final long ident = Binder.clearCallingIdentity();
+        try {
+            synchronized (mPackagesLock) {
+                return getProfilesLocked(userId, enabledOnly);
             }
-            return users;
+        } finally {
+            Binder.restoreCallingIdentity(ident);
         }
     }
 
+    /** Assume permissions already checked and caller's identity cleared */
+    private List<UserInfo> getProfilesLocked(int userId, boolean enabledOnly) {
+        UserInfo user = getUserInfoLocked(userId);
+        ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
+        for (int i = 0; i < mUsers.size(); i++) {
+            UserInfo profile = mUsers.valueAt(i);
+            if (!isProfileOf(user, profile)) {
+                continue;
+            }
+            if (enabledOnly && !profile.isEnabled()) {
+                continue;
+            }
+            users.add(profile);
+        }
+        return users;
+    }
+
     private boolean isProfileOf(UserInfo user, UserInfo profile) {
         return user.id == profile.id ||
                 (user.profileGroupId != UserInfo.NO_PROFILE_GROUP_ID
@@ -282,6 +295,18 @@
     }
 
     @Override
+    public void setUserEnabled(int userId) {
+        checkManageUsersPermission("enable user");
+        synchronized (mPackagesLock) {
+            UserInfo info = getUserInfoLocked(userId);
+            if (info != null && !info.isEnabled()) {
+                info.flags ^= UserInfo.FLAG_DISABLED;
+                writeUserLocked(info);
+            }
+        }
+    }
+
+    @Override
     public UserInfo getUserInfo(int userId) {
         checkManageUsersPermission("query user");
         synchronized (mPackagesLock) {
@@ -431,7 +456,7 @@
 
         synchronized (mPackagesLock) {
             Bundle restrictions = mUserRestrictions.get(userId);
-            return restrictions != null ? restrictions : Bundle.EMPTY;
+            return restrictions != null ? new Bundle(restrictions) : new Bundle();
         }
     }
 
@@ -1194,6 +1219,12 @@
             // Write the restrictions to XML
             writeApplicationRestrictionsLocked(packageName, restrictions, userId);
         }
+
+        // Notify package of changes via an intent - only sent to explicitly registered receivers.
+        Intent changeIntent = new Intent(Intent.ACTION_APPLICATION_RESTRICTIONS_CHANGED);
+        changeIntent.setPackage(packageName);
+        changeIntent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        mContext.sendBroadcastAsUser(changeIntent, new UserHandle(userId));
     }
 
     @Override
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index f72efff..d84e8e1 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -28,6 +28,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.hardware.input.InputManagerInternal;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -86,6 +87,7 @@
     private final ScreenOnBlocker mScreenOnBlocker;
     private final WindowManagerPolicy mPolicy;
     private final ActivityManagerInternal mActivityManagerInternal;
+    private final InputManagerInternal mInputManagerInternal;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -121,6 +123,7 @@
         mScreenOnBlocker = screenOnBlocker;
         mPolicy = policy;
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
 
         mHandler = new NotifierHandler(looper);
         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
@@ -232,73 +235,58 @@
     }
 
     /**
-     * Called when the device is waking up from sleep and the
-     * display is about to be turned on.
+     * Notifies that the device is changing interactive state.
      */
-    public void onWakeUpStarted() {
+    public void onInteractiveStateChangeStarted(boolean interactive, int reason) {
         if (DEBUG) {
-            Slog.d(TAG, "onWakeUpStarted");
+            Slog.d(TAG, "onInteractiveChangeStarted: interactive=" + interactive
+                    + ", reason=" + reason);
         }
 
         synchronized (mLock) {
-            if (mActualPowerState != POWER_STATE_AWAKE) {
-                mActualPowerState = POWER_STATE_AWAKE;
-                mPendingWakeUpBroadcast = true;
-                if (!mScreenOnBlockerAcquired) {
-                    mScreenOnBlockerAcquired = true;
-                    mScreenOnBlocker.acquire();
+            if (interactive) {
+                // Waking up...
+                if (mActualPowerState != POWER_STATE_AWAKE) {
+                    mActualPowerState = POWER_STATE_AWAKE;
+                    mPendingWakeUpBroadcast = true;
+                    if (!mScreenOnBlockerAcquired) {
+                        mScreenOnBlockerAcquired = true;
+                        mScreenOnBlocker.acquire();
+                    }
+                    updatePendingBroadcastLocked();
                 }
-                updatePendingBroadcastLocked();
+            } else {
+                // Going to sleep...
+                mLastGoToSleepReason = reason;
             }
+            mInputManagerInternal.setInteractive(interactive);
         }
     }
 
     /**
-     * Called when the device has finished waking up from sleep
-     * and the display has been turned on.
+     * Notifies that the device has finished changing interactive state.
      */
-    public void onWakeUpFinished() {
+    public void onInteractiveStateChangeFinished(boolean interactive) {
         if (DEBUG) {
-            Slog.d(TAG, "onWakeUpFinished");
-        }
-    }
-
-    /**
-     * Called when the device is going to sleep.
-     */
-    public void onGoToSleepStarted(int reason) {
-        if (DEBUG) {
-            Slog.d(TAG, "onGoToSleepStarted");
+            Slog.d(TAG, "onInteractiveChangeFinished");
         }
 
         synchronized (mLock) {
-            mLastGoToSleepReason = reason;
-        }
-    }
-
-    /**
-     * Called when the device has finished going to sleep and the
-     * display has been turned off.
-     *
-     * This is a good time to make transitions that we don't want the user to see,
-     * such as bringing the key guard to focus.  There's no guarantee for this,
-     * however because the user could turn the device on again at any time.
-     * Some things may need to be protected by other mechanisms that defer screen on.
-     */
-    public void onGoToSleepFinished() {
-        if (DEBUG) {
-            Slog.d(TAG, "onGoToSleepFinished");
-        }
-
-        synchronized (mLock) {
-            if (mActualPowerState != POWER_STATE_ASLEEP) {
-                mActualPowerState = POWER_STATE_ASLEEP;
-                mPendingGoToSleepBroadcast = true;
-                if (mUserActivityPending) {
-                    mUserActivityPending = false;
-                    mHandler.removeMessages(MSG_USER_ACTIVITY);
+            if (!interactive) {
+                // Finished going to sleep...
+                // This is a good time to make transitions that we don't want the user to see,
+                // such as bringing the key guard to focus.  There's no guarantee for this,
+                // however because the user could turn the device on again at any time.
+                // Some things may need to be protected by other mechanisms that defer screen on.
+                if (mActualPowerState != POWER_STATE_ASLEEP) {
+                    mActualPowerState = POWER_STATE_ASLEEP;
+                    mPendingGoToSleepBroadcast = true;
+                    if (mUserActivityPending) {
+                        mUserActivityPending = false;
+                        mHandler.removeMessages(MSG_USER_ACTIVITY);
+                    }
+                    updatePendingBroadcastLocked();
                 }
-                updatePendingBroadcastLocked();
             }
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 90363d7..cfe24fe 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -62,6 +62,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.TimeUtils;
+import android.view.Display;
 import android.view.WindowManagerPolicy;
 
 import java.io.FileDescriptor;
@@ -167,6 +168,10 @@
     // Poll interval in milliseconds for watching boot animation finished.
     private static final int BOOT_ANIMATION_POLL_INTERVAL = 200;
 
+    //powerHint
+    private static final int POWER_HINT_LOW_POWER_MODE = 5;
+    private static boolean mLowPowerModeEnabled;
+
     private final Context mContext;
     private LightsManager mLightsManager;
     private BatteryService mBatteryService;
@@ -209,6 +214,10 @@
     // A bitfield that summarizes the state of all active wakelocks.
     private int mWakeLockSummary;
 
+    // True if the device is in an interactive state.
+    private boolean mInteractive;
+    private boolean mInteractiveChanging;
+
     // If true, instructs the display controller to wait for the proximity sensor to
     // go negative before turning the screen on.
     private boolean mRequestWaitForNegativeProximity;
@@ -217,11 +226,6 @@
     private long mLastWakeTime;
     private long mLastSleepTime;
 
-    // True if we need to send a wake up or go to sleep finished notification
-    // when the display is ready.
-    private boolean mSendWakeUpFinishedNotificationWhenReady;
-    private boolean mSendGoToSleepFinishedNotificationWhenReady;
-
     // Timestamp of the last call to user activity.
     private long mLastUserActivityTime;
     private long mLastUserActivityTimeNoChangeLights;
@@ -265,11 +269,11 @@
 
     // True if auto-suspend mode is enabled.
     // Refer to autosuspend.h.
-    private boolean mAutoSuspendModeEnabled;
+    private boolean mHalAutoSuspendModeEnabled;
 
     // True if interactive mode is enabled.
     // Refer to power.h.
-    private boolean mInteractiveModeEnabled;
+    private boolean mHalInteractiveModeEnabled;
 
     // True if the device is plugged into a power source.
     private boolean mIsPowered;
@@ -289,10 +293,10 @@
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
     // True to decouple auto-suspend mode from the display state.
-    private boolean mDecoupleAutoSuspendModeFromDisplayConfig;
+    private boolean mDecoupleHalAutoSuspendModeFromDisplayConfig;
 
     // True to decouple interactive mode from the display state.
-    private boolean mDecoupleInteractiveModeFromDisplayConfig;
+    private boolean mDecoupleHalInteractiveModeFromDisplayConfig;
 
     // True if the device should wake up when plugged or unplugged.
     private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
@@ -397,7 +401,6 @@
 
     private native void nativeInit();
 
-    private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
     private static native void nativeAcquireSuspendBlocker(String name);
     private static native void nativeReleaseSuspendBlocker(String name);
     private static native void nativeSetInteractive(boolean enable);
@@ -412,13 +415,17 @@
             mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
             mDisplaySuspendBlocker.acquire();
             mHoldingDisplaySuspendBlocker = true;
+            mHalAutoSuspendModeEnabled = false;
+            mHalInteractiveModeEnabled = true;
 
             mScreenOnBlocker = new ScreenOnBlockerImpl();
             mWakefulness = WAKEFULNESS_AWAKE;
-        }
+            mInteractive = true;
 
-        nativeInit();
-        nativeSetPowerState(true, true);
+            nativeInit();
+            nativeSetAutoSuspend(false);
+            nativeSetInteractive(true);
+        }
     }
 
     @Override
@@ -446,14 +453,6 @@
 
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
-
-        // Forcibly turn the screen on at boot so that it is in a known power state.
-        // We do this in init() rather than in the constructor because setting the
-        // screen state requires a call into surface flinger which then needs to call back
-        // into the activity manager to check permissions.  Unfortunately the
-        // activity manager is not running when the constructor is called, so we
-        // have to defer setting the screen state until this point.
-        mDisplayPowerCallbacks.unblankAllDisplays();
     }
 
     void setPolicy(WindowManagerPolicy policy) {
@@ -535,7 +534,9 @@
             resolver.registerContentObserver(Settings.System.getUriFor(
                     Settings.System.SCREEN_BRIGHTNESS_MODE),
                     false, mSettingsObserver, UserHandle.USER_ALL);
-
+            resolver.registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.LOW_POWER_MODE),
+                    false, mSettingsObserver, UserHandle.USER_ALL);
             // Go.
             readConfigurationLocked();
             updateSettingsLocked();
@@ -547,9 +548,9 @@
     private void readConfigurationLocked() {
         final Resources resources = mContext.getResources();
 
-        mDecoupleAutoSuspendModeFromDisplayConfig = resources.getBoolean(
+        mDecoupleHalAutoSuspendModeFromDisplayConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay);
-        mDecoupleInteractiveModeFromDisplayConfig = resources.getBoolean(
+        mDecoupleHalInteractiveModeFromDisplayConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
         mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_unplugTurnsOnScreen);
@@ -615,6 +616,14 @@
                 Settings.System.SCREEN_BRIGHTNESS_MODE,
                 Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL, UserHandle.USER_CURRENT);
 
+        boolean mIsEnabled = Settings.Global.getInt(resolver,
+            Settings.Global.LOW_POWER_MODE, 0) != 0;
+        if (mIsEnabled != mLowPowerModeEnabled) {
+            BinderService bs = new BinderService();
+            bs.powerHint(POWER_HINT_LOW_POWER_MODE, mIsEnabled ? 1 : 0);
+            mLowPowerModeEnabled = mIsEnabled;
+        }
+
         mDirty |= DIRTY_SETTINGS;
     }
 
@@ -867,11 +876,6 @@
         return false;
     }
 
-    // Called from native code.
-    private void wakeUpFromNative(long eventTime) {
-        wakeUpInternal(eventTime);
-    }
-
     private void wakeUpInternal(long eventTime) {
         synchronized (mLock) {
             if (wakeUpNoUpdateLocked(eventTime)) {
@@ -902,26 +906,16 @@
                 break;
         }
 
-        if (mWakefulness != WAKEFULNESS_DREAMING) {
-            sendPendingNotificationsLocked();
-            mNotifier.onWakeUpStarted();
-            mSendWakeUpFinishedNotificationWhenReady = true;
-        }
-
         mLastWakeTime = eventTime;
-        mWakefulness = WAKEFULNESS_AWAKE;
         mDirty |= DIRTY_WAKEFULNESS;
+        mWakefulness = WAKEFULNESS_AWAKE;
+        setInteractiveStateLocked(true, 0);
 
         userActivityNoUpdateLocked(
                 eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
         return true;
     }
 
-    // Called from native code.
-    private void goToSleepFromNative(long eventTime, int reason) {
-        goToSleepInternal(eventTime, reason);
-    }
-
     private void goToSleepInternal(long eventTime, int reason) {
         synchronized (mLock) {
             if (goToSleepNoUpdateLocked(eventTime, reason)) {
@@ -958,14 +952,11 @@
                 break;
         }
 
-        sendPendingNotificationsLocked();
-        mNotifier.onGoToSleepStarted(reason);
-        mSendGoToSleepFinishedNotificationWhenReady = true;
-
         mLastSleepTime = eventTime;
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_DOZING;
         mSandmanSummoned = true;
+        setInteractiveStateLocked(false, reason);
 
         // Report the number of wake locks that will be cleared by going to sleep.
         int numWakeLocksCleared = 0;
@@ -1007,6 +998,7 @@
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_DREAMING;
         mSandmanSummoned = true;
+        setInteractiveStateLocked(true, 0);
         return true;
     }
 
@@ -1025,9 +1017,27 @@
 
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_ASLEEP;
+        setInteractiveStateLocked(false, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
         return true;
     }
 
+    private void setInteractiveStateLocked(boolean interactive, int reason) {
+        if (mInteractive != interactive) {
+            finishInteractiveStateChangeLocked();
+
+            mInteractive = interactive;
+            mInteractiveChanging = true;
+            mNotifier.onInteractiveStateChangeStarted(interactive, reason);
+        }
+    }
+
+    private void finishInteractiveStateChangeLocked() {
+        if (mInteractiveChanging) {
+            mNotifier.onInteractiveStateChangeFinished(mInteractive);
+            mInteractiveChanging = false;
+        }
+    }
+
     /**
      * Updates the global power state based on dirty bits recorded in mDirty.
      *
@@ -1071,7 +1081,7 @@
 
         // Phase 3: Send notifications, if needed.
         if (mDisplayReady) {
-            sendPendingNotificationsLocked();
+            finishInteractiveStateChangeLocked();
         }
 
         // Phase 4: Update suspend blocker.
@@ -1080,17 +1090,6 @@
         updateSuspendBlockerLocked();
     }
 
-    private void sendPendingNotificationsLocked() {
-        if (mSendWakeUpFinishedNotificationWhenReady) {
-            mSendWakeUpFinishedNotificationWhenReady = false;
-            mNotifier.onWakeUpFinished();
-        }
-        if (mSendGoToSleepFinishedNotificationWhenReady) {
-            mSendGoToSleepFinishedNotificationWhenReady = false;
-            mNotifier.onGoToSleepFinished();
-        }
-    }
-
     /**
      * Updates the value of mIsPowered.
      * Sets DIRTY_IS_POWERED if a change occurred.
@@ -1210,48 +1209,45 @@
                         mWakeLockSummary |= WAKE_LOCK_CPU;
                         break;
                     case PowerManager.FULL_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU
-                                    | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
                         break;
                     case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
                         break;
                     case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
                         break;
                     case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING
-                                || mWakefulness == WAKEFULNESS_DOZING) {
-                            mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
                         break;
                     case PowerManager.DOZE_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_DOZING) {
-                            mWakeLockSummary |= WAKE_LOCK_DOZE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_DOZE;
                         break;
                 }
             }
 
+            // Cancel wake locks that make no sense based on the current state.
+            if (mWakefulness != WAKEFULNESS_DOZING) {
+                mWakeLockSummary &= ~WAKE_LOCK_DOZE;
+            }
+            if (mWakefulness == WAKEFULNESS_ASLEEP
+                    || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+                mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
+                        | WAKE_LOCK_BUTTON_BRIGHT);
+                if (mWakefulness == WAKEFULNESS_ASLEEP) {
+                    mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
+                }
+            }
+
+            // Infer implied wake locks where necessary based on the current state.
+            if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
+                if (mWakefulness == WAKEFULNESS_AWAKE) {
+                    mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
+                } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+                    mWakeLockSummary |= WAKE_LOCK_CPU;
+                }
+            }
+
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
                         + wakefulnessToString(mWakefulness)
@@ -1269,12 +1265,14 @@
      */
     private void updateUserActivitySummaryLocked(long now, int dirty) {
         // Update the status of the user activity timeout timer.
-        if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
+                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
             mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
 
             long nextTimeout = 0;
             if (mWakefulness == WAKEFULNESS_AWAKE
-                    || mWakefulness == WAKEFULNESS_DREAMING) {
+                    || mWakefulness == WAKEFULNESS_DREAMING
+                    || mWakefulness == WAKEFULNESS_DOZING) {
                 final int screenOffTimeout = getScreenOffTimeoutLocked();
                 final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
 
@@ -1598,8 +1596,6 @@
                 | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
             final int newScreenState = getDesiredScreenPowerStateLocked();
             mDisplayPowerRequest.screenState = newScreenState;
-            nativeSetPowerState(isScreenOnLocked(),
-                    newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
 
             int screenBrightness = mScreenBrightnessSettingDefault;
             float screenAutoBrightnessAdjustment = 0.0f;
@@ -1681,7 +1677,7 @@
 
     private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
             new DisplayManagerInternal.DisplayPowerCallbacks() {
-        private boolean mBlanked;
+        private int mDisplayState = Display.STATE_UNKNOWN;
 
         @Override
         public void onStateChanged() {
@@ -1712,6 +1708,33 @@
         }
 
         @Override
+        public void onDisplayStateChange(int state) {
+            // This method is only needed to support legacy display blanking behavior
+            // where the display's power state is coupled to suspend or to the power HAL.
+            // The order of operations matters here.
+            synchronized (mLock) {
+                if (mDisplayState != state) {
+                    mDisplayState = state;
+                    if (state == Display.STATE_OFF) {
+                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                            setHalInteractiveModeLocked(false);
+                        }
+                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                            setHalAutoSuspendModeLocked(true);
+                        }
+                    } else {
+                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                            setHalAutoSuspendModeLocked(false);
+                        }
+                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                            setHalInteractiveModeLocked(true);
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
         public void acquireSuspendBlocker() {
             mDisplaySuspendBlocker.acquire();
         }
@@ -1722,37 +1745,9 @@
         }
 
         @Override
-        public void blankAllDisplays() {
-            synchronized (this) {
-                mBlanked = true;
-                mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
-                if (!mDecoupleInteractiveModeFromDisplayConfig) {
-                    setInteractiveModeLocked(false);
-                }
-                if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
-                    setAutoSuspendModeLocked(true);
-                }
-            }
-        }
-
-        @Override
-        public void unblankAllDisplays() {
-            synchronized (this) {
-                if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
-                    setAutoSuspendModeLocked(false);
-                }
-                if (!mDecoupleInteractiveModeFromDisplayConfig) {
-                    setInteractiveModeLocked(true);
-                }
-                mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
-                mBlanked = false;
-            }
-        }
-
-        @Override
         public String toString() {
             synchronized (this) {
-                return "blanked=" + mBlanked;
+                return "state=" + Display.stateToString(mDisplayState);
             }
         }
     };
@@ -1773,11 +1768,11 @@
 
         // Disable auto-suspend if needed.
         if (!autoSuspend) {
-            if (mDecoupleAutoSuspendModeFromDisplayConfig) {
-                setAutoSuspendModeLocked(false);
+            if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                setHalAutoSuspendModeLocked(false);
             }
-            if (mDecoupleInteractiveModeFromDisplayConfig) {
-                setInteractiveModeLocked(true);
+            if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+                setHalInteractiveModeLocked(true);
             }
         }
 
@@ -1803,11 +1798,11 @@
 
         // Enable auto-suspend if needed.
         if (autoSuspend) {
-            if (mDecoupleInteractiveModeFromDisplayConfig) {
-                setInteractiveModeLocked(false);
+            if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+                setHalInteractiveModeLocked(false);
             }
-            if (mDecoupleAutoSuspendModeFromDisplayConfig) {
-                setAutoSuspendModeLocked(true);
+            if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                setHalAutoSuspendModeLocked(true);
             }
         }
     }
@@ -1834,42 +1829,32 @@
         return false;
     }
 
-    private void setAutoSuspendModeLocked(boolean enable) {
-        if (enable != mAutoSuspendModeEnabled) {
+    private void setHalAutoSuspendModeLocked(boolean enable) {
+        if (enable != mHalAutoSuspendModeEnabled) {
             if (DEBUG) {
-                Slog.d(TAG, "Setting auto-suspend mode to " + enable);
+                Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
             }
-            mAutoSuspendModeEnabled = enable;
+            mHalAutoSuspendModeEnabled = enable;
             nativeSetAutoSuspend(enable);
         }
     }
 
-    private void setInteractiveModeLocked(boolean enable) {
-        if (enable != mInteractiveModeEnabled) {
+    private void setHalInteractiveModeLocked(boolean enable) {
+        if (enable != mHalInteractiveModeEnabled) {
             if (DEBUG) {
-                Slog.d(TAG, "Setting interactive mode to " + enable);
+                Slog.d(TAG, "Setting HAL interactive mode to " + enable);
             }
-            mInteractiveModeEnabled = enable;
+            mHalInteractiveModeEnabled = enable;
             nativeSetInteractive(enable);
         }
     }
 
-    private boolean isScreenOnInternal() {
+    private boolean isInteractiveInternal() {
         synchronized (mLock) {
-            // XXX This is a temporary hack to let certain parts of the system pretend the
-            // screen is still on even when dozing and we would normally want to report
-            // screen off.  Will be removed when the window manager is modified to use
-            // the true blanking state of the display.
-            return isScreenOnLocked()
-                    || mWakefulness == WAKEFULNESS_DOZING;
+            return mInteractive;
         }
     }
 
-    private boolean isScreenOnLocked() {
-        return mWakefulness == WAKEFULNESS_AWAKE
-                || mWakefulness == WAKEFULNESS_DREAMING;
-    }
-
     private void handleBatteryStateChangedLocked() {
         mDirty |= DIRTY_BATTERY_STATE;
         updatePowerStateLocked();
@@ -2090,6 +2075,7 @@
             pw.println("Power Manager State:");
             pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
             pw.println("  mWakefulness=" + wakefulnessToString(mWakefulness));
+            pw.println("  mInteractive=" + mInteractive);
             pw.println("  mIsPowered=" + mIsPowered);
             pw.println("  mPlugType=" + mPlugType);
             pw.println("  mBatteryLevel=" + mBatteryLevel);
@@ -2099,8 +2085,8 @@
             pw.println("  mProximityPositive=" + mProximityPositive);
             pw.println("  mBootCompleted=" + mBootCompleted);
             pw.println("  mSystemReady=" + mSystemReady);
-            pw.println("  mAutoSuspendModeEnabled=" + mAutoSuspendModeEnabled);
-            pw.println("  mInteactiveModeEnabled=" + mInteractiveModeEnabled);
+            pw.println("  mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
+            pw.println("  mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
             pw.println("  mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
             pw.println("  mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
             pw.println("  mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
@@ -2108,10 +2094,6 @@
             pw.println("  mSandmanSummoned=" + mSandmanSummoned);
             pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
             pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
-            pw.println("  mSendWakeUpFinishedNotificationWhenReady="
-                    + mSendWakeUpFinishedNotificationWhenReady);
-            pw.println("  mSendGoToSleepFinishedNotificationWhenReady="
-                    + mSendGoToSleepFinishedNotificationWhenReady);
             pw.println("  mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
             pw.println("  mLastUserActivityTimeNoChangeLights="
                     + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
@@ -2121,10 +2103,10 @@
 
             pw.println();
             pw.println("Settings and Configuration:");
-            pw.println("  mDecoupleAutoSuspendModeFromDisplayConfig="
-                    + mDecoupleAutoSuspendModeFromDisplayConfig);
-            pw.println("  mDecoupleInteractiveModeFromDisplayConfig="
-                    + mDecoupleInteractiveModeFromDisplayConfig);
+            pw.println("  mDecoupleHalAutoSuspendModeFromDisplayConfig="
+                    + mDecoupleHalAutoSuspendModeFromDisplayConfig);
+            pw.println("  mDecoupleHalInteractiveModeFromDisplayConfig="
+                    + mDecoupleHalInteractiveModeFromDisplayConfig);
             pw.println("  mWakeUpWhenPluggedOrUnpluggedConfig="
                     + mWakeUpWhenPluggedOrUnpluggedConfig);
             pw.println("  mSuspendWhenScreenOffDueToProximityConfig="
@@ -2725,10 +2707,10 @@
         }
 
         @Override // Binder call
-        public boolean isScreenOn() {
+        public boolean isInteractive() {
             final long ident = Binder.clearCallingIdentity();
             try {
-                return isScreenOnInternal();
+                return isInteractiveInternal();
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index e4b5f3a..91f796b 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -588,6 +588,19 @@
     }
 
     @Override
+    public void onNotificationVisibilityChanged(
+            String[] newlyVisibleKeys, String[] noLongerVisibleKeys) throws RemoteException {
+        enforceStatusBarService();
+        long identity = Binder.clearCallingIdentity();
+        try {
+            mNotificationDelegate.onNotificationVisibilityChanged(
+                    newlyVisibleKeys, noLongerVisibleKeys);
+        } finally {
+            Binder.restoreCallingIdentity(identity);
+        }
+    }
+
+    @Override
     public void onClearAllNotifications(int userId) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
diff --git a/services/core/java/com/android/server/trust/TrustManagerService.java b/services/core/java/com/android/server/trust/TrustManagerService.java
index a2a49c9..9061f96 100644
--- a/services/core/java/com/android/server/trust/TrustManagerService.java
+++ b/services/core/java/com/android/server/trust/TrustManagerService.java
@@ -187,7 +187,7 @@
 
         boolean trustMayHaveChanged = false;
         for (int i = 0; i < mObsoleteAgents.size(); i++) {
-            AgentInfo info = mActiveAgents.valueAt(i);
+            AgentInfo info = mObsoleteAgents.valueAt(i);
             if (info.agent.isTrusted()) {
                 trustMayHaveChanged = true;
             }
diff --git a/services/core/java/com/android/server/tv/TvInputManagerService.java b/services/core/java/com/android/server/tv/TvInputManagerService.java
index 79c4a50..50dd27d 100644
--- a/services/core/java/com/android/server/tv/TvInputManagerService.java
+++ b/services/core/java/com/android/server/tv/TvInputManagerService.java
@@ -19,6 +19,9 @@
 import android.app.ActivityManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.ContentValues;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -26,12 +29,18 @@
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
+import android.database.Cursor;
+import android.graphics.Rect;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
+import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.UserHandle;
+import android.provider.TvContract;
 import android.tv.ITvInputClient;
 import android.tv.ITvInputManager;
 import android.tv.ITvInputService;
@@ -40,12 +49,14 @@
 import android.tv.ITvInputSessionCallback;
 import android.tv.TvInputInfo;
 import android.tv.TvInputService;
-import android.util.ArrayMap;
-import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
+import android.view.InputChannel;
 import android.view.Surface;
 
 import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.SomeArgs;
+import com.android.server.IoThread;
 import com.android.server.SystemService;
 
 import java.util.ArrayList;
@@ -61,6 +72,8 @@
 
     private final Context mContext;
 
+    private final ContentResolver mContentResolver;
+
     // A global lock.
     private final Object mLock = new Object();
 
@@ -70,10 +83,17 @@
     // A map from user id to UserState.
     private final SparseArray<UserState> mUserStates = new SparseArray<UserState>();
 
+    private final Handler mLogHandler;
+
     public TvInputManagerService(Context context) {
         super(context);
+
         mContext = context;
+        mContentResolver = context.getContentResolver();
+        mLogHandler = new LogHandler(IoThread.get().getLooper());
+
         registerBroadcastReceivers();
+
         synchronized (mLock) {
             mUserStates.put(mCurrentUserId, new UserState());
             buildTvInputListLocked(mCurrentUserId);
@@ -116,17 +136,19 @@
         UserState userState = getUserStateLocked(userId);
         userState.inputList.clear();
 
+        if (DEBUG) Slog.d(TAG, "buildTvInputList");
         PackageManager pm = mContext.getPackageManager();
         List<ResolveInfo> services = pm.queryIntentServices(
                 new Intent(TvInputService.SERVICE_INTERFACE), PackageManager.GET_SERVICES);
         for (ResolveInfo ri : services) {
             ServiceInfo si = ri.serviceInfo;
             if (!android.Manifest.permission.BIND_TV_INPUT.equals(si.permission)) {
-                Log.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
+                Slog.w(TAG, "Skipping TV input " + si.name + ": it does not require the permission "
                         + android.Manifest.permission.BIND_TV_INPUT);
                 continue;
             }
             TvInputInfo info = new TvInputInfo(ri);
+            if (DEBUG) Slog.d(TAG, "add " + info.getId());
             userState.inputList.add(info);
         }
     }
@@ -161,7 +183,7 @@
                     try {
                         state.session.release();
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in release", e);
+                        Slog.e(TAG, "error in release", e);
                     }
                 }
             }
@@ -173,7 +195,7 @@
                     try {
                         serviceState.service.unregisterCallback(serviceState.callback);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in unregisterCallback", e);
+                        Slog.e(TAG, "error in unregisterCallback", e);
                     }
                 }
                 serviceState.clients.clear();
@@ -197,8 +219,8 @@
         UserState userState = getUserStateLocked(userId);
         ServiceState serviceState = userState.serviceStateMap.get(name);
         if (serviceState == null) {
-            throw new IllegalStateException("Service state not found for " + name + " (userId=" +
-                    userId + ")");
+            throw new IllegalStateException("Service state not found for " + name + " (userId="
+                    + userId + ")");
         }
         return serviceState;
     }
@@ -233,8 +255,8 @@
         if (serviceState == null) {
             return;
         }
-        boolean isStateEmpty = serviceState.clients.size() == 0
-                && serviceState.sessionStateMap.size() == 0;
+        boolean isStateEmpty = serviceState.clients.isEmpty()
+                && serviceState.sessionTokens.isEmpty();
         if (serviceState.service == null && !isStateEmpty && userId == mCurrentUserId) {
             // This means that the service is not yet connected but its state indicates that we
             // have pending requests. Then, connect the service.
@@ -244,7 +266,7 @@
                 return;
             }
             if (DEBUG) {
-                Log.i(TAG, "bindServiceAsUser(name=" + name.getClassName() + ", userId=" + userId
+                Slog.d(TAG, "bindServiceAsUser(name=" + name.getClassName() + ", userId=" + userId
                         + ")");
             }
             Intent i = new Intent(TvInputService.SERVICE_INTERFACE).setComponent(name);
@@ -255,7 +277,7 @@
             // This means that the service is already connected but its state indicates that we have
             // nothing to do with it. Then, disconnect the service.
             if (DEBUG) {
-                Log.i(TAG, "unbindService(name=" + name.getClassName() + ")");
+                Slog.d(TAG, "unbindService(name=" + name.getClassName() + ")");
             }
             mContext.unbindService(serviceState.connection);
             userState.serviceStateMap.remove(name);
@@ -263,42 +285,56 @@
     }
 
     private void createSessionInternalLocked(ITvInputService service, final IBinder sessionToken,
-            final SessionState sessionState, final int userId) {
+            final int userId) {
+        final SessionState sessionState =
+                getUserStateLocked(userId).sessionStateMap.get(sessionToken);
         if (DEBUG) {
-            Log.d(TAG, "createSessionInternalLocked(name=" + sessionState.name.getClassName()
+            Slog.d(TAG, "createSessionInternalLocked(name=" + sessionState.name.getClassName()
                     + ")");
         }
+
+        final InputChannel[] channels = InputChannel.openInputChannelPair(sessionToken.toString());
+
         // Set up a callback to send the session token.
         ITvInputSessionCallback callback = new ITvInputSessionCallback.Stub() {
             @Override
             public void onSessionCreated(ITvInputSession session) {
                 if (DEBUG) {
-                    Log.d(TAG, "onSessionCreated(name=" + sessionState.name.getClassName() + ")");
+                    Slog.d(TAG, "onSessionCreated(name=" + sessionState.name.getClassName() + ")");
                 }
                 synchronized (mLock) {
                     sessionState.session = session;
-                    sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
-                            sessionToken, sessionState.seq, userId);
+                    if (session == null) {
+                        removeSessionStateLocked(sessionToken, userId);
+                        sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
+                                null, sessionState.seq, userId);
+                    } else {
+                        sendSessionTokenToClientLocked(sessionState.client, sessionState.name,
+                                sessionToken, channels[0], sessionState.seq, userId);
+                    }
+                    channels[0].dispose();
                 }
             }
         };
 
         // Create a session. When failed, send a null token immediately.
         try {
-            service.createSession(callback);
+            service.createSession(channels[1], callback);
         } catch (RemoteException e) {
-            Log.e(TAG, "error in createSession", e);
-            sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null,
+            Slog.e(TAG, "error in createSession", e);
+            removeSessionStateLocked(sessionToken, userId);
+            sendSessionTokenToClientLocked(sessionState.client, sessionState.name, null, null,
                     sessionState.seq, userId);
         }
+        channels[1].dispose();
     }
 
     private void sendSessionTokenToClientLocked(ITvInputClient client, ComponentName name,
-            IBinder sessionToken, int seq, int userId) {
+            IBinder sessionToken, InputChannel channel, int seq, int userId) {
         try {
-            client.onSessionCreated(name, sessionToken, seq);
+            client.onSessionCreated(name, sessionToken, channel, seq);
         } catch (RemoteException exception) {
-            Log.e(TAG, "error in onSessionCreated", exception);
+            Slog.e(TAG, "error in onSessionCreated", exception);
         }
 
         if (sessionToken == null) {
@@ -307,6 +343,27 @@
         }
     }
 
+    private void removeSessionStateLocked(IBinder sessionToken, int userId) {
+        // Remove the session state from the global session state map of the current user.
+        UserState userState = getUserStateLocked(userId);
+        SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
+
+        // Close the open log entry, if any.
+        if (sessionState.logUri != null) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = sessionState.logUri;
+            args.arg2 = System.currentTimeMillis();
+            mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args).sendToTarget();
+        }
+
+        // Also remove the session token from the session token list of the current service.
+        ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
+        if (serviceState != null) {
+            serviceState.sessionTokens.remove(sessionToken);
+        }
+        updateServiceConnectionLocked(sessionState.name, userId);
+    }
+
     private final class BinderService extends ITvInputManager.Stub {
         @Override
         public List<TvInputInfo> getTvInputList(int userId) {
@@ -358,7 +415,7 @@
                     UserState userState = getUserStateLocked(resolvedUserId);
                     ServiceState serviceState = userState.serviceStateMap.get(name);
                     if (serviceState == null) {
-                        serviceState = new ServiceState(name, resolvedUserId);
+                        serviceState = new ServiceState(resolvedUserId);
                         userState.serviceStateMap.put(name, serviceState);
                     }
                     IBinder iBinder = client.asBinder();
@@ -374,7 +431,7 @@
                         try {
                             serviceState.service.registerCallback(serviceState.callback);
                         } catch (RemoteException e) {
-                            Log.e(TAG, "error in registerCallback", e);
+                            Slog.e(TAG, "error in registerCallback", e);
                         }
                     } else {
                         updateServiceConnectionLocked(name, resolvedUserId);
@@ -410,7 +467,7 @@
                     try {
                         serviceState.service.unregisterCallback(serviceState.callback);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in unregisterCallback", e);
+                        Slog.e(TAG, "error in unregisterCallback", e);
                     } finally {
                         serviceState.callback = null;
                         updateServiceConnectionLocked(name, resolvedUserId);
@@ -442,14 +499,14 @@
                     // Also, add them to the session state map of the current service.
                     ServiceState serviceState = userState.serviceStateMap.get(name);
                     if (serviceState == null) {
-                        serviceState = new ServiceState(name, resolvedUserId);
+                        serviceState = new ServiceState(resolvedUserId);
                         userState.serviceStateMap.put(name, serviceState);
                     }
-                    serviceState.sessionStateMap.put(sessionToken, sessionState);
+                    serviceState.sessionTokens.add(sessionToken);
 
                     if (serviceState.service != null) {
                         createSessionInternalLocked(serviceState.service, sessionToken,
-                                sessionState, resolvedUserId);
+                                resolvedUserId);
                     } else {
                         updateServiceConnectionLocked(name, resolvedUserId);
                     }
@@ -471,20 +528,10 @@
                     try {
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).release();
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in release", e);
+                        Slog.e(TAG, "error in release", e);
                     }
 
-                    // Remove its state from the global session state map of the current user.
-                    UserState userState = getUserStateLocked(resolvedUserId);
-                    SessionState sessionState = userState.sessionStateMap.remove(sessionToken);
-
-                    // Also remove it from the session state map of the current service.
-                    ServiceState serviceState = userState.serviceStateMap.get(sessionState.name);
-                    if (serviceState != null) {
-                        serviceState.sessionStateMap.remove(sessionToken);
-                    }
-
-                    updateServiceConnectionLocked(sessionState.name, resolvedUserId);
+                    removeSessionStateLocked(sessionToken, resolvedUserId);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -503,10 +550,14 @@
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).setSurface(
                                 surface);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in setSurface", e);
+                        Slog.e(TAG, "error in setSurface", e);
                     }
                 }
             } finally {
+                if (surface != null) {
+                    // surface is not used in TvInputManagerService.
+                    surface.release();
+                }
                 Binder.restoreCallingIdentity(identity);
             }
         }
@@ -523,7 +574,7 @@
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).setVolume(
                                 volume);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in setVolume", e);
+                        Slog.e(TAG, "error in setVolume", e);
                     }
                 }
             } finally {
@@ -539,13 +590,39 @@
             final long identity = Binder.clearCallingIdentity();
             try {
                 synchronized (mLock) {
-                    SessionState sessionState = getUserStateLocked(resolvedUserId)
-                            .sessionStateMap.get(sessionToken);
-                    final String serviceName = sessionState.name.getClassName();
                     try {
                         getSessionLocked(sessionToken, callingUid, resolvedUserId).tune(channelUri);
+
+                        long currentTime = System.currentTimeMillis();
+                        long channelId = ContentUris.parseId(channelUri);
+
+                        // Close the open log entry first, if any.
+                        UserState userState = getUserStateLocked(resolvedUserId);
+                        SessionState sessionState = userState.sessionStateMap.get(sessionToken);
+                        if (sessionState.logUri != null) {
+                            SomeArgs args = SomeArgs.obtain();
+                            args.arg1 = sessionState.logUri;
+                            args.arg2 = currentTime;
+                            mLogHandler.obtainMessage(LogHandler.MSG_CLOSE_ENTRY, args)
+                                    .sendToTarget();
+                        }
+
+                        // Create a log entry and fill it later.
+                        ContentValues values = new ContentValues();
+                        values.put(TvContract.WatchedPrograms.WATCH_START_TIME_UTC_MILLIS,
+                                currentTime);
+                        values.put(TvContract.WatchedPrograms.WATCH_END_TIME_UTC_MILLIS, 0);
+                        values.put(TvContract.WatchedPrograms.CHANNEL_ID, channelId);
+
+                        sessionState.logUri = mContentResolver.insert(
+                                TvContract.WatchedPrograms.CONTENT_URI, values);
+                        SomeArgs args = SomeArgs.obtain();
+                        args.arg1 = sessionState.logUri;
+                        args.arg2 = ContentUris.parseId(channelUri);
+                        args.arg3 = currentTime;
+                        mLogHandler.obtainMessage(LogHandler.MSG_OPEN_ENTRY, args).sendToTarget();
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in tune", e);
+                        Slog.e(TAG, "error in tune", e);
                         return;
                     }
                 }
@@ -553,6 +630,67 @@
                 Binder.restoreCallingIdentity(identity);
             }
         }
+
+        @Override
+        public void createOverlayView(IBinder sessionToken, IBinder windowToken, Rect frame,
+                int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "createOverlayView");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .createOverlayView(windowToken, frame);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in createOverlayView", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void relayoutOverlayView(IBinder sessionToken, Rect frame, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "relayoutOverlayView");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .relayoutOverlayView(frame);
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in relayoutOverlayView", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
+
+        @Override
+        public void removeOverlayView(IBinder sessionToken, int userId) {
+            final int callingUid = Binder.getCallingUid();
+            final int resolvedUserId = resolveCallingUserId(Binder.getCallingPid(), callingUid,
+                    userId, "removeOverlayView");
+            final long identity = Binder.clearCallingIdentity();
+            try {
+                synchronized (mLock) {
+                    try {
+                        getSessionLocked(sessionToken, callingUid, resolvedUserId)
+                                .removeOverlayView();
+                    } catch (RemoteException e) {
+                        Slog.e(TAG, "error in removeOverlayView", e);
+                    }
+                }
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        }
     }
 
     private static final class UserState {
@@ -570,8 +708,7 @@
 
     private final class ServiceState {
         private final List<IBinder> clients = new ArrayList<IBinder>();
-        private final ArrayMap<IBinder, SessionState> sessionStateMap = new ArrayMap<IBinder,
-                SessionState>();
+        private final List<IBinder> sessionTokens = new ArrayList<IBinder>();
         private final ServiceConnection connection;
 
         private ITvInputService service;
@@ -579,7 +716,7 @@
         private boolean bound;
         private boolean available;
 
-        private ServiceState(ComponentName name, int userId) {
+        private ServiceState(int userId) {
             this.connection = new InputServiceConnection(userId);
         }
     }
@@ -591,6 +728,7 @@
         private final int callingUid;
 
         private ITvInputSession session;
+        private Uri logUri;
 
         private SessionState(ComponentName name, ITvInputClient client, int seq, int callingUid) {
             this.name = name;
@@ -610,7 +748,7 @@
         @Override
         public void onServiceConnected(ComponentName name, IBinder service) {
             if (DEBUG) {
-                Log.d(TAG, "onServiceConnected(name=" + name.getClassName() + ")");
+                Slog.d(TAG, "onServiceConnected(name=" + name.getClassName() + ")");
             }
             synchronized (mLock) {
                 ServiceState serviceState = getServiceStateLocked(name, mUserId);
@@ -622,15 +760,13 @@
                     try {
                         serviceState.service.registerCallback(serviceState.callback);
                     } catch (RemoteException e) {
-                        Log.e(TAG, "error in registerCallback", e);
+                        Slog.e(TAG, "error in registerCallback", e);
                     }
                 }
 
                 // And create sessions, if any.
-                for (Map.Entry<IBinder, SessionState> entry : serviceState.sessionStateMap
-                        .entrySet()) {
-                    createSessionInternalLocked(serviceState.service, entry.getKey(),
-                            entry.getValue(), mUserId);
+                for (IBinder sessionToken : serviceState.sessionTokens) {
+                    createSessionInternalLocked(serviceState.service, sessionToken, mUserId);
                 }
             }
         }
@@ -638,7 +774,7 @@
         @Override
         public void onServiceDisconnected(ComponentName name) {
             if (DEBUG) {
-                Log.d(TAG, "onServiceDisconnected(name=" + name.getClassName() + ")");
+                Slog.d(TAG, "onServiceDisconnected(name=" + name.getClassName() + ")");
             }
         }
     }
@@ -654,7 +790,7 @@
         public void onAvailabilityChanged(ComponentName name, boolean isAvailable)
                 throws RemoteException {
             if (DEBUG) {
-                Log.d(TAG, "onAvailabilityChanged(name=" + name.getClassName() + ", isAvailable="
+                Slog.d(TAG, "onAvailabilityChanged(name=" + name.getClassName() + ", isAvailable="
                         + isAvailable + ")");
             }
             synchronized (mLock) {
@@ -667,4 +803,147 @@
             }
         }
     }
+
+    private final class LogHandler extends Handler {
+        private static final int MSG_OPEN_ENTRY = 1;
+        private static final int MSG_UPDATE_ENTRY = 2;
+        private static final int MSG_CLOSE_ENTRY = 3;
+
+        public LogHandler(Looper looper) {
+            super(looper);
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_OPEN_ENTRY: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Uri uri = (Uri) args.arg1;
+                    long channelId = (long) args.arg2;
+                    long time = (long) args.arg3;
+                    onOpenEntry(uri, channelId, time);
+                    args.recycle();
+                    return;
+                }
+                case MSG_UPDATE_ENTRY: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Uri uri = (Uri) args.arg1;
+                    long channelId = (long) args.arg2;
+                    long time = (long) args.arg3;
+                    onUpdateEntry(uri, channelId, time);
+                    args.recycle();
+                    return;
+                }
+                case MSG_CLOSE_ENTRY: {
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    Uri uri = (Uri) args.arg1;
+                    long time = (long) args.arg2;
+                    onCloseEntry(uri, time);
+                    args.recycle();
+                    return;
+                }
+                default: {
+                    Slog.w(TAG, "Unhandled message code: " + msg.what);
+                    return;
+                }
+            }
+        }
+
+        private void onOpenEntry(Uri uri, long channelId, long watchStarttime) {
+            String[] projection = {
+                    TvContract.Programs.TITLE,
+                    TvContract.Programs.START_TIME_UTC_MILLIS,
+                    TvContract.Programs.END_TIME_UTC_MILLIS,
+                    TvContract.Programs.DESCRIPTION
+            };
+            String selection = TvContract.Programs.CHANNEL_ID + "=? AND "
+                    + TvContract.Programs.START_TIME_UTC_MILLIS + "<=? AND "
+                    + TvContract.Programs.END_TIME_UTC_MILLIS + ">?";
+            String[] selectionArgs = {
+                    String.valueOf(channelId),
+                    String.valueOf(watchStarttime),
+                    String.valueOf(watchStarttime)
+            };
+            String sortOrder = TvContract.Programs.START_TIME_UTC_MILLIS + " ASC";
+            Cursor cursor = null;
+            try {
+                cursor = mContentResolver.query(TvContract.Programs.CONTENT_URI, projection,
+                        selection, selectionArgs, sortOrder);
+                if (cursor != null && cursor.moveToNext()) {
+                    ContentValues values = new ContentValues();
+                    values.put(TvContract.WatchedPrograms.TITLE, cursor.getString(0));
+                    values.put(TvContract.WatchedPrograms.START_TIME_UTC_MILLIS, cursor.getLong(1));
+                    long endTime = cursor.getLong(2);
+                    values.put(TvContract.WatchedPrograms.END_TIME_UTC_MILLIS, endTime);
+                    values.put(TvContract.WatchedPrograms.DESCRIPTION, cursor.getString(3));
+                    mContentResolver.update(uri, values, null, null);
+
+                    // Schedule an update when the current program ends.
+                    SomeArgs args = SomeArgs.obtain();
+                    args.arg1 = uri;
+                    args.arg2 = channelId;
+                    args.arg3 = endTime;
+                    Message msg = obtainMessage(LogHandler.MSG_UPDATE_ENTRY, args);
+                    sendMessageDelayed(msg, endTime - System.currentTimeMillis());
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+        }
+
+        private void onUpdateEntry(Uri uri, long channelId, long time) {
+            String[] projection = {
+                    TvContract.WatchedPrograms.WATCH_START_TIME_UTC_MILLIS,
+                    TvContract.WatchedPrograms.WATCH_END_TIME_UTC_MILLIS,
+                    TvContract.WatchedPrograms.TITLE,
+                    TvContract.WatchedPrograms.START_TIME_UTC_MILLIS,
+                    TvContract.WatchedPrograms.END_TIME_UTC_MILLIS,
+                    TvContract.WatchedPrograms.DESCRIPTION
+            };
+            Cursor cursor = null;
+            try {
+                cursor = mContentResolver.query(uri, projection, null, null, null);
+                if (cursor != null && cursor.moveToNext()) {
+                    long watchStartTime = cursor.getLong(0);
+                    long watchEndTime = cursor.getLong(1);
+                    String title = cursor.getString(2);
+                    long startTime = cursor.getLong(3);
+                    long endTime = cursor.getLong(4);
+                    String description = cursor.getString(5);
+
+                    // Do nothing if the current log entry is already closed.
+                    if (watchEndTime > 0) {
+                        return;
+                    }
+
+                    // The current program has just ended. Create a (complete) log entry off the
+                    // current entry.
+                    ContentValues values = new ContentValues();
+                    values.put(TvContract.WatchedPrograms.WATCH_START_TIME_UTC_MILLIS,
+                            watchStartTime);
+                    values.put(TvContract.WatchedPrograms.WATCH_END_TIME_UTC_MILLIS, time);
+                    values.put(TvContract.WatchedPrograms.CHANNEL_ID, channelId);
+                    values.put(TvContract.WatchedPrograms.TITLE, title);
+                    values.put(TvContract.WatchedPrograms.START_TIME_UTC_MILLIS, startTime);
+                    values.put(TvContract.WatchedPrograms.END_TIME_UTC_MILLIS, endTime);
+                    values.put(TvContract.WatchedPrograms.DESCRIPTION, description);
+                    mContentResolver.insert(TvContract.WatchedPrograms.CONTENT_URI, values);
+                }
+            } finally {
+                if (cursor != null) {
+                    cursor.close();
+                }
+            }
+            // Re-open the current log entry with the next program information.
+            onOpenEntry(uri, channelId, time);
+        }
+
+        private void onCloseEntry(Uri uri, long watchEndTime) {
+            ContentValues values = new ContentValues();
+            values.put(TvContract.WatchedPrograms.WATCH_END_TIME_UTC_MILLIS, watchEndTime);
+            mContentResolver.update(uri, values, null, null);
+        }
+    }
 }
diff --git a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
index fdc604f..3c960c7 100644
--- a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
+++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java
@@ -20,6 +20,8 @@
 import android.content.Intent;
 import android.os.SystemProperties;
 import android.provider.Settings;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Base64;
 import android.util.Slog;
 
@@ -28,9 +30,7 @@
 import java.io.FileInputStream;
 import java.io.IOException;
 
-import libcore.io.ErrnoException;
 import libcore.io.IoUtils;
-import libcore.io.Libcore;
 
 public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver {
 
@@ -110,16 +110,16 @@
         File update = new File(updateDir.getParentFile(), "update");
         File tmp = new File(updateDir.getParentFile(), "tmp");
         if (current.exists()) {
-            Libcore.os.symlink(updateDir.getPath(), update.getPath());
-            Libcore.os.rename(update.getPath(), current.getPath());
+            Os.symlink(updateDir.getPath(), update.getPath());
+            Os.rename(update.getPath(), current.getPath());
         } else {
-            Libcore.os.symlink(updateDir.getPath(), current.getPath());
+            Os.symlink(updateDir.getPath(), current.getPath());
         }
         contexts.mkdirs();
         backupContexts(contexts);
         copyUpdate(contexts);
-        Libcore.os.symlink(contexts.getPath(), tmp.getPath());
-        Libcore.os.rename(tmp.getPath(), current.getPath());
+        Os.symlink(contexts.getPath(), tmp.getPath());
+        Os.rename(tmp.getPath(), current.getPath());
         SystemProperties.set("selinux.reload_policy", "1");
     }
 
diff --git a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
index 87953fe..3eb2d5f 100644
--- a/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
+++ b/services/core/java/com/android/server/wallpaper/WallpaperManagerService.java
@@ -25,6 +25,7 @@
 import android.app.IWallpaperManagerCallback;
 import android.app.PendingIntent;
 import android.app.WallpaperInfo;
+import android.app.WallpaperManager;
 import android.app.backup.BackupManager;
 import android.app.backup.WallpaperBackupHelper;
 import android.content.BroadcastReceiver;
@@ -844,13 +845,7 @@
         
         try {
             if (componentName == null) {
-                String defaultComponent = 
-                    mContext.getString(com.android.internal.R.string.default_wallpaper_component);
-                if (defaultComponent != null) {
-                    // See if there is a default wallpaper component specified
-                    componentName = ComponentName.unflattenFromString(defaultComponent);
-                    if (DEBUG) Slog.v(TAG, "Use default component wallpaper:" + componentName);
-                }
+                componentName = WallpaperManager.getDefaultWallpaperComponent(mContext);
                 if (componentName == null) {
                     // Fall back to static image wallpaper
                     componentName = IMAGE_WALLPAPER;
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 7d8b5af..9039236 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import android.content.Context;
+import android.content.res.Configuration;
 import android.graphics.Bitmap;
 import android.graphics.Point;
 import android.graphics.Rect;
@@ -147,6 +148,9 @@
     private int mNextAppTransitionStartWidth;
     private int mNextAppTransitionStartHeight;
 
+    private Rect mTmpFromClipRect = new Rect();
+    private Rect mTmpToClipRect = new Rect();
+
     private final static int APP_STATE_IDLE = 0;
     private final static int APP_STATE_READY = 1;
     private final static int APP_STATE_RUNNING = 2;
@@ -158,13 +162,10 @@
     private final Interpolator mThumbnailFadeoutInterpolator;
 
     private int mCurrentUserId = 0;
-    private boolean mUseAlternateThumbnailAnimation;
 
     AppTransition(Context context, Handler h) {
         mContext = context;
         mH = h;
-        mUseAlternateThumbnailAnimation =
-                SystemProperties.getBoolean("persist.anim.use_alt_thumbnail", false);
         mConfigShortAnimTime = context.getResources().getInteger(
                 com.android.internal.R.integer.config_shortAnimTime);
         mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
@@ -485,7 +486,7 @@
      * activity that is leaving, and the activity that is entering.
      */
     Animation createAlternateThumbnailEnterExitAnimationLocked(int thumbTransitState, int appWidth,
-                                                    int appHeight, int transit,
+                                                    int appHeight, int orientation, int transit,
                                                     Rect containingFrame, Rect contentInsets) {
         Animation a;
         final int thumbWidthI = mNextAppTransitionThumbnail.getWidth();
@@ -493,21 +494,36 @@
         final int thumbHeightI = mNextAppTransitionThumbnail.getHeight();
         final float thumbHeight = thumbHeightI > 0 ? thumbHeightI : 1;
 
+        // Used for the ENTER_SCALE_UP and EXIT_SCALE_DOWN transitions
+        float scale = 1f;
+        int scaledTopDecor = 0;
+
         switch (thumbTransitState) {
             case THUMBNAIL_TRANSITION_ENTER_SCALE_UP: {
                 // Entering app scales up with the thumbnail
-                float scale = thumbWidth / appWidth;
-                int unscaledThumbHeight = (int) (thumbHeight / scale);
-                int scaledTopDecor = (int) (scale * contentInsets.top);
-                Rect fromClipRect = new Rect(containingFrame);
-                fromClipRect.bottom = (fromClipRect.top + unscaledThumbHeight);
-                Rect toClipRect = new Rect(containingFrame);
+                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    // In portrait, we scale the width and clip to the top/left square
+                    scale = thumbWidth / appWidth;
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpFromClipRect.bottom = (mTmpFromClipRect.top + unscaledThumbHeight);
+                    mTmpToClipRect.set(containingFrame);
+                } else {
+                    // In landscape, we scale the height and clip to the top/left square
+                    scale = thumbHeight / (appHeight - contentInsets.top);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpFromClipRect.right = (mTmpFromClipRect.left + unscaledThumbWidth);
+                    mTmpToClipRect.set(containingFrame);
+                }
 
                 Animation scaleAnim = new ScaleAnimation(scale, 1, scale, 1,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
                 Animation alphaAnim = new AlphaAnimation(1, 1);
-                Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+                Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, -scaledTopDecor, 0);
 
                 AnimationSet set = new AnimationSet(true);
@@ -539,18 +555,29 @@
             }
             case THUMBNAIL_TRANSITION_EXIT_SCALE_DOWN: {
                 // Exiting the current app, the app should scale down with the thumbnail
-                float scale = thumbWidth / appWidth;
-                int unscaledThumbHeight = (int) (thumbHeight / scale);
-                int scaledTopDecor = (int) (scale * contentInsets.top);
-                Rect fromClipRect = new Rect(containingFrame);
-                Rect toClipRect = new Rect(containingFrame);
-                toClipRect.bottom = (toClipRect.top + unscaledThumbHeight);
+                if (orientation == Configuration.ORIENTATION_PORTRAIT) {
+                    // In portrait, we scale the width and clip to the top/left square
+                    scale = thumbWidth / appWidth;
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbHeight = (int) (thumbHeight / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpToClipRect.set(containingFrame);
+                    mTmpToClipRect.bottom = (mTmpToClipRect.top + unscaledThumbHeight);
+                } else {
+                    // In landscape, we scale the height and clip to the top/left square
+                    scale = thumbHeight / (appHeight - contentInsets.top);
+                    scaledTopDecor = (int) (scale * contentInsets.top);
+                    int unscaledThumbWidth = (int) (thumbWidth / scale);
+                    mTmpFromClipRect.set(containingFrame);
+                    mTmpToClipRect.set(containingFrame);
+                    mTmpToClipRect.right = (mTmpToClipRect.left + unscaledThumbWidth);
+                }
 
                 Animation scaleAnim = new ScaleAnimation(1, scale, 1, scale,
                         computePivot(mNextAppTransitionStartX, scale),
                         computePivot(mNextAppTransitionStartY, scale));
                 Animation alphaAnim = new AlphaAnimation(1, 1);
-                Animation clipAnim = new ClipRectAnimation(fromClipRect, toClipRect);
+                Animation clipAnim = new ClipRectAnimation(mTmpFromClipRect, mTmpToClipRect);
                 Animation translateAnim = new TranslateAnimation(0, 0, 0, -scaledTopDecor);
 
                 AnimationSet set = new AnimationSet(true);
@@ -637,7 +664,8 @@
 
 
     Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
-                            int appWidth, int appHeight, Rect containingFrame, Rect contentInsets) {
+                            int appWidth, int appHeight, int orientation,
+                            Rect containingFrame, Rect contentInsets, Configuration configuration) {
         Animation a;
         if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -658,10 +686,11 @@
                 mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_DOWN) {
             mNextAppTransitionScaleUp =
                     (mNextAppTransitionType == NEXT_TRANSIT_TYPE_THUMBNAIL_SCALE_UP);
-            if (mUseAlternateThumbnailAnimation) {
+            boolean useAlternateThumbnailAnimation = (configuration.smallestScreenWidthDp < 600);
+            if (useAlternateThumbnailAnimation) {
                 a = createAlternateThumbnailEnterExitAnimationLocked(
-                        getThumbnailTransitionState(enter), appWidth, appHeight, transit,
-                        containingFrame, contentInsets);
+                        getThumbnailTransitionState(enter), appWidth, appHeight, orientation,
+                        transit, containingFrame, contentInsets);
             } else {
                 a = createThumbnailEnterExitAnimationLocked(getThumbnailTransitionState(enter),
                         appWidth, appHeight, transit);
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index fbfca93..35d19c1 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -22,7 +22,6 @@
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.util.Log;
 import android.view.Display;
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
@@ -40,6 +39,7 @@
     private int mLastDH;
     private boolean mDrawNeeded;
     private Paint mPaint;
+    private int mRotation;
 
     public CircularDisplayMask(Display display, SurfaceSession session, int zOrder) {
         SurfaceControl ctrl = null;
@@ -78,7 +78,26 @@
         if (c == null) {
             return;
         }
-        c.drawCircle(160, 160, 160, mPaint);
+        int cx = 160;
+        int cy = 160;
+        switch (mRotation) {
+            case Surface.ROTATION_0:
+            case Surface.ROTATION_90:
+                // chin bottom or right
+                cx = 160;
+                cy = 160;
+                break;
+            case Surface.ROTATION_180:
+                // chin top
+                cx = 160;
+                cy = 145;
+                break;
+            case Surface.ROTATION_270:
+                cx = 145;
+                cy = 160;
+                break;
+        }
+        c.drawCircle(cx, cy, 160, mPaint);
 
         mSurface.unlockCanvasAndPost(c);
     }
@@ -97,7 +116,7 @@
         }
     }
 
-    void positionSurface(int dw, int dh) {
+    void positionSurface(int dw, int dh, int rotation) {
         if (mLastDW == dw && mLastDH == dh) {
             return;
         }
@@ -105,6 +124,7 @@
         mLastDH = dh;
         mSurfaceControl.setSize(dw, dh);
         mDrawNeeded = true;
+        mRotation = rotation;
     }
 
 }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4aae5c1..f02c0e6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -284,7 +284,7 @@
                 final boolean hasFocus = (child == mInputFocus);
                 final boolean isVisible = child.isVisibleLw();
                 final boolean hasWallpaper = (child == mService.mWallpaperTarget)
-                        && (type != WindowManager.LayoutParams.TYPE_KEYGUARD);
+                        && (privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD) == 0;
                 final boolean onDefaultDisplay = (child.getDisplayId() == Display.DEFAULT_DISPLAY);
 
                 // If there's a drag in progress and 'child' is a potential drop target,
@@ -355,17 +355,16 @@
     /* Provides an opportunity for the window manager policy to intercept early key
      * processing as soon as the key has been read from the device. */
     @Override
-    public int interceptKeyBeforeQueueing(
-            KeyEvent event, int policyFlags, boolean isScreenOn) {
-        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
+    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
     }
 
     /* Provides an opportunity for the window manager policy to intercept early
      * motion event processing when the screen is off since these events are normally
      * dropped. */
     @Override
-    public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
-        return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(whenNanos, policyFlags);
+    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+        return mService.mPolicy.interceptWakeMotionBeforeQueueing(whenNanos, policyFlags);
     }
 
     /* Provides an opportunity for the window manager policy to process a key before
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index b12ae4f..637beec 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -24,6 +24,7 @@
 import android.util.TimeUtils;
 import android.view.IWindowId;
 
+import android.view.WindowContentFrameStats;
 import com.android.internal.app.IBatteryStats;
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.policy.impl.PhoneWindowManager;
@@ -286,8 +287,6 @@
     private static final String DENSITY_OVERRIDE = "ro.config.density_override";
     private static final String SIZE_OVERRIDE = "ro.config.size_override";
 
-    private static final String SCREEN_CIRCULAR = "ro.display.circular";
-
     private static final int MAX_SCREENSHOT_RETRIES = 3;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -626,6 +625,8 @@
 
     private final PointerEventDispatcher mPointerEventDispatcher;
 
+    private WindowContentFrameStats mTempWindowRenderStats;
+
     final class DragInputEventReceiver extends InputEventReceiver {
         public DragInputEventReceiver(InputChannel inputChannel, Looper looper) {
             super(inputChannel, looper);
@@ -1890,7 +1891,9 @@
                 int insertionIndex = 0;
                 if (visible && foundW != null) {
                     final int type = foundW.mAttrs.type;
-                    if (type == TYPE_KEYGUARD || type == TYPE_KEYGUARD_SCRIM) {
+                    final int privateFlags = foundW.mAttrs.privateFlags;
+                    if ((privateFlags & PRIVATE_FLAG_KEYGUARD) != 0
+                            || type == TYPE_KEYGUARD_SCRIM) {
                         insertionIndex = windows.indexOf(foundW);
                     }
                 }
@@ -3187,7 +3190,7 @@
             }
 
             Animation a = mAppTransition.loadAnimation(lp, transit, enter, width, height,
-                    containingFrame, contentInsets);
+                    mCurConfiguration.orientation, containingFrame, contentInsets, mCurConfiguration);
             if (a != null) {
                 if (DEBUG_ANIM) {
                     RuntimeException e = null;
@@ -5288,6 +5291,13 @@
         performEnableScreen();
     }
 
+    @Override
+    public void enableScreenIfNeeded() {
+        synchronized (mWindowMap) {
+            enableScreenIfNeededLocked();
+        }
+    }
+
     void enableScreenIfNeededLocked() {
         if (DEBUG_BOOT) {
             RuntimeException here = new RuntimeException("here");
@@ -5352,18 +5362,6 @@
                 final int N = windows.size();
                 for (int i=0; i<N; i++) {
                     WindowState w = windows.get(i);
-                    if (w.mAttrs.type == TYPE_KEYGUARD) {
-                        // Only if there is a keyguard attached to the window manager
-                        // will we consider ourselves as having a keyguard.  If it
-                        // isn't attached, we don't know if it wants to be shown or
-                        // hidden.  If it is attached, we will say we have a keyguard
-                        // if the window doesn't want to be visible, because in that
-                        // case it explicitly doesn't want to be shown so we should
-                        // not delay turning the screen on for it.
-                        boolean vis = w.mViewVisibility == View.VISIBLE
-                                && w.mPolicyVisibility;
-                        haveKeyguard = !vis;
-                    }
                     if (w.isVisibleLw() && !w.mObscured && !w.isDrawnLw()) {
                         return;
                     }
@@ -5374,8 +5372,8 @@
                             haveApp = true;
                         } else if (w.mAttrs.type == TYPE_WALLPAPER) {
                             haveWallpaper = true;
-                        } else if (w.mAttrs.type == TYPE_KEYGUARD) {
-                            haveKeyguard = true;
+                        } else if (w.mAttrs.type == TYPE_STATUS_BAR) {
+                            haveKeyguard = mPolicy.isKeyguardDrawnLw();
                         }
                     }
                 }
@@ -5489,7 +5487,9 @@
     }
 
     public void showCircularDisplayMaskIfNeeded() {
-        if (SystemProperties.getBoolean(SCREEN_CIRCULAR, false)) {
+        // we're fullscreen and not hosted in an ActivityView
+        if (mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_windowIsRound)) {
             mH.sendMessage(mH.obtainMessage(H.SHOW_DISPLAY_MASK));
         }
     }
@@ -6981,7 +6981,6 @@
             if (mDisplayEnabled) {
                 mInputMonitor.setEventDispatchingLw(enabled);
             }
-            sendScreenStatusToClientsLocked();
         }
     }
 
@@ -7086,23 +7085,6 @@
         mPolicy.systemReady();
     }
 
-    // TODO(multidisplay): Call isScreenOn for each display.
-    private void sendScreenStatusToClientsLocked() {
-        final boolean on = mPowerManager.isScreenOn();
-        final int numDisplays = mDisplayContents.size();
-        for (int displayNdx = 0; displayNdx < numDisplays; ++displayNdx) {
-            final WindowList windows = mDisplayContents.valueAt(displayNdx).getWindowList();
-            final int numWindows = windows.size();
-            for (int winNdx = 0; winNdx < numWindows; ++winNdx) {
-                try {
-                    windows.get(winNdx).mClient.dispatchScreenState(on);
-                } catch (RemoteException e) {
-                    // Ignored
-                }
-            }
-        }
-    }
-
     // -------------------------------------------------------------
     // Async Handler
     // -------------------------------------------------------------
@@ -8350,7 +8332,7 @@
             // just don't display").
             if (!gone || !win.mHaveFrame || win.mLayoutNeeded
                     || ((win.isConfigChanged() || win.setInsetsChanged()) &&
-                            (win.mAttrs.type == TYPE_KEYGUARD ||
+                            ((win.mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
                             win.mAppToken != null && win.mAppToken.layoutConfigChanges))
                     || win.mAttrs.type == TYPE_UNIVERSE_BACKGROUND) {
                 if (!win.mLayoutAttached) {
@@ -8678,8 +8660,7 @@
                 wtoken.deferClearAllDrawn = false;
             }
 
-            boolean useAlternateThumbnailAnimation =
-                            SystemProperties.getBoolean("persist.anim.use_alt_thumbnail", false);
+            boolean useAlternateThumbnailAnimation = (mCurConfiguration.smallestScreenWidthDp < 600);
             AppWindowAnimator appAnimator =
                     topOpeningApp == null ? null : topOpeningApp.mAppAnimator;
             Bitmap nextAppTransitionThumbnail = mAppTransition.getNextAppTransitionThumbnail();
@@ -8890,8 +8871,8 @@
             if (canBeSeen
                     && (type == TYPE_SYSTEM_DIALOG
                      || type == TYPE_RECENTS_OVERLAY
-                     || type == TYPE_KEYGUARD
-                     || type == TYPE_SYSTEM_ERROR)) {
+                     || type == TYPE_SYSTEM_ERROR
+                     || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0)) {
                 mInnerFields.mSyswin = true;
             }
 
@@ -8904,7 +8885,7 @@
                     // content on secondary displays (by forcibly enabling mirroring unless
                     // there is other content we want to show) but still allow opaque
                     // keyguard dialogs to be shown.
-                    if (type == TYPE_DREAM || type == TYPE_KEYGUARD) {
+                    if (type == TYPE_DREAM || (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
                         mInnerFields.mObscureApplicationContentOnSecondaryDisplays = true;
                     }
                     mInnerFields.mDisplayHasContent = true;
@@ -9019,7 +9000,7 @@
                 mStrictModeFlash.positionSurface(defaultDw, defaultDh);
             }
             if (mCircularDisplayMask != null) {
-                mCircularDisplayMask.positionSurface(defaultDw, defaultDh);
+                mCircularDisplayMask.positionSurface(defaultDw, defaultDh, mRotation);
             }
 
             boolean focusDisplayed = false;
@@ -10264,6 +10245,51 @@
         return mSafeMode;
     }
 
+    @Override
+    public boolean clearWindowContentFrameStats(IBinder token) {
+        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+                "clearWindowContentFrameStats()")) {
+            throw new SecurityException("Requires FRAME_STATS permission");
+        }
+        synchronized (mWindowMap) {
+            WindowState windowState = mWindowMap.get(token);
+            if (windowState == null) {
+                return false;
+            }
+            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+            if (surfaceControl == null) {
+                return false;
+            }
+            return surfaceControl.clearContentFrameStats();
+        }
+    }
+
+    @Override
+    public WindowContentFrameStats getWindowContentFrameStats(IBinder token) {
+        if (!checkCallingPermission(Manifest.permission.FRAME_STATS,
+                "getWindowContentFrameStats()")) {
+            throw new SecurityException("Requires FRAME_STATS permission");
+        }
+        synchronized (mWindowMap) {
+            WindowState windowState = mWindowMap.get(token);
+            if (windowState == null) {
+                return null;
+            }
+            SurfaceControl surfaceControl = windowState.mWinAnimator.mSurfaceControl;
+            if (surfaceControl == null) {
+                return null;
+            }
+            if (mTempWindowRenderStats == null) {
+                mTempWindowRenderStats = new WindowContentFrameStats();
+            }
+            WindowContentFrameStats stats = mTempWindowRenderStats;
+            if (!surfaceControl.getContentFrameStats(stats)) {
+                return null;
+            }
+            return stats;
+        }
+    }
+
     void dumpPolicyLocked(PrintWriter pw, String[] args, boolean dumpAll) {
         pw.println("WINDOW MANAGER POLICY STATE (dumpsys window policy)");
         mPolicy.dump("    ", pw, args);
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index dff75ef..4318b0e 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -23,12 +23,12 @@
 import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
 
 import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 
 import android.app.AppOpsManager;
@@ -1010,7 +1010,7 @@
                 && (mConfiguration == null
                         || (mConfiguration.diff(mService.mCurConfiguration) != 0));
 
-        if (mAttrs.type == TYPE_KEYGUARD) {
+        if ((mAttrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0) {
             // Retain configuration changed status until resetConfiguration called.
             mConfigHasChanged |= configChanged;
             configChanged = mConfigHasChanged;
diff --git a/services/core/jni/Android.mk b/services/core/jni/Android.mk
index 1b3887c..51583a5 100644
--- a/services/core/jni/Android.mk
+++ b/services/core/jni/Android.mk
@@ -11,7 +11,9 @@
     $(LOCAL_REL_DIR)/com_android_server_connectivity_Vpn.cpp \
     $(LOCAL_REL_DIR)/com_android_server_ConsumerIrService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_dreams_McuHal.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecController.cpp \
     $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiCecService.cpp \
+    $(LOCAL_REL_DIR)/com_android_server_hdmi_HdmiMhlController.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputApplicationHandle.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputManagerService.cpp \
     $(LOCAL_REL_DIR)/com_android_server_input_InputWindowHandle.cpp \
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
new file mode 100644
index 0000000..f3e8f3c
--- /dev/null
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecController.cpp
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "HdmiCecControllerJni"
+
+#define LOG_NDEBUG 1
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/Log.h>
+#include <hardware/hdmi_cec.h>
+
+namespace android {
+
+static struct {
+    jmethodID handleMessage;
+} gHdmiCecControllerClassInfo;
+
+
+class HdmiCecController {
+public:
+    HdmiCecController(jobject callbacksObj);
+
+private:
+    static void onReceived(const hdmi_event_t* event, void* arg);
+
+    jobject mCallbacksObj;
+};
+
+HdmiCecController::HdmiCecController(jobject callbacksObj) :
+    mCallbacksObj(callbacksObj) {
+}
+
+// static
+void HdmiCecController::onReceived(const hdmi_event_t* event, void* arg) {
+    HdmiCecController* handler = static_cast<HdmiCecController*>(arg);
+    if (handler == NULL) {
+        return;
+    }
+
+    // TODO: propagate message to Java layer.
+}
+
+
+//------------------------------------------------------------------------------
+static jlong nativeInit(JNIEnv* env, jclass clazz, jobject callbacksObj) {
+    // TODO: initialize hal and pass it to controller if ready.
+
+    HdmiCecController* controller = new HdmiCecController(
+            env->NewGlobalRef(callbacksObj));
+
+    return reinterpret_cast<jlong>(controller);
+}
+
+static JNINativeMethod sMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeInit", "(Lcom/android/server/hdmi/HdmiCecController;)J",
+            (void *) nativeInit },
+};
+
+#define CLASS_PATH "com/android/server/hdmi/HdmiCecController"
+
+int register_android_server_hdmi_HdmiCecController(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, CLASS_PATH, sMethods, NELEM(sMethods));
+    LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+    return 0;
+}
+
+}  /* namespace android */
diff --git a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
index a00aaa8..6e03993 100644
--- a/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
+++ b/services/core/jni/com_android_server_hdmi_HdmiCecService.cpp
@@ -67,10 +67,10 @@
 
     cec_logical_address_t getLogicalAddress(cec_device_type_t deviceType);
     uint16_t getPhysicalAddress();
-    int getDeviceType(cec_logical_address_t addr);
+    cec_device_type_t getDeviceType(cec_logical_address_t addr);
     void queueMessage(const MessageEntry& message);
     void queueOutgoingMessage(const cec_message_t& message);
-    void sendReportPhysicalAddress();
+    void sendReportPhysicalAddress(cec_logical_address_t srcAddr);
     void sendActiveSource(cec_logical_address_t srcAddr);
     void sendFeatureAbort(cec_logical_address_t srcAddr, cec_logical_address_t dstAddr,
             int opcode, int reason);
@@ -93,15 +93,41 @@
         EVENT_TYPE_STANDBY
     };
 
+    /*
+     * logical address pool for each device type.
+     */
+    static const cec_logical_address_t TV_ADDR_POOL[];
+    static const cec_logical_address_t PLAYBACK_ADDR_POOL[];
+    static const cec_logical_address_t RECORDER_ADDR_POOL[];
+    static const cec_logical_address_t TUNER_ADDR_POOL[];
+
     static const unsigned int MAX_BUFFER_SIZE = 256;
     static const uint16_t INVALID_PHYSICAL_ADDRESS = 0xFFFF;
-    static const int INACTIVE_DEVICE_TYPE = -1;
 
     static void onReceived(const hdmi_event_t* event, void* arg);
     static void checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     void updatePhysicalAddress();
     void updateLogicalAddress();
+
+    // Allocate logical address. The CEC standard recommends that we try to use the address
+    // we have ever used before, in case this is to allocate an address afte the cable is
+    // connected again. If preferredAddr is given a valid one (not CEC_ADDR_UNREGISTERED), then
+    // this method checks if the address is available first. If not, it tries other addresses
+    // int the address pool available for the given type.
+    cec_logical_address_t allocateLogicalAddress(cec_device_type_t type,
+            cec_logical_address_t preferredAddr);
+
+    // Send a CEC ping message. Returns true if successful.
+    bool sendPing(cec_logical_address_t addr);
+
+    // Return the pool of logical addresses that are used for a given device type.
+    // One of the addresses in the pool will be chosen in the allocation logic.
+    bool getLogicalAddressPool(cec_device_type_t type, const cec_logical_address_t** addrPool,
+            size_t* poolSize);
+
+    // Handles the message retrieved from internal message queue. The message can be
+    // for either rx or tx.
     void dispatchMessage(const MessageEntry& message);
     void processIncomingMessage(const cec_message_t& msg);
 
@@ -159,6 +185,29 @@
     std::string mOsdName;
 };
 
+    const cec_logical_address_t HdmiCecHandler::TV_ADDR_POOL[] = {
+        CEC_ADDR_TV,
+        CEC_ADDR_FREE_USE,
+    };
+
+    const cec_logical_address_t HdmiCecHandler::PLAYBACK_ADDR_POOL[] = {
+        CEC_ADDR_PLAYBACK_1,
+        CEC_ADDR_PLAYBACK_2,
+        CEC_ADDR_PLAYBACK_3
+    };
+
+    const cec_logical_address_t HdmiCecHandler::RECORDER_ADDR_POOL[] = {
+        CEC_ADDR_RECORDER_1,
+        CEC_ADDR_RECORDER_2,
+        CEC_ADDR_RECORDER_3
+    };
+
+    const cec_logical_address_t HdmiCecHandler::TUNER_ADDR_POOL[] = {
+        CEC_ADDR_TUNER_1,
+        CEC_ADDR_TUNER_2,
+        CEC_ADDR_TUNER_3,
+        CEC_ADDR_TUNER_4
+    };
 
 HdmiCecHandler::HdmiCecHandler(hdmi_cec_device_t* device, jobject callbacksObj) :
     mDevice(device),
@@ -176,34 +225,15 @@
     return mPhysicalAddress;
 }
 
-void HdmiCecHandler::updatePhysicalAddress() {
-    uint16_t addr;
-    if (!mDevice->get_physical_address(mDevice, &addr)) {
-        mPhysicalAddress = addr;
-    } else {
-        mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
-    }
-}
-
-void HdmiCecHandler::updateLogicalAddress() {
-    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
-    for (; it != mLogicalDevices.end(); ++it) {
-        cec_logical_address_t addr;
-        if (!mDevice->get_logical_address(mDevice, it->first, &addr)) {
-            it->second = addr;
-        }
-    }
-}
-
 cec_logical_address_t HdmiCecHandler::initLogicalDevice(cec_device_type_t type) {
-    cec_logical_address_t addr;
-    int res = mDevice->allocate_logical_address(mDevice, type, &addr);
-
-    if (res != 0) {
-        ALOGE("Logical Address Allocation failed: %d", res);
-    } else {
-        ALOGV("Logical Address Allocation success: %d", addr);
+    cec_logical_address addr = allocateLogicalAddress(type, CEC_ADDR_UNREGISTERED);
+    if (addr != CEC_ADDR_UNREGISTERED && !mDevice->add_logical_address(mDevice, addr)) {
         mLogicalDevices.insert(std::pair<cec_device_type_t, cec_logical_address_t>(type, addr));
+
+        // Broadcast <Report Physical Address> when a new logical address was allocated to let
+        // other devices discover the new logical device and its logical - physical address
+        // association.
+        sendReportPhysicalAddress(addr);
     }
     return addr;
 }
@@ -224,14 +254,14 @@
     return CEC_ADDR_UNREGISTERED;
 }
 
-int HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
+cec_device_type_t HdmiCecHandler::getDeviceType(cec_logical_address_t addr) {
     std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
     for (; it != mLogicalDevices.end(); ++it) {
         if (it->second == addr) {
             return it->first;
         }
     }
-    return INACTIVE_DEVICE_TYPE;
+    return CEC_DEVICE_INACTIVE;
 }
 
 void HdmiCecHandler::queueMessage(const MessageEntry& entry) {
@@ -251,26 +281,26 @@
     queueMessage(entry);
 }
 
-void HdmiCecHandler::sendReportPhysicalAddress() {
+void HdmiCecHandler::sendReportPhysicalAddress(cec_logical_address_t addr) {
     if (mPhysicalAddress == INVALID_PHYSICAL_ADDRESS) {
         ALOGE("Invalid physical address.");
         return;
     }
-
-    // Report physical address for each logical one hosted in it.
-    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
-    while (it != mLogicalDevices.end()) {
-        cec_message_t msg;
-        msg.initiator = it->second;  // logical address
-        msg.destination = CEC_ADDR_BROADCAST;
-        msg.length = 4;
-        msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
-        msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
-        msg.body[2] = mPhysicalAddress & 0xff;
-        msg.body[3] = it->first;  // device type
-        queueOutgoingMessage(msg);
-        ++it;
+    cec_device_type_t deviceType = getDeviceType(addr);
+    if (deviceType == CEC_DEVICE_INACTIVE) {
+        ALOGE("Invalid logical address: %d", addr);
+        return;
     }
+
+    cec_message_t msg;
+    msg.initiator = addr;
+    msg.destination = CEC_ADDR_BROADCAST;
+    msg.length = 4;
+    msg.body[0] = CEC_MESSAGE_REPORT_PHYSICAL_ADDRESS;
+    msg.body[1] = (mPhysicalAddress >> 8) & 0xff;
+    msg.body[2] = mPhysicalAddress & 0xff;
+    msg.body[3] = deviceType;
+    queueOutgoingMessage(msg);
 }
 
 void HdmiCecHandler::sendActiveSource(cec_logical_address_t srcAddr) {
@@ -405,6 +435,99 @@
     }
 }
 
+void HdmiCecHandler::updatePhysicalAddress() {
+    uint16_t addr;
+    if (!mDevice->get_physical_address(mDevice, &addr)) {
+        mPhysicalAddress = addr;
+    } else {
+        mPhysicalAddress = INVALID_PHYSICAL_ADDRESS;
+    }
+}
+
+void HdmiCecHandler::updateLogicalAddress() {
+    mDevice->clear_logical_address(mDevice);
+    std::map<cec_device_type_t, cec_logical_address_t>::iterator it = mLogicalDevices.begin();
+    for (; it != mLogicalDevices.end(); ++it) {
+        cec_logical_address_t addr;
+        cec_logical_address_t preferredAddr = it->second;
+        cec_device_type_t deviceType = it->first;
+        addr = allocateLogicalAddress(deviceType, preferredAddr);
+        if (!mDevice->add_logical_address(mDevice, addr)) {
+            it->second = addr;
+        } else {
+            it->second = CEC_ADDR_UNREGISTERED;
+        }
+    }
+}
+
+cec_logical_address_t HdmiCecHandler::allocateLogicalAddress(cec_device_type_t type,
+        cec_logical_address_t preferredAddr) {
+    const cec_logical_address_t* addrPool;
+    size_t poolSize;
+    if (getLogicalAddressPool(type, &addrPool, &poolSize) < 0) {
+        return CEC_ADDR_UNREGISTERED;
+    }
+    unsigned start = 0;
+
+    // Find the index of preferred address in the pool. If not found, the start
+    // position will be 0. This happens when the passed preferredAddr is set to
+    // CEC_ADDR_UNREGISTERED, meaning that no preferred address is given.
+    for (unsigned i = 0; i < poolSize; i++) {
+        if (addrPool[i] == preferredAddr) {
+            start = i;
+            break;
+        }
+    }
+    for (unsigned i = 0; i < poolSize; i++) {
+        cec_logical_address_t addr = addrPool[(start + i) % poolSize];
+        if (!sendPing(addr)) {
+            // Failure in pinging means the address is available, not taken by any device.
+            ALOGV("Logical Address Allocation success: %d", addr);
+            return addr;
+        }
+    }
+    ALOGE("Logical Address Allocation failed");
+    return CEC_ADDR_UNREGISTERED;
+}
+
+bool HdmiCecHandler::sendPing(cec_logical_address addr) {
+    cec_message_t msg;
+    msg.initiator = msg.destination = addr;
+    msg.length = 0;
+    return !mDevice->send_message(mDevice, &msg);
+
+}
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+bool HdmiCecHandler::getLogicalAddressPool(cec_device_type_t deviceType,
+        const cec_logical_address_t** addrPool, size_t* poolSize) {
+    switch (deviceType) {
+    case CEC_DEVICE_TV:
+        *addrPool = TV_ADDR_POOL;
+        *poolSize = ARRAY_SIZE(TV_ADDR_POOL);
+        break;
+    case CEC_DEVICE_RECORDER:
+        *addrPool = RECORDER_ADDR_POOL;
+        *poolSize = ARRAY_SIZE(RECORDER_ADDR_POOL);
+        break;
+    case CEC_DEVICE_TUNER:
+        *addrPool = TUNER_ADDR_POOL;
+        *poolSize = ARRAY_SIZE(TUNER_ADDR_POOL);
+        break;
+    case CEC_DEVICE_PLAYBACK:
+        *addrPool = PLAYBACK_ADDR_POOL;
+        *poolSize = ARRAY_SIZE(PLAYBACK_ADDR_POOL);
+        break;
+    default:
+        ALOGE("Unsupported device type: %d", deviceType);
+        return false;
+    }
+    return true;
+}
+
+#undef ARRAY_SIZE
+
 void HdmiCecHandler::dispatchMessage(const MessageEntry& entry) {
     int type = entry.first;
     mMessageQueueLock.unlock();
@@ -429,7 +552,7 @@
 void HdmiCecHandler::processIncomingMessage(const cec_message_t& msg) {
     int opcode = msg.body[0];
     if (opcode == CEC_MESSAGE_GIVE_PHYSICAL_ADDRESS) {
-        sendReportPhysicalAddress();
+        sendReportPhysicalAddress(msg.destination);
     } else if (opcode == CEC_MESSAGE_REQUEST_ACTIVE_SOURCE) {
         handleRequestActiveSource();
     } else if (opcode == CEC_MESSAGE_GET_OSD_NAME) {
@@ -502,7 +625,7 @@
     JNIEnv* env = AndroidRuntime::getJNIEnv();
     jint activeDeviceType = env->CallIntMethod(mCallbacksObj,
             gHdmiCecServiceClassInfo.getActiveSource);
-    if (activeDeviceType != INACTIVE_DEVICE_TYPE) {
+    if (activeDeviceType != CEC_DEVICE_INACTIVE) {
         sendActiveSource(getLogicalAddress(static_cast<cec_device_type_t>(activeDeviceType)));
     }
     checkAndClearExceptionFromCallback(env, __FUNCTION__);
diff --git a/services/core/jni/com_android_server_input_InputManagerService.cpp b/services/core/jni/com_android_server_input_InputManagerService.cpp
index b3247ff..34ae8b4 100644
--- a/services/core/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/core/jni/com_android_server_input_InputManagerService.cpp
@@ -71,7 +71,7 @@
     jmethodID notifyANR;
     jmethodID filterInputEvent;
     jmethodID interceptKeyBeforeQueueing;
-    jmethodID interceptMotionBeforeQueueingWhenScreenOff;
+    jmethodID interceptWakeMotionBeforeQueueing;
     jmethodID interceptKeyBeforeDispatching;
     jmethodID dispatchUnhandledKey;
     jmethodID checkInjectEventsPermission;
@@ -189,6 +189,7 @@
     void setSystemUiVisibility(int32_t visibility);
     void setPointerSpeed(int32_t speed);
     void setShowTouches(bool enabled);
+    void setInteractive(bool interactive);
     void reloadCalibration();
 
     /* --- InputReaderPolicyInterface implementation --- */
@@ -214,7 +215,6 @@
     virtual void notifyInputChannelBroken(const sp<InputWindowHandle>& inputWindowHandle);
     virtual bool filterInputEvent(const InputEvent* inputEvent, uint32_t policyFlags);
     virtual void getDispatcherConfiguration(InputDispatcherConfiguration* outConfig);
-    virtual bool isKeyRepeatEnabled();
     virtual void interceptKeyBeforeQueueing(const KeyEvent* keyEvent, uint32_t& policyFlags);
     virtual void interceptMotionBeforeQueueing(nsecs_t when, uint32_t& policyFlags);
     virtual nsecs_t interceptKeyBeforeDispatching(
@@ -262,14 +262,12 @@
         wp<PointerController> pointerController;
     } mLocked;
 
+    volatile bool mInteractive;
+
     void updateInactivityTimeoutLocked(const sp<PointerController>& controller);
     void handleInterceptActions(jint wmActions, nsecs_t when, uint32_t& policyFlags);
     void ensureSpriteControllerLocked();
 
-    // Power manager interactions.
-    bool isScreenOn();
-    bool isScreenBright();
-
     static bool checkAndClearExceptionFromCallback(JNIEnv* env, const char* methodName);
 
     static inline JNIEnv* jniEnv() {
@@ -281,7 +279,7 @@
 
 NativeInputManager::NativeInputManager(jobject contextObj,
         jobject serviceObj, const sp<Looper>& looper) :
-        mLooper(looper) {
+        mLooper(looper), mInteractive(true) {
     JNIEnv* env = jniEnv();
 
     mContextObj = env->NewGlobalRef(contextObj);
@@ -637,11 +635,6 @@
     }
 }
 
-bool NativeInputManager::isKeyRepeatEnabled() {
-    // Only enable automatic key repeating when the screen is on.
-    return isScreenOn();
-}
-
 void NativeInputManager::setInputWindows(JNIEnv* env, jobjectArray windowHandleObjArray) {
     Vector<sp<InputWindowHandle> > windowHandles;
 
@@ -753,19 +746,15 @@
             InputReaderConfiguration::CHANGE_SHOW_TOUCHES);
 }
 
+void NativeInputManager::setInteractive(bool interactive) {
+    mInteractive = interactive;
+}
+
 void NativeInputManager::reloadCalibration() {
     mInputManager->getReader()->requestRefreshConfiguration(
             InputReaderConfiguration::TOUCH_AFFINE_TRANSFORMATION);
 }
 
-bool NativeInputManager::isScreenOn() {
-    return android_server_PowerManagerService_isScreenOn();
-}
-
-bool NativeInputManager::isScreenBright() {
-    return android_server_PowerManagerService_isScreenBright();
-}
-
 TouchAffineTransformation NativeInputManager::getTouchAffineTransformation(
         JNIEnv *env, jfloatArray matrixArr) {
     ScopedFloatArrayRO matrix(env, matrixArr);
@@ -841,18 +830,18 @@
     // - Ignore untrusted events and pass them along.
     // - Ask the window manager what to do with normal events and trusted injected events.
     // - For normal events wake and brighten the screen if currently off or dim.
+    if (mInteractive) {
+        policyFlags |= POLICY_FLAG_INTERACTIVE;
+    }
     if ((policyFlags & POLICY_FLAG_TRUSTED)) {
         nsecs_t when = keyEvent->getEventTime();
-        bool isScreenOn = this->isScreenOn();
-        bool isScreenBright = this->isScreenBright();
-
         JNIEnv* env = jniEnv();
         jobject keyEventObj = android_view_KeyEvent_fromNative(env, keyEvent);
         jint wmActions;
         if (keyEventObj) {
             wmActions = env->CallIntMethod(mServiceObj,
                     gServiceClassInfo.interceptKeyBeforeQueueing,
-                    keyEventObj, policyFlags, isScreenOn);
+                    keyEventObj, policyFlags);
             if (checkAndClearExceptionFromCallback(env, "interceptKeyBeforeQueueing")) {
                 wmActions = 0;
             }
@@ -863,16 +852,6 @@
             wmActions = 0;
         }
 
-        if (!(policyFlags & POLICY_FLAG_INJECTED)) {
-            if (!isScreenOn) {
-                policyFlags |= POLICY_FLAG_WOKE_HERE;
-            }
-
-            if (!isScreenBright) {
-                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
-            }
-        }
-
         handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
     } else {
         policyFlags |= POLICY_FLAG_PASS_TO_USER;
@@ -885,24 +864,22 @@
     // - No special filtering for injected events required at this time.
     // - Filter normal events based on screen state.
     // - For normal events brighten (but do not wake) the screen if currently dim.
+    if (mInteractive) {
+        policyFlags |= POLICY_FLAG_INTERACTIVE;
+    }
     if ((policyFlags & POLICY_FLAG_TRUSTED) && !(policyFlags & POLICY_FLAG_INJECTED)) {
-        if (isScreenOn()) {
+        if (policyFlags & POLICY_FLAG_INTERACTIVE) {
             policyFlags |= POLICY_FLAG_PASS_TO_USER;
-
-            if (!isScreenBright()) {
-                policyFlags |= POLICY_FLAG_BRIGHT_HERE;
-            }
-        } else {
+        } else if (policyFlags & POLICY_FLAG_WAKE) {
             JNIEnv* env = jniEnv();
             jint wmActions = env->CallIntMethod(mServiceObj,
-                        gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
+                        gServiceClassInfo.interceptWakeMotionBeforeQueueing,
                         when, policyFlags);
             if (checkAndClearExceptionFromCallback(env,
-                    "interceptMotionBeforeQueueingWhenScreenOff")) {
+                    "interceptWakeMotionBeforeQueueing")) {
                 wmActions = 0;
             }
 
-            policyFlags |= POLICY_FLAG_WOKE_HERE | POLICY_FLAG_BRIGHT_HERE;
             handleInterceptActions(wmActions, when, /*byref*/ policyFlags);
         }
     } else {
@@ -1285,6 +1262,13 @@
     im->setShowTouches(enabled);
 }
 
+static void nativeSetInteractive(JNIEnv* env,
+        jclass clazz, jlong ptr, jboolean interactive) {
+    NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
+
+    im->setInteractive(interactive);
+}
+
 static void nativeReloadCalibration(JNIEnv* env, jclass clazz, jlong ptr) {
     NativeInputManager* im = reinterpret_cast<NativeInputManager*>(ptr);
     im->reloadCalibration();
@@ -1395,6 +1379,8 @@
             (void*) nativeSetPointerSpeed },
     { "nativeSetShowTouches", "(JZ)V",
             (void*) nativeSetShowTouches },
+    { "nativeSetInteractive", "(JZ)V",
+            (void*) nativeSetInteractive },
     { "nativeReloadCalibration", "(J)V",
             (void*) nativeReloadCalibration },
     { "nativeVibrate", "(JI[JII)V",
@@ -1453,11 +1439,10 @@
             "filterInputEvent", "(Landroid/view/InputEvent;I)Z");
 
     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeQueueing, clazz,
-            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;IZ)I");
+            "interceptKeyBeforeQueueing", "(Landroid/view/KeyEvent;I)I");
 
-    GET_METHOD_ID(gServiceClassInfo.interceptMotionBeforeQueueingWhenScreenOff,
-            clazz,
-            "interceptMotionBeforeQueueingWhenScreenOff", "(JI)I");
+    GET_METHOD_ID(gServiceClassInfo.interceptWakeMotionBeforeQueueing, clazz,
+            "interceptWakeMotionBeforeQueueing", "(JI)I");
 
     GET_METHOD_ID(gServiceClassInfo.interceptKeyBeforeDispatching, clazz,
             "interceptKeyBeforeDispatching",
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index dbf5439..33e0bd7 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -42,8 +42,6 @@
 // ----------------------------------------------------------------------------
 
 static struct {
-    jmethodID wakeUpFromNative;
-    jmethodID goToSleepFromNative;
     jmethodID userActivityFromNative;
 } gPowerManagerServiceClassInfo;
 
@@ -52,10 +50,6 @@
 static jobject gPowerManagerServiceObj;
 static struct power_module* gPowerModule;
 
-static Mutex gPowerManagerLock;
-static bool gScreenOn;
-static bool gScreenBright;
-
 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
 
 // Throttling interval for user activity calls.
@@ -73,16 +67,6 @@
     return false;
 }
 
-bool android_server_PowerManagerService_isScreenOn() {
-    AutoMutex _l(gPowerManagerLock);
-    return gScreenOn;
-}
-
-bool android_server_PowerManagerService_isScreenBright() {
-    AutoMutex _l(gPowerManagerLock);
-    return gScreenBright;
-}
-
 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
     // Tell the power HAL when user activity occurs.
     if (gPowerModule && gPowerModule->powerHint) {
@@ -114,28 +98,6 @@
     }
 }
 
-void android_server_PowerManagerService_wakeUp(nsecs_t eventTime) {
-    if (gPowerManagerServiceObj) {
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-        env->CallVoidMethod(gPowerManagerServiceObj,
-                gPowerManagerServiceClassInfo.wakeUpFromNative,
-                nanoseconds_to_milliseconds(eventTime));
-        checkAndClearExceptionFromCallback(env, "wakeUpFromNative");
-    }
-}
-
-void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
-    if (gPowerManagerServiceObj) {
-        JNIEnv* env = AndroidRuntime::getJNIEnv();
-
-        env->CallVoidMethod(gPowerManagerServiceObj,
-                gPowerManagerServiceClassInfo.goToSleepFromNative,
-                nanoseconds_to_milliseconds(eventTime), 0);
-        checkAndClearExceptionFromCallback(env, "goToSleepFromNative");
-    }
-}
-
 // ----------------------------------------------------------------------------
 
 static void nativeInit(JNIEnv* env, jobject obj) {
@@ -150,13 +112,6 @@
     }
 }
 
-static void nativeSetPowerState(JNIEnv* env,
-        jclass clazz, jboolean screenOn, jboolean screenBright) {
-    AutoMutex _l(gPowerManagerLock);
-    gScreenOn = screenOn;
-    gScreenBright = screenBright;
-}
-
 static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
     ScopedUtfChars name(env, nameStr);
     acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
@@ -207,8 +162,6 @@
     /* name, signature, funcPtr */
     { "nativeInit", "()V",
             (void*) nativeInit },
-    { "nativeSetPowerState", "(ZZ)V",
-            (void*) nativeSetPowerState },
     { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
             (void*) nativeAcquireSuspendBlocker },
     { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
@@ -243,12 +196,6 @@
     jclass clazz;
     FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
 
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
-            "wakeUpFromNative", "(J)V");
-
-    GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz,
-            "goToSleepFromNative", "(JI)V");
-
     GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
             "userActivityFromNative", "(JII)V");
 
@@ -256,8 +203,6 @@
     for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
         gLastEventTime[i] = LLONG_MIN;
     }
-    gScreenOn = true;
-    gScreenBright = true;
     gPowerManagerServiceObj = NULL;
     gPowerModule = NULL;
     return 0;
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.h b/services/core/jni/com_android_server_power_PowerManagerService.h
index b48e546..f5fd3d6 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.h
+++ b/services/core/jni/com_android_server_power_PowerManagerService.h
@@ -24,11 +24,7 @@
 
 namespace android {
 
-extern bool android_server_PowerManagerService_isScreenOn();
-extern bool android_server_PowerManagerService_isScreenBright();
 extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
-extern void android_server_PowerManagerService_wakeUp(nsecs_t eventTime);
-extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
 
 } // namespace android
 
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index bf9f7f4..1feb325 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -38,7 +38,9 @@
 int register_android_server_location_FlpHardwareProvider(JNIEnv* env);
 int register_android_server_connectivity_Vpn(JNIEnv* env);
 int register_android_server_dreams_McuHal(JNIEnv* env);
+int register_android_server_hdmi_HdmiCecController(JNIEnv* env);
 int register_android_server_hdmi_HdmiCecService(JNIEnv* env);
+int register_android_server_hdmi_HdmiMhlController(JNIEnv* env);
 };
 
 using namespace android;
@@ -72,7 +74,10 @@
     register_android_server_ConsumerIrService(env);
     register_android_server_dreams_McuHal(env);
     register_android_server_BatteryStatsService(env);
+    register_android_server_hdmi_HdmiCecController(env);
+    // TODO: remove this once replaces HdmiCecService with HdmiControlService.
     register_android_server_hdmi_HdmiCecService(env);
+    register_android_server_hdmi_HdmiMhlController(env);
 
     return JNI_VERSION_1_4;
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
index 1b048a1..1647425 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DeviceOwner.java
@@ -61,11 +61,10 @@
     private OutputStream mOutputStreamForTest;
 
     // Internal state for the device owner package.
-    private String mDeviceOwnerPackageName;
-    private String mDeviceOwnerName;
+    private OwnerInfo mDeviceOwner;
 
     // Internal state for the profile owner packages.
-    private final HashMap<Integer, String[]> mProfileOwners = new HashMap<Integer, String[]>();
+    private final HashMap<Integer, OwnerInfo> mProfileOwners = new HashMap<Integer, OwnerInfo>();
 
     // Private default constructor.
     private DeviceOwner() {
@@ -95,8 +94,7 @@
      */
     static DeviceOwner createWithDeviceOwner(String packageName, String ownerName) {
         DeviceOwner owner = new DeviceOwner();
-        owner.mDeviceOwnerPackageName = packageName;
-        owner.mDeviceOwnerName = ownerName;
+        owner.mDeviceOwner = new OwnerInfo(ownerName, packageName);
         return owner;
     }
 
@@ -105,25 +103,24 @@
      */
     static DeviceOwner createWithProfileOwner(String packageName, String ownerName, int userId) {
         DeviceOwner owner = new DeviceOwner();
-        owner.mProfileOwners.put(userId, new String[] { packageName, ownerName });
+        owner.mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
         return owner;
     }
 
     String getDeviceOwnerPackageName() {
-        return mDeviceOwnerPackageName;
+        return mDeviceOwner != null ? mDeviceOwner.packageName : null;
     }
 
     String getDeviceOwnerName() {
-        return mDeviceOwnerName;
+        return mDeviceOwner != null ? mDeviceOwner.name : null;
     }
 
     void setDeviceOwner(String packageName, String ownerName) {
-        mDeviceOwnerPackageName = packageName;
-        mDeviceOwnerName = ownerName;
+        mDeviceOwner = new OwnerInfo(ownerName, packageName);
     }
 
     void setProfileOwner(String packageName, String ownerName, int userId) {
-        mProfileOwners.put(userId, new String[] { packageName, ownerName });
+        mProfileOwners.put(userId, new OwnerInfo(ownerName, packageName));
     }
 
     void removeProfileOwner(int userId) {
@@ -131,17 +128,17 @@
     }
 
     String getProfileOwnerPackageName(int userId) {
-        String[] profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner[0] : null;
+        OwnerInfo profileOwner = mProfileOwners.get(userId);
+        return profileOwner != null ? profileOwner.packageName : null;
     }
 
     String getProfileOwnerName(int userId) {
-        String[] profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner[1] : null;
+        OwnerInfo profileOwner = mProfileOwners.get(userId);
+        return profileOwner != null ? profileOwner.name : null;
     }
 
     boolean hasDeviceOwner() {
-        return mDeviceOwnerPackageName != null;
+        return mDeviceOwner != null;
     }
 
     static boolean isInstalled(String packageName, PackageManager pm) {
@@ -185,14 +182,15 @@
 
                 String tag = parser.getName();
                 if (tag.equals(TAG_DEVICE_OWNER)) {
-                    mDeviceOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
-                    mDeviceOwnerName = parser.getAttributeValue(null, ATTR_NAME);
+                    mDeviceOwner = new OwnerInfo(
+                            parser.getAttributeValue(null, ATTR_NAME),
+                            parser.getAttributeValue(null, ATTR_PACKAGE));
                 } else if (tag.equals(TAG_PROFILE_OWNER)) {
                     String profileOwnerPackageName = parser.getAttributeValue(null, ATTR_PACKAGE);
                     String profileOwnerName = parser.getAttributeValue(null, ATTR_NAME);
                     int userId = Integer.parseInt(parser.getAttributeValue(null, ATTR_USERID));
                     mProfileOwners.put(userId,
-                            new String[] { profileOwnerPackageName, profileOwnerName });
+                            new OwnerInfo(profileOwnerName, profileOwnerPackageName));
                 } else {
                     throw new XmlPullParserException(
                             "Unexpected tag in device owner file: " + tag);
@@ -220,21 +218,21 @@
             out.startDocument(null, true);
 
             // Write device owner tag
-            if (mDeviceOwnerPackageName != null) {
+            if (mDeviceOwner != null) {
                 out.startTag(null, TAG_DEVICE_OWNER);
-                out.attribute(null, ATTR_PACKAGE, mDeviceOwnerPackageName);
-                if (mDeviceOwnerName != null) {
-                    out.attribute(null, ATTR_NAME, mDeviceOwnerName);
+                out.attribute(null, ATTR_PACKAGE, mDeviceOwner.packageName);
+                if (mDeviceOwner.packageName != null) {
+                    out.attribute(null, ATTR_NAME, mDeviceOwner.packageName);
                 }
                 out.endTag(null, TAG_DEVICE_OWNER);
             }
 
             // Write profile owner tags
             if (mProfileOwners.size() > 0) {
-                for (HashMap.Entry<Integer, String[]> owner : mProfileOwners.entrySet()) {
+                for (HashMap.Entry<Integer, OwnerInfo> owner : mProfileOwners.entrySet()) {
                     out.startTag(null, TAG_PROFILE_OWNER);
-                    out.attribute(null, ATTR_PACKAGE, owner.getValue()[0]);
-                    out.attribute(null, ATTR_NAME, owner.getValue()[1]);
+                    out.attribute(null, ATTR_PACKAGE, owner.getValue().packageName);
+                    out.attribute(null, ATTR_NAME, owner.getValue().name);
                     out.attribute(null, ATTR_USERID, Integer.toString(owner.getKey()));
                     out.endTag(null, TAG_PROFILE_OWNER);
                 }
@@ -271,4 +269,14 @@
             fileForWriting.finishWrite((FileOutputStream) stream);
         }
     }
-}
\ No newline at end of file
+
+    static class OwnerInfo {
+        public String name;
+        public String packageName;
+
+        public OwnerInfo(String name, String packageName) {
+            this.name = name;
+            this.packageName = packageName;
+        }
+    }
+}
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 983ca2d..aaa97eb 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -51,6 +51,7 @@
 import android.content.pm.UserInfo;
 import android.net.ProxyProperties;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -2827,7 +2828,7 @@
             return null;
         }
         synchronized (this) {
-            if (mDeviceOwner != null) {
+            if (mDeviceOwner != null && mDeviceOwner.hasDeviceOwner()) {
                 return mDeviceOwner.getDeviceOwnerPackageName();
             }
         }
@@ -2888,6 +2889,36 @@
     }
 
     @Override
+    public void setProfileEnabled(ComponentName who) {
+        if (!mHasFeature) {
+            return;
+        }
+        synchronized (this) {
+            // Check for permissions
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            // Check if this is the profile owner who is calling
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            int userId = UserHandle.getCallingUserId();
+            Slog.d(LOG_TAG, "Enabling the profile for: " + userId);
+
+            UserManager um = UserManager.get(mContext);
+            long id = Binder.clearCallingIdentity();
+            try {
+                um.setUserEnabled(userId);
+                Intent intent = new Intent(Intent.ACTION_MANAGED_PROFILE_ADDED);
+                intent.putExtra(Intent.EXTRA_USER, new UserHandle(UserHandle.getCallingUserId()));
+                intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY |
+                        Intent.FLAG_RECEIVER_FOREGROUND);
+                mContext.sendBroadcastAsUser(intent, UserHandle.OWNER);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    @Override
     public String getProfileOwner(int userHandle) {
         if (!mHasFeature) {
             return null;
@@ -3029,4 +3060,109 @@
             }
         }
     }
+
+    @Override
+    public void setApplicationRestrictions(ComponentName who, String packageName, Bundle settings) {
+        final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            UserManager um = UserManager.get(mContext);
+            long id = Binder.clearCallingIdentity();
+            try {
+                um.setApplicationRestrictions(packageName, settings, userHandle);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    public void forwardMatchingIntents(ComponentName who, IntentFilter filter, int flags) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                if ((flags & DevicePolicyManager.FLAG_TO_PRIMARY_USER) != 0) {
+                    pm.addForwardingIntentFilter(filter, callingUserId, UserHandle.USER_OWNER);
+                }
+                if ((flags & DevicePolicyManager.FLAG_TO_MANAGED_PROFILE) != 0) {
+                    pm.addForwardingIntentFilter(filter, UserHandle.USER_OWNER, callingUserId);
+                }
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    public void clearForwardingIntentFilters(ComponentName who) {
+        int callingUserId = UserHandle.getCallingUserId();
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+            IPackageManager pm = AppGlobals.getPackageManager();
+            long id = Binder.clearCallingIdentity();
+            try {
+                pm.clearForwardingIntentFilters(callingUserId);
+                pm.clearForwardingIntentFilters(UserHandle.USER_OWNER);
+            } catch (RemoteException re) {
+                // Shouldn't happen
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    @Override
+    public Bundle getApplicationRestrictions(ComponentName who, String packageName) {
+        final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            UserManager um = UserManager.get(mContext);
+            long id = Binder.clearCallingIdentity();
+            try {
+                return um.getApplicationRestrictions(packageName, userHandle);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
+
+    @Override
+    public void setUserRestriction(ComponentName who, String key, boolean enabled) {
+        final UserHandle userHandle = new UserHandle(UserHandle.getCallingUserId());
+
+        synchronized (this) {
+            if (who == null) {
+                throw new NullPointerException("ComponentName is null");
+            }
+            getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
+
+            UserManager um = UserManager.get(mContext);
+            long id = Binder.clearCallingIdentity();
+            try {
+                um.setUserRestriction(key, enabled, userHandle);
+            } finally {
+                restoreCallingIdentity(id);
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 912ac4d..7c9f7a8 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -29,6 +29,7 @@
 import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.media.AudioService;
+import android.os.Build;
 import android.os.Environment;
 import android.os.FactoryTest;
 import android.os.Handler;
@@ -59,8 +60,10 @@
 import com.android.server.am.BatteryStatsService;
 import com.android.server.clipboard.ClipboardService;
 import com.android.server.content.ContentService;
+import com.android.server.devicepolicy.DevicePolicyManagerService;
 import com.android.server.display.DisplayManagerService;
 import com.android.server.dreams.DreamManagerService;
+import com.android.server.hdmi.HdmiControlService;
 import com.android.server.input.InputManagerService;
 import com.android.server.lights.LightsManager;
 import com.android.server.lights.LightsService;
@@ -110,10 +113,10 @@
      */
     private static final String BACKUP_MANAGER_SERVICE_CLASS =
             "com.android.server.backup.BackupManagerService$Lifecycle";
-    private static final String DEVICE_POLICY_MANAGER_SERVICE_CLASS =
-            "com.android.server.devicepolicy.DevicePolicyManagerService$Lifecycle";
     private static final String APPWIDGET_SERVICE_CLASS =
             "com.android.server.appwidget.AppWidgetService";
+    private static final String VOICE_RECOGNITION_MANAGER_SERVICE_CLASS =
+            "com.android.server.voiceinteraction.VoiceInteractionManagerService";
     private static final String PRINT_MANAGER_SERVICE_CLASS =
             "com.android.server.print.PrintManagerService";
     private static final String USB_SERVICE_CLASS =
@@ -198,6 +201,10 @@
         // as efficient as possible with its memory usage.
         VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
 
+        // Some devices rely on runtime fingerprint generation, so make sure
+        // we've defined it before booting further.
+        Build.ensureFingerprintProperty();
+
         // Within the system server, it is an error to access Environment paths without
         // explicitly specifying a user.
         Environment.setUserRequired(true);
@@ -290,6 +297,7 @@
         // Activity manager runs the show.
         mActivityManagerService = mSystemServiceManager.startService(
                 ActivityManagerService.Lifecycle.class).getService();
+        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
     }
 
     private void startCoreServices() {
@@ -311,6 +319,7 @@
         NetworkStatsService networkStats = null;
         NetworkPolicyManagerService networkPolicy = null;
         ConnectivityService connectivity = null;
+        NetworkScoreService networkScore = null;
         NsdService serviceDiscovery= null;
         IPackageManager pm = null;
         WindowManagerService wm = null;
@@ -545,9 +554,9 @@
                 }
 
                 try {
-                    if (pm.hasSystemFeature(PackageManager.FEATURE_DEVICE_ADMIN)) {
-                        mSystemServiceManager.startService(DEVICE_POLICY_MANAGER_SERVICE_CLASS);
-                    }
+                    // Always start the Device Policy Manager, so that the API is compatible with
+                    // API8.
+                    mSystemServiceManager.startService(DevicePolicyManagerService.Lifecycle.class);
                 } catch (Throwable e) {
                     reportWtf("starting DevicePolicyService", e);
                 }
@@ -643,6 +652,14 @@
                 }
 
                 try {
+                    Slog.i(TAG, "Network Score Service");
+                    networkScore = new NetworkScoreService(context);
+                    ServiceManager.addService(Context.NETWORK_SCORE_SERVICE, networkScore);
+                } catch (Throwable e) {
+                    reportWtf("starting Network Score Service", e);
+                }
+
+                try {
                     Slog.i(TAG, "Network Service Discovery Service");
                     serviceDiscovery = NsdService.create(context);
                     ServiceManager.addService(
@@ -817,6 +834,15 @@
                 } catch (Throwable e) {
                     reportWtf("starting Recognition Service", e);
                 }
+
+                try {
+                    if (pm.hasSystemFeature(PackageManager.FEATURE_VOICE_RECOGNIZERS)) {
+                        Slog.i(TAG, "Voice Recognition Service");
+                        mSystemServiceManager.startService(VOICE_RECOGNITION_MANAGER_SERVICE_CLASS);
+                    }
+                } catch (Throwable e) {
+                    reportWtf("starting Voice Recognition Service", e);
+                }
             }
 
             try {
@@ -897,7 +923,6 @@
             }
 
             try {
-                Slog.i(TAG, "MediaSessionService");
                 mSystemServiceManager.startService(MediaSessionService.class);
             } catch (Throwable e) {
                 reportWtf("starting MediaSessionService", e);
@@ -910,6 +935,12 @@
             }
 
             try {
+                mSystemServiceManager.startService(HdmiControlService.class);
+            } catch (Throwable e) {
+                reportWtf("starting HdmiControlService", e);
+            }
+
+            try {
                 Slog.i(TAG, "TvInputManagerService");
                 mSystemServiceManager.startService(TvInputManagerService.class);
             } catch (Throwable e) {
@@ -1021,6 +1052,7 @@
         final NetworkStatsService networkStatsF = networkStats;
         final NetworkPolicyManagerService networkPolicyF = networkPolicy;
         final ConnectivityService connectivityF = connectivity;
+        final NetworkScoreService networkScoreF = networkScore;
         final DockObserver dockF = dock;
         final WallpaperManagerService wallpaperF = wallpaper;
         final InputMethodManagerService immF = imm;
@@ -1069,6 +1101,11 @@
                     reportWtf("making Battery Service ready", e);
                 }
                 try {
+                    if (networkScoreF != null) networkScoreF.systemReady();
+                } catch (Throwable e) {
+                    reportWtf("making Network Score Service ready", e);
+                }
+                try {
                     if (networkManagementF != null) networkManagementF.systemReady();
                 } catch (Throwable e) {
                     reportWtf("making Network Managment Service ready", e);
diff --git a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
index 8b9f718..8392672 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkPolicyManagerServiceTest.java
@@ -216,7 +216,7 @@
         expectLastCall().atLeastOnce();
 
         // expect to answer screen status during systemReady()
-        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
         expect(mNetworkManager.isBandwidthControlEnabled()).andReturn(true).atLeastOnce();
         expectCurrentTime();
 
@@ -331,7 +331,7 @@
         verifyAndReset();
 
         // now turn screen off and verify REJECT rule
-        expect(mPowerManager.isScreenOn()).andReturn(false).atLeastOnce();
+        expect(mPowerManager.isInteractive()).andReturn(false).atLeastOnce();
         expectSetUidNetworkRules(UID_A, true);
         expectSetUidForeground(UID_A, false);
         future = expectRulesChanged(UID_A, RULE_REJECT_METERED);
@@ -341,7 +341,7 @@
         verifyAndReset();
 
         // and turn screen back on, verify ALLOW rule restored
-        expect(mPowerManager.isScreenOn()).andReturn(true).atLeastOnce();
+        expect(mPowerManager.isInteractive()).andReturn(true).atLeastOnce();
         expectSetUidNetworkRules(UID_A, false);
         expectSetUidForeground(UID_A, true);
         future = expectRulesChanged(UID_A, RULE_ALLOW_ALL);
diff --git a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
index f73d425..0946c5a 100644
--- a/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDebuggingManager.java
@@ -20,6 +20,8 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.net.LocalSocket;
 import android.net.LocalSocketAddress;
@@ -210,7 +212,7 @@
                 case MESSAGE_ADB_CONFIRM: {
                     String key = (String)msg.obj;
                     mFingerprints = getFingerprints(key);
-                    showConfirmationDialog(key, mFingerprints);
+                    startConfirmation(key, mFingerprints);
                     break;
                 }
 
@@ -245,22 +247,60 @@
         return sb.toString();
     }
 
-    private void showConfirmationDialog(String key, String fingerprints) {
-        Intent intent = new Intent();
+    private void startConfirmation(String key, String fingerprints) {
+        String nameString = Resources.getSystem().getString(
+                com.android.internal.R.string.config_customAdbPublicKeyConfirmationComponent);
+        ComponentName componentName = ComponentName.unflattenFromString(nameString);
+        if (startConfirmationActivity(componentName, key, fingerprints)
+                || startConfirmationService(componentName, key, fingerprints)) {
+            return;
+        }
+        Slog.e(TAG, "unable to start customAdbPublicKeyConfirmationComponent "
+                + nameString + " as an Activity or a Service");
+    }
 
-        ComponentName componentName = ComponentName.unflattenFromString(
-                Resources.getSystem().getString(
-                        com.android.internal.R.string.config_customAdbPublicKeyActivity));
-        intent.setClassName(componentName.getPackageName(),
-                componentName.getClassName());
+    /**
+     * @returns true if the componentName led to an Activity that was started.
+     */
+    private boolean startConfirmationActivity(ComponentName componentName, String key,
+            String fingerprints) {
+        PackageManager packageManager = mContext.getPackageManager();
+        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        if (packageManager.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY) != null) {
+            try {
+                mContext.startActivity(intent);
+                return true;
+            } catch (ActivityNotFoundException e) {
+                Slog.e(TAG, "unable to start adb whitelist activity: " + componentName, e);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * @returns true if the componentName led to a Service that was started.
+     */
+    private boolean startConfirmationService(ComponentName componentName, String key,
+            String fingerprints) {
+        Intent intent = createConfirmationIntent(componentName, key, fingerprints);
+        try {
+            if (mContext.startService(intent) != null) {
+                return true;
+            }
+        } catch (SecurityException e) {
+            Slog.e(TAG, "unable to start adb whitelist service: " + componentName, e);
+        }
+        return false;
+    }
+
+    private Intent createConfirmationIntent(ComponentName componentName, String key,
+            String fingerprints) {
+        Intent intent = new Intent();
+        intent.setClassName(componentName.getPackageName(), componentName.getClassName());
         intent.putExtra("key", key);
         intent.putExtra("fingerprints", fingerprints);
-        try {
-            mContext.startActivity(intent);
-        } catch (ActivityNotFoundException e) {
-            Slog.e(TAG, "unable to start UsbDebuggingActivity");
-        }
+        return intent;
     }
 
     private File getUserKeyFile() {
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index 502ee18..f5ac178 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -590,14 +590,19 @@
                 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
                 intent.putExtra("state", (enabled ? 1 : 0));
                 if (enabled) {
+                    Scanner scanner = null;
                     try {
-                        Scanner scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
+                        scanner = new Scanner(new File(AUDIO_SOURCE_PCM_PATH));
                         int card = scanner.nextInt();
                         int device = scanner.nextInt();
                         intent.putExtra("card", card);
                         intent.putExtra("device", device);
                     } catch (FileNotFoundException e) {
                         Slog.e(TAG, "could not open audio source PCM file", e);
+                    } finally {
+                        if (scanner != null) {
+                            scanner.close();
+                        }
                     }
                 }
                 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
diff --git a/services/usb/java/com/android/server/usb/UsbHostManager.java b/services/usb/java/com/android/server/usb/UsbHostManager.java
index 7ae5460..8b54264 100644
--- a/services/usb/java/com/android/server/usb/UsbHostManager.java
+++ b/services/usb/java/com/android/server/usb/UsbHostManager.java
@@ -17,6 +17,7 @@
 package com.android.server.usb;
 
 import android.content.Context;
+import android.content.Intent;
 import android.hardware.usb.UsbConfiguration;
 import android.hardware.usb.UsbConstants;
 import android.hardware.usb.UsbDevice;
@@ -25,11 +26,16 @@
 import android.os.Bundle;
 import android.os.ParcelFileDescriptor;
 import android.os.Parcelable;
+import android.os.UserHandle;
 import android.util.Slog;
 
+import com.android.alsascan.AlsaCardsParser;
+import com.android.alsascan.AlsaDevicesParser;
 import com.android.internal.annotations.GuardedBy;
 
+import java.io.File;
 import java.io.FileDescriptor;
+import java.io.FileNotFoundException;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -39,7 +45,7 @@
  */
 public class UsbHostManager {
     private static final String TAG = UsbHostManager.class.getSimpleName();
-    private static final boolean LOG = false;
+    private static final boolean DEBUG_AUDIO = false;
 
     // contains all connected USB devices
     private final HashMap<String, UsbDevice> mDevices = new HashMap<String, UsbDevice>();
@@ -57,6 +63,15 @@
     private ArrayList<UsbInterface> mNewInterfaces;
     private ArrayList<UsbEndpoint> mNewEndpoints;
 
+    // Attributes of any connected USB audio device.
+    //TODO(pmclean) When we extend to multiple, USB Audio devices, we will need to get
+    // more clever about this.
+    private int mConnectedUsbCard = -1;
+    private int mConnectedUsbDeviceNum = -1;
+    private boolean mConnectedHasPlayback = false;
+    private boolean mConnectedHasCapture = false;
+    private boolean mConnectedHasMIDI = false;
+
     @GuardedBy("mLock")
     private UsbSettingsManager mCurrentSettings;
 
@@ -102,6 +117,48 @@
         return false;
     }
 
+    // Broadcasts the arrival/departure of a USB audio interface
+    // card - the ALSA card number of the physical interface
+    // device - the ALSA device number of the physical interface
+    // enabled - if true, we're connecting a device (it's arrived), else disconnecting
+    private void sendDeviceNotification(int card, int device, boolean enabled,
+            boolean hasPlayback, boolean hasCapture, boolean hasMIDI) {
+        // send a sticky broadcast containing current USB state
+        Intent intent = new Intent(Intent.ACTION_USB_AUDIO_DEVICE_PLUG);
+        intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
+        intent.putExtra("state", enabled ? 1 : 0);
+        intent.putExtra("card", card);
+        intent.putExtra("device", device);
+        intent.putExtra("hasPlayback", hasPlayback);
+        intent.putExtra("hasCapture", hasCapture);
+        intent.putExtra("hasMIDI", hasMIDI);
+        mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
+    }
+
+    private boolean waitForAlsaFile(int card, int device, boolean capture) {
+        // These values were empirically determined.
+        final int kNumRetries = 5;
+        final int kSleepTime = 500; // ms
+        String alsaDevPath = "/dev/snd/pcmC" + card + "D" + device + (capture ? "c" : "p");
+        File alsaDevFile = new File(alsaDevPath);
+        boolean exists = false;
+        for (int retry = 0; !exists && retry < kNumRetries; retry++) {
+            exists = alsaDevFile.exists();
+            if (!exists) {
+                try {
+                    Thread.sleep(kSleepTime);
+                } catch (IllegalThreadStateException ex) {
+                    Slog.d(TAG, "usb: IllegalThreadStateException while waiting for ALSA file.");
+                } catch (java.lang.InterruptedException ex) {
+                    Slog.d(TAG, "usb: InterruptedException while waiting for ALSA file.");
+                }
+            }
+        }
+
+        return exists;
+    }
+
     /* Called from JNI in monitorUsbHostBus() to report new USB devices
        Returns true if successful, in which case the JNI code will continue adding configurations,
        interfaces and endpoints, and finally call endUsbDeviceAdded after all descriptors
@@ -111,6 +168,25 @@
             int deviceClass, int deviceSubclass, int deviceProtocol,
             String manufacturerName, String productName, String serialNumber) {
 
+        if (DEBUG_AUDIO) {
+            Slog.d(TAG, "usb:UsbHostManager.beginUsbDeviceAdded(" + deviceName + ")");
+            // Audio Class Codes:
+            // Audio: 0x01
+            // Audio Subclass Codes:
+            // undefined: 0x00
+            // audio control: 0x01
+            // audio streaming: 0x02
+            // midi streaming: 0x03
+
+            // some useful debugging info
+            Slog.d(TAG, "usb: nm:" + deviceName + " vnd:" + vendorID + " prd:" + productID + " cls:"
+                    + deviceClass + " sub:" + deviceSubclass + " proto:" + deviceProtocol);
+        }
+
+        // OK this is non-obvious, but true. One can't tell if the device being attached is even
+        // potentially an audio device without parsing the interface descriptors, so punt on any
+        // such test until endUsbDeviceAdded() when we have that info.
+
         if (isBlackListed(deviceName) ||
                 isBlackListed(deviceClass, deviceSubclass, deviceProtocol)) {
             return false;
@@ -135,6 +211,7 @@
             mNewInterfaces = new ArrayList<UsbInterface>();
             mNewEndpoints = new ArrayList<UsbEndpoint>();
         }
+
         return true;
     }
 
@@ -176,6 +253,9 @@
 
     /* Called from JNI in monitorUsbHostBus() to finish adding a new device */
     private void endUsbDeviceAdded() {
+        if (DEBUG_AUDIO) {
+            Slog.d(TAG, "usb:UsbHostManager.endUsbDeviceAdded()");
+        }
         if (mNewInterface != null) {
             mNewInterface.setEndpoints(
                     mNewEndpoints.toArray(new UsbEndpoint[mNewEndpoints.size()]));
@@ -185,6 +265,17 @@
                     mNewInterfaces.toArray(new UsbInterface[mNewInterfaces.size()]));
         }
 
+        // Is there an audio interface in there?
+        final int kUsbClassId_Audio = 0x01;
+        boolean isAudioDevice = false;
+        for (int ntrfaceIndex = 0; !isAudioDevice && ntrfaceIndex < mNewInterfaces.size();
+                ntrfaceIndex++) {
+            UsbInterface ntrface = mNewInterfaces.get(ntrfaceIndex);
+            if (ntrface.getInterfaceClass() == kUsbClassId_Audio) {
+                isAudioDevice = true;
+            }
+        }
+
         synchronized (mLock) {
             if (mNewDevice != null) {
                 mNewDevice.setConfigurations(
@@ -200,10 +291,70 @@
             mNewInterfaces = null;
             mNewEndpoints = null;
         }
+
+        if (!isAudioDevice) {
+            return; // bail
+        }
+
+        //TODO(pmclean) The "Parser" objects inspect files in "/proc/asound" which we presume is
+        // present, unlike the waitForAlsaFile() which waits on a file in /dev/snd. It is not
+        // clear why this works, or that it can be relied on going forward.  Needs further
+        // research.
+        AlsaCardsParser cardsParser = new AlsaCardsParser();
+        cardsParser.scan();
+        // cardsParser.Log();
+
+        // But we need to parse the device to determine its capabilities.
+        AlsaDevicesParser devicesParser = new AlsaDevicesParser();
+        devicesParser.scan();
+        // devicesParser.Log();
+
+        // The protocol for now will be to select the last-connected (highest-numbered)
+        // Alsa Card.
+        mConnectedUsbCard = cardsParser.getNumCardRecords() - 1;
+        mConnectedUsbDeviceNum = 0;
+
+        if (!waitForAlsaFile(mConnectedUsbCard, mConnectedUsbDeviceNum, false)) {
+            return;
+        }
+
+        mConnectedHasPlayback = devicesParser.hasPlaybackDevices(mConnectedUsbCard);
+        mConnectedHasCapture = devicesParser.hasCaptureDevices(mConnectedUsbCard);
+        mConnectedHasMIDI = devicesParser.hasMIDIDevices(mConnectedUsbCard);
+
+        if (DEBUG_AUDIO) {
+            Slog.d(TAG,
+                    "usb: hasPlayback:" + mConnectedHasPlayback + " hasCapture:" + mConnectedHasCapture);
+        }
+
+        sendDeviceNotification(mConnectedUsbCard,
+                mConnectedUsbDeviceNum,
+                true,
+                mConnectedHasPlayback,
+                mConnectedHasCapture,
+                mConnectedHasMIDI);
     }
 
     /* Called from JNI in monitorUsbHostBus to report USB device removal */
     private void usbDeviceRemoved(String deviceName) {
+        if (DEBUG_AUDIO) {
+          Slog.d(TAG, "usb:UsbHostManager.usbDeviceRemoved() nm:" + deviceName);
+        }
+
+        if (mConnectedUsbCard != -1 && mConnectedUsbDeviceNum != -1) {
+            sendDeviceNotification(mConnectedUsbCard,
+                    mConnectedUsbDeviceNum,
+                    false,
+                    mConnectedHasPlayback,
+                    mConnectedHasCapture,
+                    mConnectedHasMIDI);
+            mConnectedUsbCard = -1;
+            mConnectedUsbDeviceNum = -1;
+            mConnectedHasPlayback = false;
+            mConnectedHasCapture = false;
+            mConnectedHasMIDI = false;
+        }
+
         synchronized (mLock) {
             UsbDevice device = mDevices.remove(deviceName);
             if (device != null) {
diff --git a/services/voiceinteraction/Android.mk b/services/voiceinteraction/Android.mk
new file mode 100644
index 0000000..c9e5dd0
--- /dev/null
+++ b/services/voiceinteraction/Android.mk
@@ -0,0 +1,12 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := services.voiceinteraction
+
+LOCAL_SRC_FILES += \
+      $(call all-java-files-under,java)
+
+LOCAL_JAVA_LIBRARIES := services.core
+
+include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
new file mode 100644
index 0000000..045c0f6
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.voiceinteraction;
+
+import android.Manifest;
+import android.app.ActivityManager;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.database.ContentObserver;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.voice.IVoiceInteractionService;
+import android.service.voice.IVoiceInteractionSession;
+import android.util.Slog;
+import com.android.internal.app.IVoiceInteractionManagerService;
+import com.android.internal.app.IVoiceInteractor;
+import com.android.internal.content.PackageMonitor;
+import com.android.internal.os.BackgroundThread;
+import com.android.server.SystemService;
+import com.android.server.UiThread;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+
+/**
+ * SystemService that publishes an IVoiceInteractionManagerService.
+ */
+public class VoiceInteractionManagerService extends SystemService {
+
+    static final String TAG = "VoiceInteractionManagerService";
+
+    final Context mContext;
+    final ContentResolver mResolver;
+
+    public VoiceInteractionManagerService(Context context) {
+        super(context);
+        mContext = context;
+        mResolver = context.getContentResolver();
+    }
+
+    @Override
+    public void onStart() {
+        publishBinderService(Context.VOICE_INTERACTION_MANAGER_SERVICE, mServiceStub);
+    }
+
+    @Override
+    public void onBootPhase(int phase) {
+        if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+            mServiceStub.systemRunning(isSafeMode());
+        }
+    }
+
+    @Override
+    public void onSwitchUser(int userHandle) {
+        mServiceStub.switchUser(userHandle);
+    }
+
+    // implementation entry point and binder service
+    private final VoiceInteractionManagerServiceStub mServiceStub
+            = new VoiceInteractionManagerServiceStub();
+
+    class VoiceInteractionManagerServiceStub extends IVoiceInteractionManagerService.Stub {
+
+        VoiceInteractionManagerServiceImpl mImpl;
+
+        private boolean mSafeMode;
+        private int mCurUser;
+
+        public void systemRunning(boolean safeMode) {
+            mSafeMode = safeMode;
+
+            mPackageMonitor.register(mContext, BackgroundThread.getHandler().getLooper(),
+                    UserHandle.ALL, true);
+            new SettingsObserver(UiThread.getHandler());
+
+            synchronized (this) {
+                mCurUser = ActivityManager.getCurrentUser();
+                switchImplementationIfNeededLocked();
+            }
+        }
+
+        public void switchUser(int userHandle) {
+            synchronized (this) {
+                mCurUser = userHandle;
+                switchImplementationIfNeededLocked();
+            }
+        }
+
+        void switchImplementationIfNeededLocked() {
+            if (!mSafeMode) {
+                String curService = Settings.Secure.getStringForUser(
+                        mResolver, Settings.Secure.VOICE_INTERACTION_SERVICE, mCurUser);
+                ComponentName serviceComponent = null;
+                if (curService != null && !curService.isEmpty()) {
+                    try {
+                        serviceComponent = ComponentName.unflattenFromString(curService);
+                    } catch (RuntimeException e) {
+                        Slog.wtf(TAG, "Bad voice interaction service name " + curService, e);
+                        serviceComponent = null;
+                    }
+                }
+                if (mImpl == null || mImpl.mUser != mCurUser
+                        || !mImpl.mComponent.equals(serviceComponent)) {
+                    if (mImpl != null) {
+                        mImpl.shutdownLocked();
+                    }
+                    if (serviceComponent != null) {
+                        mImpl = new VoiceInteractionManagerServiceImpl(mContext,
+                                UiThread.getHandler(), this, mCurUser, serviceComponent);
+                        mImpl.startLocked();
+                    } else {
+                        mImpl = null;
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void startVoiceActivity(Intent intent, String resolvedType,
+                IVoiceInteractionService service, Bundle args) {
+            synchronized (this) {
+                if (mImpl == null || service.asBinder() != mImpl.mService.asBinder()) {
+                    throw new SecurityException(
+                            "Caller is not the current voice interaction service");
+                }
+                final int callingPid = Binder.getCallingPid();
+                final int callingUid = Binder.getCallingUid();
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    mImpl.startVoiceActivityLocked(callingPid, callingUid,
+                            intent, resolvedType, args);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
+        @Override
+        public int deliverNewSession(IBinder token, IVoiceInteractionSession session,
+                IVoiceInteractor interactor) {
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "deliverNewSession without running voice interaction service");
+                    return ActivityManager.START_CANCELED;
+                }
+                final int callingPid = Binder.getCallingPid();
+                final int callingUid = Binder.getCallingUid();
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    return mImpl.deliverNewSessionLocked(callingPid, callingUid, token, session,
+                            interactor);
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+
+        }
+
+        @Override
+        public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump PowerManager from from pid="
+                        + Binder.getCallingPid()
+                        + ", uid=" + Binder.getCallingUid());
+                return;
+            }
+            synchronized (this) {
+                pw.println("VOICE INTERACTION MANAGER (dumpsys voiceinteraction)\n");
+                if (mImpl == null) {
+                    pw.println("  (No active implementation)");
+                    return;
+                }
+                mImpl.dumpLocked(fd, pw, args);
+            }
+        }
+
+        class SettingsObserver extends ContentObserver {
+            SettingsObserver(Handler handler) {
+                super(handler);
+                ContentResolver resolver = mContext.getContentResolver();
+                resolver.registerContentObserver(Settings.Secure.getUriFor(
+                        Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
+            }
+
+            @Override public void onChange(boolean selfChange) {
+                synchronized (VoiceInteractionManagerServiceStub.this) {
+                    switchImplementationIfNeededLocked();
+                }
+            }
+        }
+
+        PackageMonitor mPackageMonitor = new PackageMonitor() {
+            @Override
+            public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
+                return super.onHandleForceStop(intent, packages, uid, doit);
+            }
+
+            @Override
+            public void onHandleUserStop(Intent intent, int userHandle) {
+                super.onHandleUserStop(intent, userHandle);
+            }
+
+            @Override
+            public void onPackageDisappeared(String packageName, int reason) {
+                super.onPackageDisappeared(packageName, reason);
+            }
+
+            @Override
+            public void onPackageAppeared(String packageName, int reason) {
+                super.onPackageAppeared(packageName, reason);
+            }
+
+            @Override
+            public void onPackageModified(String packageName) {
+                super.onPackageModified(packageName);
+            }
+
+            @Override
+            public void onSomePackagesChanged() {
+                super.onSomePackagesChanged();
+            }
+        };
+    }
+}
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
new file mode 100644
index 0000000..6bbd1c1
--- /dev/null
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerServiceImpl.java
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.voiceinteraction;
+
+import android.app.ActivityManager;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
+import android.content.pm.ServiceInfo;
+import android.os.Binder;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.service.voice.IVoiceInteractionService;
+import android.service.voice.IVoiceInteractionSession;
+import android.service.voice.IVoiceInteractionSessionService;
+import android.service.voice.VoiceInteractionService;
+import android.service.voice.VoiceInteractionServiceInfo;
+import android.util.Slog;
+import com.android.internal.app.IVoiceInteractor;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+class VoiceInteractionManagerServiceImpl {
+    final static String TAG = "VoiceInteractionServiceManager";
+
+    final boolean mValid;
+
+    final Context mContext;
+    final Handler mHandler;
+    final Object mLock;
+    final int mUser;
+    final ComponentName mComponent;
+    final IActivityManager mAm;
+    final VoiceInteractionServiceInfo mInfo;
+    final ComponentName mSessionComponentName;
+    boolean mBound = false;
+    IVoiceInteractionService mService;
+
+    SessionConnection mActiveSession;
+
+    final ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized (mLock) {
+                mService = IVoiceInteractionService.Stub.asInterface(service);
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+        }
+    };
+
+    final class SessionConnection implements ServiceConnection {
+        final IBinder mToken = new Binder();
+        final Intent mIntent;
+        final String mResolvedType;
+        final Bundle mArgs;
+        boolean mBound;
+        IVoiceInteractionSessionService mService;
+        IVoiceInteractionSession mSession;
+        IVoiceInteractor mInteractor;
+
+        SessionConnection(Intent intent, String resolvedType, Bundle args) {
+            mIntent = intent;
+            mResolvedType = resolvedType;
+            mArgs = args;
+            Intent serviceIntent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
+            serviceIntent.setComponent(mSessionComponentName);
+            mBound = mContext.bindServiceAsUser(serviceIntent, this,
+                    Context.BIND_AUTO_CREATE, new UserHandle(mUser));
+            if (!mBound) {
+                Slog.w(TAG, "Failed binding to voice interaction session service " + mComponent);
+            }
+        }
+
+        @Override
+        public void onServiceConnected(ComponentName name, IBinder service) {
+            synchronized (mLock) {
+                mService = IVoiceInteractionSessionService.Stub.asInterface(service);
+                if (mActiveSession == this) {
+                    try {
+                        mService.newSession(mToken, mArgs);
+                    } catch (RemoteException e) {
+                        Slog.w(TAG, "Failed making new session", e);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName name) {
+            mService = null;
+        }
+
+        public void cancel() {
+            if (mBound) {
+                mContext.unbindService(this);
+                mBound = false;
+                mService = null;
+                mSession = null;
+                mInteractor = null;
+            }
+        }
+
+        public void dump(String prefix, PrintWriter pw) {
+            pw.print(prefix); pw.print("mToken="); pw.println(mToken);
+            pw.print(prefix); pw.print("mIntent="); pw.println(mIntent);
+                    pw.print(" mResolvedType="); pw.println(mResolvedType);
+            pw.print(prefix); pw.print("mArgs="); pw.println(mArgs);
+            pw.print(prefix); pw.print("mBound="); pw.println(mBound);
+            if (mBound) {
+                pw.print(prefix); pw.print("mService="); pw.println(mService);
+                pw.print(prefix); pw.print("mSession="); pw.println(mSession);
+                pw.print(prefix); pw.print("mInteractor="); pw.println(mInteractor);
+            }
+        }
+    };
+
+    VoiceInteractionManagerServiceImpl(Context context, Handler handler, Object lock,
+            int userHandle, ComponentName service) {
+        mContext = context;
+        mHandler = handler;
+        mLock = lock;
+        mUser = userHandle;
+        mComponent = service;
+        mAm = ActivityManagerNative.getDefault();
+        VoiceInteractionServiceInfo info;
+        try {
+            info = new VoiceInteractionServiceInfo(context.getPackageManager(), service);
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.w(TAG, "Voice interaction service not found: " + service);
+            mInfo = null;
+            mSessionComponentName = null;
+            mValid = false;
+            return;
+        }
+        mInfo = info;
+        if (mInfo.getParseError() != null) {
+            Slog.w(TAG, "Bad voice interaction service: " + mInfo.getParseError());
+            mSessionComponentName = null;
+            mValid = false;
+            return;
+        }
+        mValid = true;
+        mSessionComponentName = new ComponentName(service.getPackageName(),
+                mInfo.getSessionService());
+    }
+
+    public void startVoiceActivityLocked(int callingPid, int callingUid, Intent intent,
+            String resolvedType, Bundle args) {
+        if (mActiveSession != null) {
+            mActiveSession.cancel();
+            mActiveSession = null;
+        }
+        mActiveSession = new SessionConnection(intent, resolvedType, args);
+        intent.addCategory(Intent.CATEGORY_VOICE);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
+    }
+
+    public int deliverNewSessionLocked(int callingPid, int callingUid, IBinder token,
+            IVoiceInteractionSession session, IVoiceInteractor interactor) {
+        try {
+            if (mActiveSession == null || token != mActiveSession.mToken) {
+                Slog.w(TAG, "deliverNewSession does not match active session");
+                return ActivityManager.START_CANCELED;
+            }
+            mActiveSession.mSession = session;
+            mActiveSession.mInteractor = interactor;
+            return mAm.startVoiceActivity(mComponent.getPackageName(), callingPid, callingUid,
+                    mActiveSession.mIntent, mActiveSession.mResolvedType,
+                    mActiveSession.mSession, mActiveSession.mInteractor,
+                    0, null, null, null, mUser);
+        } catch (RemoteException e) {
+            throw new IllegalStateException("Unexpected remote error", e);
+        }
+    }
+
+    public void dumpLocked(FileDescriptor fd, PrintWriter pw, String[] args) {
+        if (!mValid) {
+            pw.print("  NOT VALID: ");
+            if (mInfo == null) {
+                pw.println("no info");
+            } else {
+                pw.println(mInfo.getParseError());
+            }
+            return;
+        }
+        pw.print("  mComponent="); pw.println(mComponent.flattenToShortString());
+        pw.print("  Session service="); pw.println(mInfo.getSessionService());
+        pw.print("  Settings activity="); pw.println(mInfo.getSettingsActivity());
+        pw.print("  mBound="); pw.print(mBound);  pw.print(" mService="); pw.println(mService);
+        if (mActiveSession != null) {
+            pw.println("  Active session:");
+            mActiveSession.dump("    ", pw);
+        }
+    }
+
+    void startLocked() {
+        Intent intent = new Intent(VoiceInteractionService.SERVICE_INTERFACE);
+        intent.setComponent(mComponent);
+        mBound = mContext.bindServiceAsUser(intent, mConnection,
+                Context.BIND_AUTO_CREATE, new UserHandle(mUser));
+        if (!mBound) {
+            Slog.w(TAG, "Failed binding to voice interaction service " + mComponent);
+        }
+    }
+
+    void shutdownLocked() {
+        if (mBound) {
+            mContext.unbindService(mConnection);
+            mBound = false;
+        }
+    }
+}
diff --git a/telephony/java/android/telephony/CellSignalStrengthCdma.java b/telephony/java/android/telephony/CellSignalStrengthCdma.java
index 46d09f6..be13acc 100644
--- a/telephony/java/android/telephony/CellSignalStrengthCdma.java
+++ b/telephony/java/android/telephony/CellSignalStrengthCdma.java
@@ -137,7 +137,6 @@
 
     /**
      * Get the signal level as an asu value between 0..97, 99 is unknown
-     * Asu is calculated based on 3GPP RSRP. Refer to 3GPP 27.007 (Ver 10.3.0) Sec 8.69
      */
     @Override
     public int getAsuLevel() {
@@ -342,7 +341,7 @@
 
     /**
      * Construct a SignalStrength object from the given parcel
-     * where the TYPE_LTE token is already been processed.
+     * where the TYPE_CDMA token is already been processed.
      */
     private CellSignalStrengthCdma(Parcel in) {
         // CdmaDbm, CdmaEcio, EvdoDbm and EvdoEcio are written into
diff --git a/media/java/android/media/session/MediaSessionToken.aidl b/telephony/java/android/telephony/DataConnectionRealTimeInfo.aidl
similarity index 81%
copy from media/java/android/media/session/MediaSessionToken.aidl
copy to telephony/java/android/telephony/DataConnectionRealTimeInfo.aidl
index 5812682..70fbb11 100644
--- a/media/java/android/media/session/MediaSessionToken.aidl
+++ b/telephony/java/android/telephony/DataConnectionRealTimeInfo.aidl
@@ -1,4 +1,6 @@
-/* Copyright 2014, The Android Open Source Project
+/*
+**
+** Copyright 2007, 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.
@@ -13,6 +15,6 @@
 ** limitations under the License.
 */
 
-package android.media.session;
+package android.telephony;
 
-parcelable MediaSessionToken;
+parcelable DataConnectionRealTimeInfo;
diff --git a/telephony/java/android/telephony/DataConnectionRealTimeInfo.java b/telephony/java/android/telephony/DataConnectionRealTimeInfo.java
new file mode 100644
index 0000000..96069213
--- /dev/null
+++ b/telephony/java/android/telephony/DataConnectionRealTimeInfo.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.telephony;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Data connection real time information
+ *
+ * TODO: How to handle multiple subscriptions?
+ * @hide
+ */
+public class DataConnectionRealTimeInfo implements Parcelable {
+    private long mTime;             // Time the info was collected since boot in nanos;
+
+    public static int DC_POWER_STATE_LOW       = 1;
+    public static int DC_POWER_STATE_MEDIUM    = 2;
+    public static int DC_POWER_STATE_HIGH      = 3;
+    public static int DC_POWER_STATE_UNKNOWN   = Integer.MAX_VALUE;
+
+    private int mDcPowerState;      // DC_POWER_STATE_[LOW | MEDIUM | HIGH | UNKNOWN]
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public DataConnectionRealTimeInfo(long time, int dcPowerState) {
+        mTime = time;
+        mDcPowerState = dcPowerState;
+    }
+
+    /**
+     * Constructor
+     *
+     * @hide
+     */
+    public DataConnectionRealTimeInfo() {
+        mTime = Long.MAX_VALUE;
+        mDcPowerState = DC_POWER_STATE_UNKNOWN;
+    }
+
+    /**
+     * Construct a PreciseCallState object from the given parcel.
+     */
+    private DataConnectionRealTimeInfo(Parcel in) {
+        mTime = in.readLong();
+        mDcPowerState = in.readInt();
+    }
+
+    /**
+     * @return time the information was collected or Long.MAX_VALUE if unknown
+     */
+    public long getTime() {
+        return mTime;
+    }
+
+    /**
+     * @return DC_POWER_STATE_[LOW | MEDIUM | HIGH | UNKNOWN]
+     */
+    public int getDcPowerState() {
+        return mDcPowerState;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeLong(mTime);
+        out.writeInt(mDcPowerState);
+    }
+
+    public static final Parcelable.Creator<DataConnectionRealTimeInfo> CREATOR
+            = new Parcelable.Creator<DataConnectionRealTimeInfo>() {
+
+        @Override
+        public DataConnectionRealTimeInfo createFromParcel(Parcel in) {
+            return new DataConnectionRealTimeInfo(in);
+        }
+
+        @Override
+        public DataConnectionRealTimeInfo[] newArray(int size) {
+            return new DataConnectionRealTimeInfo[size];
+        }
+    };
+
+    @Override
+    public int hashCode() {
+        final long prime = 17;
+        long result = 1;
+        result = (prime * result) + mTime;
+        result += (prime * result) + mDcPowerState;
+        return (int)result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        DataConnectionRealTimeInfo other = (DataConnectionRealTimeInfo) obj;
+        return (mTime == other.mTime)
+                && (mDcPowerState == other.mDcPowerState);
+    }
+
+    @Override
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        sb.append("mTime=").append(mTime);
+        sb.append(" mDcPowerState=").append(mDcPowerState);
+
+        return sb.toString();
+    }
+}
diff --git a/telephony/java/android/telephony/PhoneStateListener.java b/telephony/java/android/telephony/PhoneStateListener.java
index bb3f132..59ec6f5 100644
--- a/telephony/java/android/telephony/PhoneStateListener.java
+++ b/telephony/java/android/telephony/PhoneStateListener.java
@@ -18,6 +18,7 @@
 
 import android.os.Bundle;
 import android.os.Handler;
+import android.os.Looper;
 import android.os.Message;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
@@ -188,7 +189,78 @@
      */
     public static final int LISTEN_PRECISE_DATA_CONNECTION_STATE            = 0x00001000;
 
+    /**
+     * Listen for real time info for all data connections (cellular)).
+     * {@more}
+     * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+     * READ_PRECISE_PHONE_STATE}
+     *
+     * @see #onDataConnectionRealTimeInfoChanged(DataConnectionRealTimeInfo)
+     * @hide
+     */
+    public static final int LISTEN_DATA_CONNECTION_REAL_TIME_INFO           = 0x00002000;
+
+    private final Handler mHandler;
+
     public PhoneStateListener() {
+        this(Looper.myLooper());
+    }
+
+    /** @hide */
+    public PhoneStateListener(Looper looper) {
+        mHandler = new Handler(looper) {
+            public void handleMessage(Message msg) {
+                //Rlog.d("TelephonyRegistry", "what=0x" + Integer.toHexString(msg.what)
+                // + " msg=" + msg);
+                switch (msg.what) {
+                    case LISTEN_SERVICE_STATE:
+                        PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
+                        break;
+                    case LISTEN_SIGNAL_STRENGTH:
+                        PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
+                        break;
+                    case LISTEN_MESSAGE_WAITING_INDICATOR:
+                        PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
+                        break;
+                    case LISTEN_CALL_FORWARDING_INDICATOR:
+                        PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
+                        break;
+                    case LISTEN_CELL_LOCATION:
+                        PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
+                        break;
+                    case LISTEN_CALL_STATE:
+                        PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
+                        break;
+                    case LISTEN_DATA_CONNECTION_STATE:
+                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
+                        PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
+                        break;
+                    case LISTEN_DATA_ACTIVITY:
+                        PhoneStateListener.this.onDataActivity(msg.arg1);
+                        break;
+                    case LISTEN_SIGNAL_STRENGTHS:
+                        PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
+                        break;
+                    case LISTEN_OTASP_CHANGED:
+                        PhoneStateListener.this.onOtaspChanged(msg.arg1);
+                        break;
+                    case LISTEN_CELL_INFO:
+                        PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
+                        break;
+                    case LISTEN_PRECISE_CALL_STATE:
+                        PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
+                        break;
+                    case LISTEN_PRECISE_DATA_CONNECTION_STATE:
+                        PhoneStateListener.this.onPreciseDataConnectionStateChanged(
+                                (PreciseDataConnectionState)msg.obj);
+                        break;
+                    case LISTEN_DATA_CONNECTION_REAL_TIME_INFO:
+                        PhoneStateListener.this.onDataConnectionRealTimeInfoChanged(
+                                (DataConnectionRealTimeInfo)msg.obj);
+                        break;
+                }
+            }
+        };
     }
 
     /**
@@ -335,6 +407,16 @@
     }
 
     /**
+     * Callback invoked when data connection state changes with precise information.
+     *
+     * @hide
+     */
+    public void onDataConnectionRealTimeInfoChanged(
+            DataConnectionRealTimeInfo dcRtInfo) {
+        // default implementation empty
+    }
+
+    /**
      * The callback methods need to be called on the handler thread where
      * this object was created.  If the binder did that for us it'd be nice.
      */
@@ -396,52 +478,11 @@
             Message.obtain(mHandler, LISTEN_PRECISE_DATA_CONNECTION_STATE, 0, 0,
                     dataConnectionState).sendToTarget();
         }
-    };
 
-    Handler mHandler = new Handler() {
-        public void handleMessage(Message msg) {
-            //Rlog.d("TelephonyRegistry", "what=0x" + Integer.toHexString(msg.what) + " msg=" + msg);
-            switch (msg.what) {
-                case LISTEN_SERVICE_STATE:
-                    PhoneStateListener.this.onServiceStateChanged((ServiceState)msg.obj);
-                    break;
-                case LISTEN_SIGNAL_STRENGTH:
-                    PhoneStateListener.this.onSignalStrengthChanged(msg.arg1);
-                    break;
-                case LISTEN_MESSAGE_WAITING_INDICATOR:
-                    PhoneStateListener.this.onMessageWaitingIndicatorChanged(msg.arg1 != 0);
-                    break;
-                case LISTEN_CALL_FORWARDING_INDICATOR:
-                    PhoneStateListener.this.onCallForwardingIndicatorChanged(msg.arg1 != 0);
-                    break;
-                case LISTEN_CELL_LOCATION:
-                    PhoneStateListener.this.onCellLocationChanged((CellLocation)msg.obj);
-                    break;
-                case LISTEN_CALL_STATE:
-                    PhoneStateListener.this.onCallStateChanged(msg.arg1, (String)msg.obj);
-                    break;
-                case LISTEN_DATA_CONNECTION_STATE:
-                    PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1, msg.arg2);
-                    PhoneStateListener.this.onDataConnectionStateChanged(msg.arg1);
-                    break;
-                case LISTEN_DATA_ACTIVITY:
-                    PhoneStateListener.this.onDataActivity(msg.arg1);
-                    break;
-                case LISTEN_SIGNAL_STRENGTHS:
-                    PhoneStateListener.this.onSignalStrengthsChanged((SignalStrength)msg.obj);
-                    break;
-                case LISTEN_OTASP_CHANGED:
-                    PhoneStateListener.this.onOtaspChanged(msg.arg1);
-                    break;
-                case LISTEN_CELL_INFO:
-                    PhoneStateListener.this.onCellInfoChanged((List<CellInfo>)msg.obj);
-                    break;
-                case LISTEN_PRECISE_CALL_STATE:
-                    PhoneStateListener.this.onPreciseCallStateChanged((PreciseCallState)msg.obj);
-                    break;
-                case LISTEN_PRECISE_DATA_CONNECTION_STATE:
-                    PhoneStateListener.this.onPreciseDataConnectionStateChanged((PreciseDataConnectionState)msg.obj);
-            }
+        public void onDataConnectionRealTimeInfoChanged(
+                DataConnectionRealTimeInfo dcRtInfo) {
+            Message.obtain(mHandler, LISTEN_DATA_CONNECTION_REAL_TIME_INFO, 0, 0,
+                    dcRtInfo).sendToTarget();
         }
     };
 }
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index d5c7caa..407a8d1 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -1094,6 +1094,10 @@
     public static final int SIM_STATE_NETWORK_LOCKED = 4;
     /** SIM card state: Ready */
     public static final int SIM_STATE_READY = 5;
+    /** SIM card state: SIM Card Error, Sim Card is present but faulty
+     *@hide
+     */
+    public static final int SIM_STATE_CARD_IO_ERROR = 6;
 
     /**
      * @return true if a ICC card is present
@@ -1120,6 +1124,7 @@
      * @see #SIM_STATE_PUK_REQUIRED
      * @see #SIM_STATE_NETWORK_LOCKED
      * @see #SIM_STATE_READY
+     * @see #SIM_STATE_CARD_IO_ERROR
      */
     public int getSimState() {
         String prop = SystemProperties.get(TelephonyProperties.PROPERTY_SIM_STATE);
@@ -1138,6 +1143,9 @@
         else if ("READY".equals(prop)) {
             return SIM_STATE_READY;
         }
+        else if ("CARD_IO_ERROR".equals(prop)) {
+            return SIM_STATE_CARD_IO_ERROR;
+        }
         else {
             return SIM_STATE_UNKNOWN;
         }
diff --git a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
index f228d4e..3f36645 100644
--- a/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
+++ b/telephony/java/com/android/internal/telephony/IPhoneStateListener.aidl
@@ -20,6 +20,7 @@
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
 import android.telephony.CellInfo;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.PreciseCallState;
 import android.telephony.PreciseDataConnectionState;
 
@@ -39,5 +40,6 @@
     void onCellInfoChanged(in List<CellInfo> cellInfo);
     void onPreciseCallStateChanged(in PreciseCallState callState);
     void onPreciseDataConnectionStateChanged(in PreciseDataConnectionState dataConnectionState);
+    void onDataConnectionRealTimeInfoChanged(in DataConnectionRealTimeInfo dcRtInfo);
 }
 
diff --git a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
index 546ce17..8ea9b0d 100644
--- a/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephonyRegistry.aidl
@@ -20,9 +20,10 @@
 import android.net.LinkProperties;
 import android.net.LinkCapabilities;
 import android.os.Bundle;
+import android.telephony.CellInfo;
+import android.telephony.DataConnectionRealTimeInfo;
 import android.telephony.ServiceState;
 import android.telephony.SignalStrength;
-import android.telephony.CellInfo;
 import com.android.internal.telephony.IPhoneStateListener;
 
 interface ITelephonyRegistry {
@@ -46,4 +47,5 @@
     void notifyDisconnectCause(int disconnectCause, int preciseDisconnectCause);
     void notifyPreciseDataConnectionFailed(String reason, String apnType, String apn,
             String failCause);
+    void notifyDataConnectionRealTimeInfo(in DataConnectionRealTimeInfo dcRtInfo);
 }
diff --git a/telephony/java/com/android/internal/telephony/IccCardConstants.java b/telephony/java/com/android/internal/telephony/IccCardConstants.java
index 236bb2f..8029713 100644
--- a/telephony/java/com/android/internal/telephony/IccCardConstants.java
+++ b/telephony/java/com/android/internal/telephony/IccCardConstants.java
@@ -28,6 +28,8 @@
     public static final String INTENT_VALUE_ICC_NOT_READY = "NOT_READY";
     /* ABSENT means ICC is missing */
     public static final String INTENT_VALUE_ICC_ABSENT = "ABSENT";
+    /* CARD_IO_ERROR means for three consecutive times there was SIM IO error */
+    static public final String INTENT_VALUE_ICC_CARD_IO_ERROR = "CARD_IO_ERROR";
     /* LOCKED means ICC is locked by pin or by network */
     public static final String INTENT_VALUE_ICC_LOCKED = "LOCKED";
     /* READY means ICC is ready to access */
@@ -63,7 +65,8 @@
         NETWORK_LOCKED,
         READY,
         NOT_READY,
-        PERM_DISABLED;
+        PERM_DISABLED,
+        CARD_IO_ERROR;
 
         public boolean isPinLocked() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED));
@@ -72,7 +75,7 @@
         public boolean iccCardExist() {
             return ((this == PIN_REQUIRED) || (this == PUK_REQUIRED)
                     || (this == NETWORK_LOCKED) || (this == READY)
-                    || (this == PERM_DISABLED));
+                    || (this == PERM_DISABLED) || (this == CARD_IO_ERROR));
         }
     }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index daef37a..992ef4b 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -78,6 +78,12 @@
     }
 
     @Override
+    public Intent getLeanbackLaunchIntentForPackage(String packageName) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+
     public int[] getPackageGids(String packageName) throws NameNotFoundException {
         throw new UnsupportedOperationException();
     }
diff --git a/tests/CoreTests/android/core/NsdServiceInfoTest.java b/tests/CoreTests/android/core/NsdServiceInfoTest.java
new file mode 100644
index 0000000..5bf0167
--- /dev/null
+++ b/tests/CoreTests/android/core/NsdServiceInfoTest.java
@@ -0,0 +1,163 @@
+package android.core;
+
+import android.test.AndroidTestCase;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.StrictMode;
+import android.net.nsd.NsdServiceInfo;
+import android.util.Log;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+
+public class NsdServiceInfoTest extends AndroidTestCase {
+
+    public final static InetAddress LOCALHOST;
+    static {
+        // Because test.
+        StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+        StrictMode.setThreadPolicy(policy);
+
+        InetAddress _host = null;
+        try {
+            _host = InetAddress.getLocalHost();
+        } catch (UnknownHostException e) { }
+        LOCALHOST = _host;
+    }
+
+    public void testLimits() throws Exception {
+        NsdServiceInfo info = new NsdServiceInfo();
+
+        // Non-ASCII keys.
+        boolean exceptionThrown = false;
+        try {
+            info.setAttribute("猫", "meow");
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // ASCII keys with '=' character.
+        exceptionThrown = false;
+        try {
+            info.setAttribute("kitten=", "meow");
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // Single key + value length too long.
+        exceptionThrown = false;
+        try {
+            String longValue = "loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "oooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo" +
+                    "ooooooooooooooooooooooooooooong";  // 248 characters.
+            info.setAttribute("longcat", longValue);  // Key + value == 255 characters.
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertEmptyServiceInfo(info);
+
+        // Total TXT record length too long.
+        exceptionThrown = false;
+        int recordsAdded = 0;
+        try {
+            for (int i = 100; i < 300; ++i) {
+                // 6 char key + 5 char value + 2 bytes overhead = 13 byte record length.
+                String key = String.format("key%d", i);
+                info.setAttribute(key, "12345");
+                recordsAdded++;
+            }
+        } catch (IllegalArgumentException e) {
+            exceptionThrown = true;
+        }
+        assertTrue(exceptionThrown);
+        assertTrue(100 == recordsAdded);
+        assertTrue(info.getTxtRecord().length == 1300);
+    }
+
+    public void testParcel() throws Exception {
+        NsdServiceInfo emptyInfo = new NsdServiceInfo();
+        checkParcelable(emptyInfo);
+
+        NsdServiceInfo fullInfo = new NsdServiceInfo();
+        fullInfo.setServiceName("kitten");
+        fullInfo.setServiceType("_kitten._tcp");
+        fullInfo.setPort(4242);
+        fullInfo.setHost(LOCALHOST);
+        checkParcelable(fullInfo);
+
+        NsdServiceInfo noHostInfo = new NsdServiceInfo();
+        noHostInfo.setServiceName("kitten");
+        noHostInfo.setServiceType("_kitten._tcp");
+        noHostInfo.setPort(4242);
+        checkParcelable(noHostInfo);
+
+        NsdServiceInfo attributedInfo = new NsdServiceInfo();
+        attributedInfo.setServiceName("kitten");
+        attributedInfo.setServiceType("_kitten._tcp");
+        attributedInfo.setPort(4242);
+        attributedInfo.setHost(LOCALHOST);
+        attributedInfo.setAttribute("color", "pink");
+        attributedInfo.setAttribute("sound", (new String("にゃあ")).getBytes("UTF-8"));
+        attributedInfo.setAttribute("adorable", (String) null);
+        attributedInfo.setAttribute("sticky", "yes");
+        attributedInfo.setAttribute("siblings", new byte[] {});
+        attributedInfo.setAttribute("edge cases", new byte[] {0, -1, 127, -128});
+        attributedInfo.removeAttribute("sticky");
+        checkParcelable(attributedInfo);
+
+        // Sanity check that we actually wrote attributes to attributedInfo.
+        assertTrue(attributedInfo.getAttributes().keySet().contains("adorable"));
+        String sound = new String(attributedInfo.getAttributes().get("sound"), "UTF-8");
+        assertTrue(sound.equals("にゃあ"));
+        byte[] edgeCases = attributedInfo.getAttributes().get("edge cases");
+        assertTrue(Arrays.equals(edgeCases, new byte[] {0, -1, 127, -128}));
+        assertFalse(attributedInfo.getAttributes().keySet().contains("sticky"));
+    }
+
+    public void checkParcelable(NsdServiceInfo original) {
+        // Write to parcel.
+        Parcel p = Parcel.obtain();
+        Bundle writer = new Bundle();
+        writer.putParcelable("test_info", original);
+        writer.writeToParcel(p, 0);
+
+        // Extract from parcel.
+        p.setDataPosition(0);
+        Bundle reader = p.readBundle();
+        reader.setClassLoader(NsdServiceInfo.class.getClassLoader());
+        NsdServiceInfo result = reader.getParcelable("test_info");
+
+        // Assert equality of base fields.
+        assertEquality(original.getServiceName(), result.getServiceName());
+        assertEquality(original.getServiceType(), result.getServiceType());
+        assertEquality(original.getHost(), result.getHost());
+        assertTrue(original.getPort() == result.getPort());
+
+        // Assert equality of attribute map.
+        Map<String, byte[]> originalMap = original.getAttributes();
+        Map<String, byte[]> resultMap = result.getAttributes();
+        assertEquality(originalMap.keySet(), resultMap.keySet());
+        for (String key : originalMap.keySet()) {
+            assertTrue(Arrays.equals(originalMap.get(key), resultMap.get(key)));
+        }
+    }
+
+    public void assertEquality(Object expected, Object result) {
+        assertTrue(expected == result || expected.equals(result));
+    }
+
+    public void assertEmptyServiceInfo(NsdServiceInfo shouldBeEmpty) {
+        assertTrue(null == shouldBeEmpty.getTxtRecord());
+    }
+}
diff --git a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
index bf35db4..a0b2d1a 100644
--- a/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
+++ b/tests/DozeTest/src/com/android/dreams/dozetest/DozeTestDream.java
@@ -97,6 +97,7 @@
         setLowProfile(true);
         setFullscreen(true);
         setContentView(R.layout.dream);
+        setScreenBright(false);
 
         mAlarmClock = (TextView)findViewById(R.id.alarm_clock);
 
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index c8eefe0..5c2583b 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -868,13 +868,12 @@
         </activity>
 
         <activity
-                android:name="IsolationVolumeActivity"
-                android:label="Reordering/IsolationVolume">
+                android:name=".ProjectionClippingActivity"
+                android:label="Reordering/Projection Clipping">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
                 <category android:name="com.android.test.hwui.TEST" />
             </intent-filter>
         </activity>
-
     </application>
 </manifest>
diff --git a/tests/HwAccelerationTest/res/drawable/round_rect_background.xml b/tests/HwAccelerationTest/res/drawable/round_rect_background.xml
new file mode 100644
index 0000000..14d4073
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/round_rect_background.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android" >
+    <solid android:color="#eee" />
+    <corners android:radius="30dp" />
+</shape>
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/res/layout/isolation.xml b/tests/HwAccelerationTest/res/layout/isolation.xml
deleted file mode 100644
index e66db19..0000000
--- a/tests/HwAccelerationTest/res/layout/isolation.xml
+++ /dev/null
@@ -1,56 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:orientation="vertical"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="#f55">
-    <!-- Left and right layouts are not isolated volumes, so the text views
-         will interleave since they share an isolated z volume-->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="200dp"
-            android:layout_weight="1"
-            android:orientation="vertical">
-            <TextView style="@style/TopLeftReorderTextView"/>
-            <TextView style="@style/BottomLeftReorderTextView"/>
-        </LinearLayout>
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="200dp"
-            android:layout_weight="1"
-            android:translationY="50dp"
-            android:orientation="vertical">
-            <TextView style="@style/TopRightReorderTextView"/>
-            <TextView style="@style/BottomRightReorderTextView"/>
-        </LinearLayout>
-    </LinearLayout>
-
-    <!-- Left and right volumes are isolated by default, so no interleaving will be seen. -->
-    <LinearLayout
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:orientation="horizontal">
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="200dp"
-            android:layout_weight="1"
-            android:orientation="vertical">
-            <TextView style="@style/TopLeftReorderTextView"/>
-            <TextView style="@style/BottomLeftReorderTextView"/>
-        </LinearLayout>
-        <LinearLayout
-            android:layout_width="0dp"
-            android:layout_height="200dp"
-            android:layout_weight="1"
-            android:translationY="50dp"
-            android:orientation="vertical">
-            <TextView style="@style/TopRightReorderTextView"/>
-            <TextView style="@style/BottomRightReorderTextView"/>
-        </LinearLayout>
-    </LinearLayout>
-</LinearLayout>
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/res/layout/projection_clipping.xml b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
new file mode 100644
index 0000000..7177fc8f
--- /dev/null
+++ b/tests/HwAccelerationTest/res/layout/projection_clipping.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+    <FrameLayout
+        android:translationX="50dp"
+        android:translationY="50dp"
+        android:elevation="30dp"
+        android:layout_width="200dp"
+        android:layout_height="200dp"
+        android:background="@drawable/round_rect_background">
+        <View
+            android:id="@+id/clickable1"
+            android:layout_width="100dp"
+            android:layout_height="100dp"
+            android:background="?android:attr/selectableItemBackground"/>
+        <View
+            android:id="@+id/clickable2"
+            android:translationX="50dp"
+            android:translationY="10dp"
+            android:layout_width="150dp"
+            android:layout_height="100dp"
+            android:background="?android:attr/selectableItemBackground"/>
+    </FrameLayout>
+</LinearLayout>
\ No newline at end of file
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java
deleted file mode 100644
index d5c93f2..0000000
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/IsolationVolumeActivity.java
+++ /dev/null
@@ -1,12 +0,0 @@
-package com.android.test.hwui;
-
-import android.os.Bundle;
-import android.app.Activity;
-
-public class IsolationVolumeActivity extends Activity {
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        setContentView(R.layout.isolation);
-    }
-}
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java
new file mode 100644
index 0000000..2ae960b
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ProjectionClippingActivity.java
@@ -0,0 +1,27 @@
+package com.android.test.hwui;
+
+import android.app.Activity;
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.os.Bundle;
+import android.util.AttributeSet;
+import android.view.RenderNode;
+import android.view.View;
+
+public class ProjectionClippingActivity extends Activity {
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.projection_clipping);
+        View.OnClickListener listener = new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                // woo! nothing!
+            }
+        };
+        findViewById(R.id.clickable1).setOnClickListener(listener);
+        findViewById(R.id.clickable2).setOnClickListener(listener);
+    }
+}
diff --git a/tests/OneMedia/AndroidManifest.xml b/tests/OneMedia/AndroidManifest.xml
index 7d6ba1d..504d471 100644
--- a/tests/OneMedia/AndroidManifest.xml
+++ b/tests/OneMedia/AndroidManifest.xml
@@ -25,6 +25,15 @@
             android:name="com.android.onemedia.OnePlayerService"
             android:exported="false"
             android:process="com.android.onemedia.service" />
+        <service
+            android:name=".provider.OneMediaRouteProvider"
+            android:permission="android.permission.BIND_ROUTE_PROVIDER"
+            android:exported="true"
+            android:process="com.android.onemedia.provider">
+            <intent-filter>
+                <action android:name="com.android.media.session.MediaRouteProvider" />
+            </intent-filter>
+          </service>
     </application>
 
 </manifest>
diff --git a/tests/OneMedia/res/layout/activity_one_player.xml b/tests/OneMedia/res/layout/activity_one_player.xml
index 4208355..516562f 100644
--- a/tests/OneMedia/res/layout/activity_one_player.xml
+++ b/tests/OneMedia/res/layout/activity_one_player.xml
@@ -53,6 +53,12 @@
                 android:layout_weight="1"
                 android:text="@string/play_button" />
     </LinearLayout>
+    <Button
+            android:id="@+id/route_button"
+            style="@style/BottomBarButton"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:text="@string/route_button" />
     <TextView
             android:id="@+id/status"
             android:layout_width="match_parent"
diff --git a/tests/OneMedia/res/values/strings.xml b/tests/OneMedia/res/values/strings.xml
index 1b0cebb..3735c8d 100644
--- a/tests/OneMedia/res/values/strings.xml
+++ b/tests/OneMedia/res/values/strings.xml
@@ -7,6 +7,7 @@
 
     <string name="start_button">Start</string>
     <string name="play_button">Play</string>
+    <string name="route_button">Change route</string>
     <string name="media_content_hint">Content</string>
     <string name="media_next_hint">Next content</string>
     <string name="has_video">Is video</string>
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
index 2b14384..189fa6a 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerCallback.aidl
@@ -15,8 +15,8 @@
 
 package com.android.onemedia;
 
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
 
 interface IPlayerCallback {
-    void onSessionChanged(in MediaSessionToken session);
+    void onSessionChanged(in SessionToken session);
 }
\ No newline at end of file
diff --git a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
index efdbe9a..15ea25f 100644
--- a/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
+++ b/tests/OneMedia/src/com/android/onemedia/IPlayerService.aidl
@@ -15,14 +15,14 @@
 
 package com.android.onemedia;
 
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
 import android.os.Bundle;
 
 import com.android.onemedia.IPlayerCallback;
 import com.android.onemedia.playback.IRequestCallback;
 
 interface IPlayerService {
-    MediaSessionToken getSessionToken();
+    SessionToken getSessionToken();
     void registerCallback(in IPlayerCallback cb);
     void unregisterCallback(in IPlayerCallback cb);
     void sendRequest(String action, in Bundle params, in IRequestCallback cb);
diff --git a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
index 3114ca9..b9a6470 100644
--- a/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
+++ b/tests/OneMedia/src/com/android/onemedia/OnePlayerActivity.java
@@ -37,6 +37,7 @@
 
     private Button mStartButton;
     private Button mPlayButton;
+    private Button mRouteButton;
     private TextView mStatusView;
 
     private EditText mContentText;
@@ -54,6 +55,7 @@
 
         mStartButton = (Button) findViewById(R.id.start_button);
         mPlayButton = (Button) findViewById(R.id.play_button);
+        mRouteButton = (Button) findViewById(R.id.route_button);
         mStatusView = (TextView) findViewById(R.id.status);
         mContentText = (EditText) findViewById(R.id.content);
         mNextContentText = (EditText) findViewById(R.id.next_content);
@@ -61,6 +63,7 @@
 
         mStartButton.setOnClickListener(mButtonListener);
         mPlayButton.setOnClickListener(mButtonListener);
+        mRouteButton.setOnClickListener(mButtonListener);
 
     }
 
@@ -107,6 +110,9 @@
                     Log.d(TAG, "Start button pressed, in state " + mPlaybackState);
                     mPlayer.setContent(mContentText.getText().toString());
                     break;
+                case R.id.route_button:
+                    mPlayer.showRoutePicker();
+                    break;
             }
 
         }
@@ -117,6 +123,7 @@
         public void onPlaybackStateChange(PlaybackState state) {
             mPlaybackState = state.getState();
             boolean enablePlay = false;
+            boolean enableControls = true;
             StringBuilder statusBuilder = new StringBuilder();
             switch (mPlaybackState) {
                 case PlaybackState.PLAYSTATE_PLAYING:
@@ -143,12 +150,17 @@
                 case PlaybackState.PLAYSTATE_NONE:
                     statusBuilder.append("none");
                     break;
+                case PlaybackState.PLAYSTATE_CONNECTING:
+                    statusBuilder.append("connecting");
+                    enableControls = false;
+                    break;
                 default:
                     statusBuilder.append(mPlaybackState);
             }
             statusBuilder.append(" -- At position: ").append(state.getPosition());
             mStatusView.setText(statusBuilder.toString());
             mPlayButton.setEnabled(enablePlay);
+            setControlsEnabled(enableControls);
         }
 
         @Override
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerController.java b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
index e831ec6..e3f5c0c 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerController.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerController.java
@@ -16,9 +16,10 @@
  */
 package com.android.onemedia;
 
-import android.media.session.MediaController;
+import android.media.session.SessionController;
 import android.media.session.MediaMetadata;
-import android.media.session.MediaSessionManager;
+import android.media.session.RouteInfo;
+import android.media.session.SessionManager;
 import android.media.session.PlaybackState;
 import android.media.session.TransportController;
 import android.os.Bundle;
@@ -39,7 +40,7 @@
     public static final int STATE_DISCONNECTED = 0;
     public static final int STATE_CONNECTED = 1;
 
-    protected MediaController mController;
+    protected SessionController mController;
     protected IPlayerService mBinder;
     protected TransportController mTransportControls;
 
@@ -48,7 +49,7 @@
     private Listener mListener;
     private TransportListener mTransportListener = new TransportListener();
     private SessionCallback mControllerCb;
-    private MediaSessionManager mManager;
+    private SessionManager mManager;
     private Handler mHandler = new Handler();
 
     private boolean mResumed;
@@ -61,7 +62,7 @@
             mServiceIntent = serviceIntent;
         }
         mControllerCb = new SessionCallback();
-        mManager = (MediaSessionManager) context
+        mManager = (SessionManager) context
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
 
         mResumed = false;
@@ -121,6 +122,10 @@
         }
     }
 
+    public void showRoutePicker() {
+        mController.showRoutePicker();
+    }
+
     private void unbindFromService() {
         mContext.unbindService(mServiceConnection);
     }
@@ -150,7 +155,7 @@
             mBinder = IPlayerService.Stub.asInterface(service);
             Log.d(TAG, "service is " + service + " binder is " + mBinder);
             try {
-                mController = MediaController.fromToken(mBinder.getSessionToken());
+                mController = SessionController.fromToken(mBinder.getSessionToken());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error getting session", e);
                 return;
@@ -171,9 +176,9 @@
         }
     };
 
-    private class SessionCallback extends MediaController.Callback {
+    private class SessionCallback extends SessionController.Callback {
         @Override
-        public void onRouteChanged(Bundle route) {
+        public void onRouteChanged(RouteInfo route) {
             // TODO
         }
     }
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerService.java b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
index 0ad6dd1..8b53ddf 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerService.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerService.java
@@ -17,7 +17,7 @@
 
 import android.app.Service;
 import android.content.Intent;
-import android.media.session.MediaSessionToken;
+import android.media.session.SessionToken;
 import android.media.session.PlaybackState;
 import android.os.Bundle;
 import android.os.IBinder;
@@ -149,7 +149,7 @@
         }
 
         @Override
-        public MediaSessionToken getSessionToken() throws RemoteException {
+        public SessionToken getSessionToken() throws RemoteException {
             return mSession.getSessionToken();
         }
     }
diff --git a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
index a2d7897..2e029f0 100644
--- a/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
+++ b/tests/OneMedia/src/com/android/onemedia/PlayerSession.java
@@ -17,9 +17,13 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.media.session.MediaSession;
-import android.media.session.MediaSessionManager;
-import android.media.session.MediaSessionToken;
+import android.media.session.Route;
+import android.media.session.RouteInfo;
+import android.media.session.RouteOptions;
+import android.media.session.RoutePlaybackControls;
+import android.media.session.Session;
+import android.media.session.SessionManager;
+import android.media.session.SessionToken;
 import android.media.session.PlaybackState;
 import android.media.session.TransportPerformer;
 import android.os.Bundle;
@@ -27,41 +31,55 @@
 import android.view.KeyEvent;
 
 import com.android.onemedia.playback.LocalRenderer;
+import com.android.onemedia.playback.OneMRPRenderer;
 import com.android.onemedia.playback.Renderer;
-import com.android.onemedia.playback.RendererFactory;
+import com.android.onemedia.playback.RequestUtils;
+
+import java.util.ArrayList;
 
 public class PlayerSession {
     private static final String TAG = "PlayerSession";
 
-    protected MediaSession mSession;
+    protected Session mSession;
     protected Context mContext;
-    protected RendererFactory mRendererFactory;
-    protected LocalRenderer mRenderer;
-    protected MediaSession.Callback mCallback;
+    protected Renderer mRenderer;
+    protected Session.Callback mCallback;
     protected Renderer.Listener mRenderListener;
     protected TransportPerformer mPerformer;
 
     protected PlaybackState mPlaybackState;
     protected Listener mListener;
+    protected ArrayList<RouteOptions> mRouteOptions;
+    protected Route mRoute;
+    protected RoutePlaybackControls mRouteControls;
+    protected RouteListener mRouteListener;
+
+    private String mContent;
 
     public PlayerSession(Context context) {
         mContext = context;
-        mRendererFactory = new RendererFactory();
         mRenderer = new LocalRenderer(context, null);
-        mCallback = new ControllerCb();
+        mCallback = new SessionCb();
         mRenderListener = new RenderListener();
         mPlaybackState = new PlaybackState();
         mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
                 | PlaybackState.ACTION_PLAY);
 
         mRenderer.registerListener(mRenderListener);
+
+        // TODO need an easier way to build route options
+        mRouteOptions = new ArrayList<RouteOptions>();
+        RouteOptions.Builder bob = new RouteOptions.Builder();
+        bob.addInterface(RoutePlaybackControls.NAME);
+        mRouteOptions.add(bob.build());
+        mRouteListener = new RouteListener();
     }
 
     public void createSession() {
         if (mSession != null) {
             mSession.release();
         }
-        MediaSessionManager man = (MediaSessionManager) mContext
+        SessionManager man = (SessionManager) mContext
                 .getSystemService(Context.MEDIA_SESSION_SERVICE);
         Log.d(TAG, "Creating session for package " + mContext.getBasePackageName());
         mSession = man.createSession("OneMedia");
@@ -69,6 +87,7 @@
         mPerformer = mSession.setTransportPerformerEnabled();
         mPerformer.addListener(new TransportListener());
         mPerformer.setPlaybackState(mPlaybackState);
+        mSession.setRouteOptions(mRouteOptions);
         mSession.publish();
     }
 
@@ -86,18 +105,26 @@
         mListener = listener;
     }
 
-    public MediaSessionToken getSessionToken() {
+    public SessionToken getSessionToken() {
         return mSession.getSessionToken();
     }
 
     public void setContent(Bundle request) {
         mRenderer.setContent(request);
+        mContent = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
     }
 
     public void setNextContent(Bundle request) {
         mRenderer.setNextContent(request);
     }
 
+    private void updateState(int newState) {
+        float rate = newState == PlaybackState.PLAYSTATE_PLAYING ? 1 : 0;
+        long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
+        mPlaybackState.setState(newState, position, rate);
+        mPerformer.setPlaybackState(mPlaybackState);
+    }
+
     public interface Listener {
         public void onPlayStateChanged(PlaybackState state);
     }
@@ -107,7 +134,7 @@
         @Override
         public void onError(int type, int extra, Bundle extras, Throwable error) {
             Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
-            mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, -1, 0);
             if (error != null) {
                 mPlaybackState.setErrorMessage(error.getLocalizedMessage());
             }
@@ -122,30 +149,33 @@
             if (newState != Renderer.STATE_ERROR) {
                 mPlaybackState.setErrorMessage(null);
             }
+            long position = -1;
+            if (mRenderer != null) {
+                position = mRenderer.getSeekPosition();
+            }
             switch (newState) {
                 case Renderer.STATE_ENDED:
                 case Renderer.STATE_STOPPED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0);
                     break;
                 case Renderer.STATE_INIT:
                 case Renderer.STATE_PREPARING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0);
                     break;
                 case Renderer.STATE_ERROR:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     break;
                 case Renderer.STATE_PAUSED:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
                     break;
                 case Renderer.STATE_PLAYING:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1);
                     break;
                 default:
-                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR);
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
                     mPlaybackState.setErrorMessage("unkown state");
                     break;
             }
-            mPlaybackState.setPosition(mRenderer.getSeekPosition());
             mPerformer.setPlaybackState(mPlaybackState);
             if (mListener != null) {
                 mListener.onPlayStateChanged(mPlaybackState);
@@ -159,8 +189,8 @@
         @Override
         public void onFocusLost() {
             Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
-            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED);
-            mPlaybackState.setPosition(mRenderer.getSeekPosition());
+            long position = mRenderer == null ? -1 : mRenderer.getSeekPosition();
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
             mPerformer.setPlaybackState(mPlaybackState);
             if (mListener != null) {
                 mListener.onPlayStateChanged(mPlaybackState);
@@ -173,8 +203,7 @@
 
     }
 
-    private class ControllerCb extends MediaSession.Callback {
-
+    private class SessionCb extends Session.Callback {
         @Override
         public void onMediaButton(Intent mediaRequestIntent) {
             if (Intent.ACTION_MEDIA_BUTTON.equals(mediaRequestIntent.getAction())) {
@@ -192,6 +221,40 @@
                 }
             }
         }
+
+        @Override
+        public void onRequestRouteChange(RouteInfo route) {
+            if (mRenderer != null) {
+                mRenderer.onStop();
+            }
+            if (route == null) {
+                // Use local route
+                mRoute = null;
+                mRenderer = new LocalRenderer(mContext, null);
+                mRenderer.registerListener(mRenderListener);
+                updateState(PlaybackState.PLAYSTATE_NONE);
+            } else {
+                // Use remote route
+                mSession.connect(route, mRouteOptions.get(0));
+                mRenderer = null;
+                updateState(PlaybackState.PLAYSTATE_CONNECTING);
+            }
+        }
+
+        @Override
+        public void onRouteConnected(Route route) {
+            mRoute = route;
+            mRouteControls = RoutePlaybackControls.from(route);
+            mRouteControls.addListener(mRouteListener);
+            Log.d(TAG, "Connected to route, registering listener");
+            mRenderer = new OneMRPRenderer(mRouteControls);
+            updateState(PlaybackState.PLAYSTATE_NONE);
+        }
+
+        @Override
+        public void onRouteDisconnected(Route route, int reason) {
+
+        }
     }
 
     private class TransportListener extends TransportPerformer.Listener {
@@ -206,4 +269,12 @@
         }
     }
 
+    private class RouteListener extends RoutePlaybackControls.Listener {
+        @Override
+        public void onPlaybackStateChange(int state) {
+            Log.d(TAG, "Updating state to " + state);
+            updateState(state);
+        }
+    }
+
 }
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
index 7f62f66..c8a8d6c 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/LocalRenderer.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.onemedia.playback;
 
 import org.apache.http.Header;
@@ -370,6 +385,8 @@
      * Prepares the player for the given playback request. If the holder is null
      * it is assumed this is an audio only source. If playOnReady is set to true
      * the media will begin playing as soon as it can.
+     *
+     * @see RequestUtils for the set of valid keys.
      */
     public void setContent(Bundle request, SurfaceHolder holder) {
         String source = request.getString(RequestUtils.EXTRA_KEY_SOURCE);
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
index f9e6794..05516d2 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/MediaItem.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.onemedia.playback;
 
 import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
new file mode 100644
index 0000000..9b0a2b2
--- /dev/null
+++ b/tests/OneMedia/src/com/android/onemedia/playback/OneMRPRenderer.java
@@ -0,0 +1,44 @@
+package com.android.onemedia.playback;
+
+import android.media.session.RoutePlaybackControls;
+import android.os.Bundle;
+
+/**
+ * Renderer for communicating with the OneMRP route
+ */
+public class OneMRPRenderer extends Renderer {
+    private final RoutePlaybackControls mControls;
+
+    public OneMRPRenderer(RoutePlaybackControls controls) {
+        super(null, null);
+        mControls = controls;
+    }
+
+    @Override
+    public void setContent(Bundle request) {
+        mControls.playNow(request.getString(RequestUtils.EXTRA_KEY_SOURCE));
+    }
+
+    @Override
+    public boolean onStop() {
+        mControls.pause();
+        return true;
+    }
+
+    @Override
+    public boolean onPlay() {
+        mControls.resume();
+        return true;
+    }
+
+    @Override
+    public boolean onPause() {
+        mControls.pause();
+        return true;
+    }
+
+    @Override
+    public long getSeekPosition() {
+        return -1;
+    }
+}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java
index 72d936c..ac9da23 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/PlaybackError.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.onemedia.playback;
 
 import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java
index 2451bdf..09debcf 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/Renderer.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.onemedia.playback;
 
 import android.content.Context;
@@ -77,39 +92,54 @@
     }
 
     public boolean onPlay() {
-        throw new UnsupportedOperationException("play is not supported.");
+        // TODO consider making these log warnings instead of crashes (or
+        // Log.wtf)
+        // throw new UnsupportedOperationException("play is not supported.");
+        return false;
     }
 
     public boolean onPause() {
-        throw new UnsupportedOperationException("pause is not supported.");
+        // throw new UnsupportedOperationException("pause is not supported.");
+        return false;
     }
 
     public boolean onNext() {
-        throw new UnsupportedOperationException("next is not supported.");
+        // throw new UnsupportedOperationException("next is not supported.");
+        return false;
     }
 
     public boolean onPrevious() {
-        throw new UnsupportedOperationException("previous is not supported.");
+        // throw new
+        // UnsupportedOperationException("previous is not supported.");
+        return false;
     }
 
     public boolean onStop() {
-        throw new UnsupportedOperationException("stop is not supported.");
+        // throw new UnsupportedOperationException("stop is not supported.");
+        return false;
     }
 
     public boolean onSeekTo(int time) {
-        throw new UnsupportedOperationException("seekTo is not supported.");
+        // throw new UnsupportedOperationException("seekTo is not supported.");
+        return false;
     }
 
     public long getSeekPosition() {
-        throw new UnsupportedOperationException("getSeekPosition is not supported.");
+        // throw new
+        // UnsupportedOperationException("getSeekPosition is not supported.");
+        return -1;
     }
 
     public long getDuration() {
-        throw new UnsupportedOperationException("getDuration is not supported.");
+        // throw new
+        // UnsupportedOperationException("getDuration is not supported.");
+        return -1;
     }
 
     public int getPlayState() {
-        throw new UnsupportedOperationException("getPlayState is not supported.");
+        // throw new
+        // UnsupportedOperationException("getPlayState is not supported.");
+        return 0;
     }
 
     public void onDestroy() {
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java b/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java
deleted file mode 100644
index f333fce..0000000
--- a/tests/OneMedia/src/com/android/onemedia/playback/RendererFactory.java
+++ /dev/null
@@ -1,22 +0,0 @@
-package com.android.onemedia.playback;
-
-import android.content.Context;
-import android.media.MediaRouter;
-import android.os.Bundle;
-import android.util.Log;
-
-/**
- * TODO: Insert description here.
- */
-public class RendererFactory {
-    private static final String TAG = "RendererFactory";
-
-    public Renderer createRenderer(MediaRouter.RouteInfo route, Context context, Bundle params) {
-        if (route.getPlaybackType() == MediaRouter.RouteInfo.PLAYBACK_TYPE_LOCAL) {
-            return new LocalRenderer(context, params);
-        }
-        Log.e(TAG, "Unable to create renderer for route of playback type "
-                + route.getPlaybackType());
-        return null;
-    }
-}
diff --git a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
index 9b50dad..dd0d982 100644
--- a/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
+++ b/tests/OneMedia/src/com/android/onemedia/playback/RequestUtils.java
@@ -1,3 +1,18 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
 package com.android.onemedia.playback;
 
 import android.os.Bundle;
diff --git a/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
new file mode 100644
index 0000000..6537d49
--- /dev/null
+++ b/tests/OneMedia/src/com/android/onemedia/provider/OneMediaRouteProvider.java
@@ -0,0 +1,207 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.onemedia.provider;
+
+import android.media.routeprovider.RouteConnection;
+import android.media.routeprovider.RouteInterfaceHandler;
+import android.media.routeprovider.RoutePlaybackControlsHandler;
+import android.media.routeprovider.RouteProviderService;
+import android.media.routeprovider.RouteRequest;
+import android.media.session.RouteInfo;
+import android.media.session.RoutePlaybackControls;
+import android.media.session.RouteInterface;
+import android.media.session.PlaybackState;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.ResultReceiver;
+import android.util.Log;
+
+import com.android.onemedia.playback.LocalRenderer;
+import com.android.onemedia.playback.Renderer;
+import com.android.onemedia.playback.RequestUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Test of MediaRouteProvider. Show a dummy provider with a simple interface for
+ * playing music.
+ */
+public class OneMediaRouteProvider extends RouteProviderService {
+    private static final String TAG = "OneMRP";
+    private static final boolean DEBUG = true;
+
+    private Renderer mRenderer;
+    private RenderListener mRenderListener;
+    private PlaybackState mPlaybackState;
+    private RouteConnection mConnection;
+    private RoutePlaybackControlsHandler mControls;
+    private String mRouteId;
+    private Handler mHandler;
+
+    @Override
+    public void onCreate() {
+        mHandler = new Handler();
+        mRouteId = UUID.randomUUID().toString();
+        mRenderer = new LocalRenderer(this, null);
+        mRenderListener = new RenderListener();
+        mPlaybackState = new PlaybackState();
+        mPlaybackState.setActions(PlaybackState.ACTION_PAUSE
+                | PlaybackState.ACTION_PLAY);
+
+        mRenderer.registerListener(mRenderListener);
+
+        if (DEBUG) {
+            Log.d(TAG, "onCreate, routeId is " + mRouteId);
+        }
+    }
+
+    @Override
+    public List<RouteInfo> getMatchingRoutes(List<RouteRequest> requests) {
+        RouteInfo.Builder bob = new RouteInfo.Builder();
+        bob.setName("OneMedia").setId(mRouteId);
+        // TODO add a helper library for generating route info with the correct
+        // options
+        Log.d(TAG, "Requests:");
+        for (RouteRequest request : requests) {
+            List<String> ifaces = request.getConnectionOptions().getInterfaceNames();
+            Log.d(TAG, "  request ifaces:" + ifaces.toString());
+            if (ifaces != null && ifaces.size() == 1
+                    && RoutePlaybackControls.NAME.equals(ifaces.get(0))) {
+                bob.addRouteOptions(request.getConnectionOptions());
+            }
+        }
+        ArrayList<RouteInfo> result = new ArrayList<RouteInfo>();
+        if (bob.getOptionsSize() > 0) {
+            RouteInfo info = bob.build();
+            result.add(info);
+        }
+        if (DEBUG) {
+            Log.d(TAG, "getRoutes returning " + result.toString());
+        }
+        return result;
+    }
+
+    @Override
+    public RouteConnection connect(RouteInfo route, RouteRequest request) {
+        if (mConnection != null) {
+            disconnect(mConnection);
+        }
+        RouteConnection connection = new RouteConnection(this, route);
+        mControls = RoutePlaybackControlsHandler.addTo(connection);
+        mControls.addListener(new PlayHandler(mRouteId), mHandler);
+        if (DEBUG) {
+            Log.d(TAG, "Connected to route");
+        }
+        return connection;
+    }
+
+    private class PlayHandler extends RoutePlaybackControlsHandler.Listener {
+        private final String mRouteId;
+
+        public PlayHandler(String routeId) {
+            mRouteId = routeId;
+        }
+
+        @Override
+        public void playNow(String content, ResultReceiver cb) {
+            if (DEBUG) {
+                Log.d(TAG, "Attempting to play " + content);
+            }
+            // look up the route and send a play command to it
+            Bundle bundle = new Bundle();
+            bundle.putString(RequestUtils.EXTRA_KEY_SOURCE, content);
+            mRenderer.setContent(bundle);
+            RouteInterfaceHandler.sendResult(cb, RouteInterface.RESULT_SUCCESS, null);
+        }
+
+        @Override
+        public boolean resume() {
+            mRenderer.onPlay();
+            return true;
+        }
+
+        @Override
+        public boolean pause() {
+            mRenderer.onPause();
+            return true;
+        }
+    }
+
+    private class RenderListener implements Renderer.Listener {
+
+        @Override
+        public void onError(int type, int extra, Bundle extras, Throwable error) {
+            Log.d(TAG, "Sending onError with type " + type + " and extra " + extra);
+            if (mControls != null) {
+                mControls.sendPlaybackChangeEvent(PlaybackState.PLAYSTATE_ERROR);
+            }
+        }
+
+        @Override
+        public void onStateChanged(int newState) {
+            if (newState != Renderer.STATE_ERROR) {
+                mPlaybackState.setErrorMessage(null);
+            }
+            long position = -1;
+            if (mRenderer != null) {
+                position = mRenderer.getSeekPosition();
+            }
+            switch (newState) {
+                case Renderer.STATE_ENDED:
+                case Renderer.STATE_STOPPED:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_STOPPED, position, 0);
+                    break;
+                case Renderer.STATE_INIT:
+                case Renderer.STATE_PREPARING:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_BUFFERING, position, 0);
+                    break;
+                case Renderer.STATE_ERROR:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
+                    break;
+                case Renderer.STATE_PAUSED:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, position, 0);
+                    break;
+                case Renderer.STATE_PLAYING:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_PLAYING, position, 1);
+                    break;
+                default:
+                    mPlaybackState.setState(PlaybackState.PLAYSTATE_ERROR, position, 0);
+                    mPlaybackState.setErrorMessage("unkown state");
+                    break;
+            }
+
+            mControls.sendPlaybackChangeEvent(mPlaybackState.getState());
+        }
+
+        @Override
+        public void onBufferingUpdate(int percent) {
+        }
+
+        @Override
+        public void onFocusLost() {
+            Log.d(TAG, "Focus lost, changing state to " + Renderer.STATE_PAUSED);
+            mPlaybackState.setState(PlaybackState.PLAYSTATE_PAUSED, mRenderer.getSeekPosition(), 0);
+            mRenderer.onPause();
+        }
+
+        @Override
+        public void onNextStarted() {
+        }
+    }
+}
diff --git a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
index 09531fd..1d209dd 100644
--- a/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
+++ b/tests/RenderThreadTest/src/com/example/renderthread/MainActivity.java
@@ -1,17 +1,13 @@
 
 package com.example.renderthread;
 
-import android.animation.TimeInterpolator;
 import android.app.Activity;
 import android.content.Intent;
 import android.os.Bundle;
 import android.os.Handler;
-import android.os.SystemClock;
-import android.view.RenderNode;
 import android.view.HardwareRenderer;
-import android.view.ThreadedRenderer;
+import android.view.RenderNodeAnimator;
 import android.view.View;
-import android.view.animation.AccelerateDecelerateInterpolator;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.ListView;
@@ -23,6 +19,8 @@
 
 public class MainActivity extends Activity implements OnItemClickListener {
 
+    static final int TRANSLATION_Y = 1;
+    static final int DELTA_TYPE_DELTA = 1;
     static final int DURATION = 400;
 
     static final String KEY_NAME = "name";
@@ -66,82 +64,21 @@
         }
     }
 
-    private static class DisplayListAnimator {
-        private static final TimeInterpolator sDefaultInterpolator =
-                new AccelerateDecelerateInterpolator();
-
-        RenderNode mDisplayList;
-        float mFromValue;
-        float mDelta;
-        long mDuration = DURATION * 2;
-        long mStartTime;
-
-        DisplayListAnimator(View view, float translateXBy) {
-            mDelta = translateXBy;
-            mFromValue = view.getTranslationY();
-            mDisplayList = view.getDisplayList();
-        }
-
-        boolean animate(long currentTime) {
-            if (mStartTime == 0) mStartTime = currentTime;
-
-            float fraction = (float)(currentTime - mStartTime) / mDuration;
-            if (fraction > 1) {
-                return false;
-            }
-            fraction = sDefaultInterpolator.getInterpolation(fraction);
-            float translation = mFromValue + (mDelta * fraction);
-            mDisplayList.setTranslationY(translation);
-            return fraction < 1f;
-        }
-    }
-
-    private static class AnimationExecutor implements Runnable {
-        DisplayListAnimator[] mAnimations;
-        ThreadedRenderer mRenderer;
-
-        AnimationExecutor(ThreadedRenderer renderer, DisplayListAnimator[] animations) {
-            mRenderer = renderer;
-            mAnimations = animations;
-            ThreadedRenderer.postToRenderThread(this);
-        }
-
-        @Override
-        public void run() {
-            boolean hasMore = false;
-            long now = SystemClock.uptimeMillis();
-            for (DisplayListAnimator animator : mAnimations) {
-                hasMore |= animator.animate(now);
-            }
-            mRenderer.repeatLastDraw();
-            if (hasMore) {
-                ThreadedRenderer.postToRenderThread(this);
-            }
-        }
-
-    }
-
     @Override
     public void onItemClick(final AdapterView<?> adapterView, View clickedView,
             int clickedPosition, long clickedId) {
         int topPosition = adapterView.getFirstVisiblePosition();
         int dy = adapterView.getHeight();
-        final DisplayListAnimator[] animators = new DisplayListAnimator[adapterView.getChildCount()];
         for (int i = 0; i < adapterView.getChildCount(); i++) {
             int pos = topPosition + i;
             View child = adapterView.getChildAt(i);
             float delta = (pos - clickedPosition) * 1.1f;
             if (delta == 0) delta = -1;
-            animators[i] = new DisplayListAnimator(child, dy * delta);
+            RenderNodeAnimator animator = new RenderNodeAnimator(
+                    TRANSLATION_Y, DELTA_TYPE_DELTA, dy * delta);
+            animator.setDuration(DURATION);
+            animator.start(child);
         }
-        adapterView.invalidate();
-        adapterView.post(new Runnable() {
-
-            @Override
-            public void run() {
-                new AnimationExecutor((ThreadedRenderer) adapterView.getHardwareRenderer(), animators);
-            }
-        });
         //mHandler.postDelayed(mLaunchActivity, (long) (DURATION * .4));
         mLaunchActivity.run();
     }
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
index 6ca1aa7..bb2bebf 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable01.xml
@@ -46,8 +46,8 @@
             android:rotation="46.757"
             android:pivotX="162"
             android:pivotY="173.5"
-            android:fill="?attr/android:colorControlNormal"
-            android:stroke="?attr/android:colorControlNormal"
+            android:fill="?android:attr/colorControlNormal"
+            android:stroke="?android:attr/colorControlNormal"
             android:strokeWidth="3"
             android:strokeLineCap="round"
             android:strokeLineJoin="round" />
@@ -56,7 +56,7 @@
         <path
             android:name="box3"
             android:pathData="m187,147l-1,55l-49,-1l2,-53l48,0z"
-            android:stroke="?attr/android:colorControlNormal"
+            android:stroke="?android:attr/colorControlNormal"
             android:strokeWidth="10"
             android:strokeLineCap="round"
             android:strokeLineJoin="round" />
@@ -65,7 +65,7 @@
         <path
             android:name="box4"
             android:pathData="m248,74l0,164l-177,0l1,-165l173,-1l3,2z"
-            android:stroke="?attr/android:colorControlNormal"
+            android:stroke="?android:attr/colorControlNormal"
             android:strokeWidth="30"
             android:strokeLineCap="round"
             android:strokeLineJoin="round" />
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
index bcf3ae6..0be6755 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable05.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,26 +16,25 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
     <viewport
-            android:viewportWidth="7.30625"
-            android:viewportHeight="12.25"/>
+        android:viewportHeight="12.25"
+        android:viewportWidth="7.30625" />
 
     <group>
         <path
-                android:name="one"
-                android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+            android:name="one"
+            android:fill="#ffff00"
+            android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
                 l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
-                l -5.046875,0.0 0.0,-1.0Z"
-                android:fill="#ffff00"
-                />
-
-
+                l -5.046875,0.0 0.0,-1.0Z" />
         <path
-                android:name="two"
-                android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+            android:name="two"
+            android:fill="#ffff00"
+            android:fillOpacity="0"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
                         q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
                         q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
                         q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
@@ -42,23 +42,20 @@
                         q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
                         q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
-                        q -0.78125024,0.8125 -2.2187502,2.265625Z"
-                android:fill="#ffff00"
-                android:fillOpacity="0"
-                />
+                        q -0.78125024,0.8125 -2.2187502,2.265625Z" />
     </group>
     <group>
         <path
-                android:name="one"
-                android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
+            android:name="one"
+            android:fill="#ffff00"
+            android:fillOpacity="0"
+            android:pathData="M 1.215625,9.5l 1.9375,0.0 0.0,-6.671875 -2.109375,0.421875 0.0,-1.078125
 l 2.09375,-0.421875 1.1874998,0.0 0.0,7.75 1.9375,0.0 0.0,1.0
-l -5.046875,0.0 0.0,-1.0Z"
-                android:fill="#ffff00"
-                android:fillOpacity="0"
-                />
+l -5.046875,0.0 0.0,-1.0Z" />
         <path
-                android:name="two"
-                android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+            android:name="two"
+            android:fill="#ffff00"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
                         q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
                         q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
                         q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
@@ -66,14 +63,13 @@
                         q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
                         q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
-                        q -0.78125024,0.8125 -2.2187502,2.265625Z"
-                android:fill="#ffff00"
-                />
+                        q -0.78125024,0.8125 -2.2187502,2.265625Z" />
     </group>
     <group>
         <path
-                android:name="two"
-                android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+            android:name="two"
+            android:fill="#ffff00"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
                         q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
                         q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
                         q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
@@ -81,12 +77,12 @@
                         q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
                         q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
-                        q -0.78125024,0.8125 -2.2187502,2.265625Z"
-                android:fill="#ffff00"
-                />
+                        q -0.78125024,0.8125 -2.2187502,2.265625Z" />
         <path
-                android:name="three"
-                android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+            android:name="three"
+            android:fill="#ffff00"
+            android:fillOpacity="0"
+            android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
                         q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
                         q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
                         l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
@@ -98,15 +94,14 @@
                         q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
                         q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
                         q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
-                        q -0.40625,0.5 -1.171875,0.6875Z"
-                android:fill="#ffff00"
-                android:fillOpacity="0"
-                />
+                        q -0.40625,0.5 -1.171875,0.6875Z" />
     </group>
     <group>
         <path
-                android:name="two"
-                android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
+            android:name="two"
+            android:fill="#ffff00"
+            android:fillOpacity="0"
+            android:pathData="M 2.534375,9.6875l 4.140625,0.0 0.0,1.0 -5.5625,0.0 0.0,-1.0q 0.671875,-0.6875 1.828125,-1.859375
                         q 1.1718752,-1.1875 1.4687502,-1.53125 0.578125,-0.625 0.796875,-1.0625
                         q 0.234375,-0.453125 0.234375,-0.875 0.0,-0.703125 -0.5,-1.140625
                         q -0.484375,-0.4375 -1.2656252,-0.4375 -0.5625,0.0 -1.1875,0.1875
@@ -114,13 +109,11 @@
                         q 0.625,-0.15625 1.140625,-0.15625 1.3593752,0.0 2.1718752,0.6875
                         q 0.8125,0.671875 0.8125,1.8125 0.0,0.53125 -0.203125,1.015625
                         q -0.203125,0.484375 -0.734375,1.140625 -0.15625,0.171875 -0.9375,0.984375
-                        q -0.78125024,0.8125 -2.2187502,2.265625Z"
-                android:fill="#ffff00"
-                android:fillOpacity="0"
-                />
+                        q -0.78125024,0.8125 -2.2187502,2.265625Z" />
         <path
-                android:name="three"
-                android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
+            android:name="three"
+            android:fill="#ffff00"
+            android:pathData="M 5.103125,6.003125q 0.84375,0.1875 1.3125,0.765625 0.484375,0.5625 0.484375,1.40625
                         q 0.0,1.296875 -0.890625,2.015625 -0.890625,0.703125 -2.53125,0.703125
                         q -0.546875,0.0 -1.140625,-0.109375 -0.5781251,-0.109375 -1.1875001,-0.328125
                         l 0.0,-1.140625q 0.484375,0.28125 1.0625001,0.4375 0.59375,0.140625 1.234375,0.140625
@@ -132,16 +125,14 @@
                         q -0.546875,0.09375 -1.2187501,0.3125l 0.0,-1.046875q 0.6875001,-0.1875 1.2656251,-0.28125
                         q 0.59375,-0.09375 1.109375,-0.09375 1.359375,0.0 2.140625,0.609375
                         q 0.78125,0.609375 0.78125,1.65625 0.0,0.734375 -0.421875,1.234375
-                        q -0.40625,0.5 -1.171875,0.6875Z"
-                android:fill="#ffff00"
-                />
+                        q -0.40625,0.5 -1.171875,0.6875Z" />
     </group>
 
+    <animation
+        android:durations="2000,0,2000"
+        android:sequence="one,one,three,three" />
+    <animation
+        android:durations="2000,0,2000"
+        android:sequence="two,two,two,two" />
 
-    <animation
-            android:sequence="one,one,three,three"
-            android:durations="2000,0,2000"/>
-    <animation
-            android:sequence="two,two,two,two"
-            android:durations="2000,0,2000"/>
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
index 09934de..b3c91a88 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable09.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,27 +16,29 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-
-    <viewport android:viewportWidth="200"
-          android:viewportHeight="200"/>
+    <viewport
+        android:viewportHeight="200"
+        android:viewportWidth="200" />
 
     <group>
         <path
-                android:name="arrow"
-                android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z"
-                android:fill="#ffffffff"/>
+            android:name="arrow"
+            android:fill="#ffffffff"
+            android:pathData="M 20,20 l 60,0 0,140 -60,0 z M 120,20 l 60,0 0,140 -60,0 z" />
     </group>
     <group>
         <path
-                android:name="house"
-                android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
-                android:fill="#ffffffff"
-                android:rotation="90"
-                android:pivotX="100"
-                android:pivotY="100"/>
+            android:name="house"
+            android:fill="#ffffffff"
+            android:pathData="M 100,20 l 0,0 0,140 -80,0 z M 100,20 l 0,0 80,140 -80,0 z"
+            android:pivotX="100"
+            android:pivotY="100"
+            android:rotation="90" />
     </group>
-    <animation android:sequence="arrow,house"/>
-</vector>
+
+    <animation android:sequence="arrow,house" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
index f17f67a..7aca169 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable10.xml
@@ -27,88 +27,87 @@
     <group>
         <path
             android:name="bar3"
-            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
         <path
             android:name="bar2"
-            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
         <path
             android:name="bar1"
-            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
         <path
             android:name="bar0"
-            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
     </group>
- <group>
+    <group>
         <path
             android:name="bar3"
-            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
         <path
             android:name="bar2"
-            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
         <path
             android:name="bar1"
-            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
         <path
             android:name="bar0"
-            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
     </group>
-
-  <group>
+    <group>
         <path
             android:name="bar3"
-            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
         <path
             android:name="bar2"
-            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
         <path
             android:name="bar1"
-            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
         <path
             android:name="bar0"
-            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
-            android:fill="#FF555555" />
+            android:fill="#FF555555"
+            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
     </group>
-
-   <group>
+    <group>
         <path
             android:name="bar3"
-            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M49.001,60c-5.466,0 -9.899,4.478 -9.899,10s4.434,10,9.899,10c5.468,0,9.899 -4.478,9.899 -10S54.469,60,49.001,60z" />
         <path
             android:name="bar2"
-            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M28.001,48.787l7,7.07c7.731 -7.811,20.269 -7.81,28.001,0l6.999 -7.07C58.403,37.071,39.599,37.071,28.001,48.787z" />
         <path
             android:name="bar1"
-            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M14.001,34.645   L21,41.716c15.464 -15.621,40.536 -15.621,56,0l7.001 -7.071C64.672,15.119,33.33,15.119,14.001,34.645z" />
         <path
             android:name="bar0"
-            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z"
-            android:fill="#FFFFFFFF" />
+            android:fill="#FFFFFFFF"
+            android:pathData="M0,20.502l6.999,7.071   c23.196 -23.431,60.806 -23.431,84.002,0L98,20.503C70.938 -6.834,27.063 -6.834,0,20.502z" />
     </group>
 
- <animation
-            android:sequence="bar0,bar0,bar0,bar0"
-            android:durations="500,500,500"/>
- <animation
-            android:sequence="bar1,bar1,bar1,bar1"
-            android:durations="500,500,500"/>
- <animation
-            android:sequence="bar2,bar2,bar2,bar2"
-            android:durations="500,500,500"/>
- <animation
-            android:sequence="bar3,bar3,bar3,bar3"
-            android:durations="500,500,500"/>
-</vector>
+    <animation
+        android:durations="500,500,500"
+        android:sequence="bar0,bar0,bar0,bar0" />
+    <animation
+        android:durations="500,500,500"
+        android:sequence="bar1,bar1,bar1,bar1" />
+    <animation
+        android:durations="500,500,500"
+        android:sequence="bar2,bar2,bar2,bar2" />
+    <animation
+        android:durations="500,500,500"
+        android:sequence="bar3,bar3,bar3,bar3" />
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
index 8787b34..a4403c5 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable11.xml
@@ -26,29 +26,28 @@
     <group>
         <path
             android:name="battery"
-            android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
             android:fill="#3388ff"
+            android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+            android:rotation="0"
             android:stroke="#ff8833"
-            android:strokeWidth="1"
-            android:rotation="0"/>
-         <path
+            android:strokeWidth="1" />
+        <path
             android:name="spark"
-            android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
-            android:fill="#FFFF0000" />
-
+            android:fill="#FFFF0000"
+            android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
     </group>
     <group>
         <path
             android:name="battery"
-            android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
             android:fill="#ff8833"
+            android:pathData="M 20.28125,2.0000002 C 17.352748,2.0000002 15,4.3527485 15,7.2812502 L 15,8.0000002 L 13.15625,8.0000002 C 9.7507553,8.0000002 7,10.750759 7,14.15625 L 7,39.84375 C 7,43.24924 9.7507558,46 13.15625,46 L 33.84375,46 C 37.249245,46 39.999999,43.24924 40,39.84375 L 40,14.15625 C 40,10.75076 37.249243,8.0000002 33.84375,8.0000002 L 32,8.0000002 L 32,7.2812502 C 32,4.3527485 29.647252,2.0000002 26.71875,2.0000002 L 20.28125,2.0000002 z"
+            android:rotation="0"
             android:stroke="#3388ff"
-            android:strokeWidth="1"
-            android:rotation="0" />
+            android:strokeWidth="1" />
         <path
             android:name="spark"
-            android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z"
-            android:fill="#FFFF0000" />
+            android:fill="#FFFF0000"
+            android:pathData="M 30,18.031528 L 25.579581,23.421071 L 29.370621,26.765348 L 20.096792,37 L 21.156922,28.014053 L 17,24.902844 L 20.880632,18 L 30,18.031528 z" />
     </group>
 
     <animation
@@ -58,5 +57,4 @@
         android:durations="2000"
         android:sequence="battery,battery" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
index 89748d5..207879d 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable12.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,76 +16,72 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-
-    <viewport android:viewportWidth="600"
-          android:viewportHeight="600"/>
+    <viewport
+        android:viewportHeight="600"
+        android:viewportWidth="600" />
 
     <group>
         <path
-                android:name="pie1"
-                android:pathData="M300,70 a230,230 0 1,0 1,0 z"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="70"
-                android:trimPathStart="0"
-                android:trimPathEnd=".75"
-                android:trimPathOffset="0"/>
-
+            android:name="pie1"
+            android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="70"
+            android:trimPathEnd=".75"
+            android:trimPathOffset="0"
+            android:trimPathStart="0" />
         <path
-                android:name="v"
-                android:pathData="M300,70 l 0,-70 70,70 -70,70z"
-                android:fill="#FF00FF00"
-                android:pivotX="300"
-                android:pivotY="300"
-                android:rotation="0"
-                />
+            android:name="v"
+            android:fill="#FF00FF00"
+            android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+            android:pivotX="300"
+            android:pivotY="300"
+            android:rotation="0" />
     </group>
-
     <group>
         <path
-                android:name="v"
-                android:pathData="M300,70 l 0,-70 70,70 -70,70z"
-                android:pivotX="300"
-                android:pivotY="300"
-                android:rotation="360"/>
+            android:name="v"
+            android:pathData="M300,70 l 0,-70 70,70 -70,70z"
+            android:pivotX="300"
+            android:pivotY="300"
+            android:rotation="360" />
         <path
-                android:name="pie2"
-                android:pathData="M300,70 a230,230 0 1,0 1,0 z"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="70"
-                android:rotation="360"
-                android:pivotX="300"
-                android:pivotY="300"
-                android:trimPathStart="0"
-                android:trimPathEnd=".5"
-                android:trimPathOffset="0"
-                android:strokeLineCap="round"
-                />
+            android:name="pie2"
+            android:pathData="M300,70 a230,230 0 1,0 1,0 z"
+            android:pivotX="300"
+            android:pivotY="300"
+            android:rotation="360"
+            android:stroke="#FF00FF00"
+            android:strokeLineCap="round"
+            android:strokeWidth="70"
+            android:trimPathEnd=".5"
+            android:trimPathOffset="0"
+            android:trimPathStart="0" />
     </group>
 
-    <animation android:sequence="pie1,pie2"
-               android:durations="2000"
-               android:startOffset="500"
-               android:repeatCount="-1"
-               android:repeatStyle="forward"
-               android:animate="easeInOut"
-            />
-    <animation android:sequence="v,v"
-               android:durations="2000"
-               android:startOffset="500"
-               android:repeatCount="-1"
-               android:repeatStyle="forward"
-               android:animate="easeInOut"
-            />
-    <animation android:sequence="pie1,pie2"
-               android:durations="2800"
-               android:startOffset="500"
-               android:limitTo="trimPathEnd"
-               android:repeatCount="-1"
-               android:repeatStyle="reverse"
-               android:animate="easeInOut"
-            />
+    <animation
+        android:animate="easeInOut"
+        android:durations="2000"
+        android:repeatCount="-1"
+        android:repeatStyle="forward"
+        android:sequence="pie1,pie2"
+        android:startOffset="500" />
+    <animation
+        android:animate="easeInOut"
+        android:durations="2000"
+        android:repeatCount="-1"
+        android:repeatStyle="forward"
+        android:sequence="v,v"
+        android:startOffset="500" />
+    <animation
+        android:animate="easeInOut"
+        android:durations="2800"
+        android:limitTo="trimPathEnd"
+        android:repeatCount="-1"
+        android:repeatStyle="reverse"
+        android:sequence="pie1,pie2"
+        android:startOffset="500" />
 
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
index 43dda52..4a2ed90 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable13.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,68 +16,64 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-
-    <viewport android:viewportWidth="600"
-          android:viewportHeight="400"/>
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="600" />
 
     <group>
         <path
-                android:name="pie1"
-                android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
-                android:fill="#ffffffff"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="1"/>
-
+            android:name="pie1"
+            android:fill="#ffffffff"
+            android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="1" />
         <path
-                android:name="half"
-                android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
-                android:fill="#FFFF0000"
-                android:stroke="#FF0000FF"
-                android:strokeWidth="5"
-                android:rotation="0"
-                android:pivotX="300"
-                android:pivotY="200"/>
+            android:name="half"
+            android:fill="#FFFF0000"
+            android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+            android:pivotX="300"
+            android:pivotY="200"
+            android:rotation="0"
+            android:stroke="#FF0000FF"
+            android:strokeWidth="5" />
     </group>
-
     <group>
         <path
-                android:name="pie2"
-                android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
-                android:fill="#ffff0000"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="10"
-                android:rotation="360"
-                android:pivotX="300"
-                android:pivotY="200"/>
-
+            android:name="pie2"
+            android:fill="#ffff0000"
+            android:pathData="M300,200 h-150 a150,150 0 1,0 150,-150 z"
+            android:pivotX="300"
+            android:pivotY="200"
+            android:rotation="360"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
         <path
-                android:name="half"
-                android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
-                android:fill="#FFFFFF00"
-                android:stroke="#FF0000FF"
-                android:strokeWidth="5"
-                android:rotation="-360"
-                android:pivotX="300"
-                android:pivotY="200"/>
+            android:name="half"
+            android:fill="#FFFFFF00"
+            android:pathData="M275,175 v-150 a150,150 0 0,0 -150,150 z"
+            android:pivotX="300"
+            android:pivotY="200"
+            android:rotation="-360"
+            android:stroke="#FF0000FF"
+            android:strokeWidth="5" />
     </group>
-    <animation android:sequence="pie1,pie2"
-               android:durations="1000"
-               android:startOffset="500"
-               android:repeatCount="2"
-               android:repeatStyle="forward"
-               android:animate="easeInOut"
-            />
-    <animation android:sequence="half,half"
-               android:durations="1000"
-               android:startOffset="500"
-               android:repeatCount="5"
-               android:repeatStyle="forward"
-               android:animate="easeInOut"
-            />
 
+    <animation
+        android:animate="easeInOut"
+        android:durations="1000"
+        android:repeatCount="2"
+        android:repeatStyle="forward"
+        android:sequence="pie1,pie2"
+        android:startOffset="500" />
+    <animation
+        android:animate="easeInOut"
+        android:durations="1000"
+        android:repeatCount="5"
+        android:repeatStyle="forward"
+        android:sequence="half,half"
+        android:startOffset="500" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
index 0f1f149..6ebd56b 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable14.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,40 +16,39 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="800"
-          android:viewportHeight="500"/>
+    <viewport
+        android:viewportHeight="500"
+        android:viewportWidth="800" />
 
     <group>
         <path
-                android:name="pie1"
-                android:pathData="M200,450 l 50,-25
+            android:name="pie1"
+            android:pathData="M200,450 l 50,-25
            a25,25 -30 0,1 100,-50 l 50,-25
            a25,50 -30 0,1 100,-50 l 50,-25
            a25,75 -30 0,1 100,-50 l 50,-25
            a25,100 -30 0,1 100,-50 l 50,-25"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="10"/>
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
-
     <group>
         <path
-                android:name="pie2"
-                android:pathData="M200,350 l 50,-25
+            android:name="pie2"
+            android:pathData="M200,350 l 50,-25
            a25,12 -30 0,1 100,-50 l 50,-25
            a25,25 -30 0,1 100,-50 l 50,-25
            a25,37 -30 0,1 100,-50 l 50,-25
            a25,50 -30 0,1 100,-50 l 50,-25"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="10"
-                android:rotation="20"
-                android:pivotX="90"
-                android:pivotY="100"/>
-
+            android:pivotX="90"
+            android:pivotY="100"
+            android:rotation="20"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
-    <animation android:sequence="pie1,pie2"/>
 
+    <animation android:sequence="pie1,pie2" />
 
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
index 6bc946f..3c92d25 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable15.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,34 +16,33 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="500"
-          android:viewportHeight="400"/>
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="500" />
 
     <group>
         <path
-                android:name="arrow"
-                android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-                android:fill="#ffffffff"
-                android:stroke="#FFFF0000"
-                android:strokeWidth="1"/>
+            android:name="arrow"
+            android:fill="#ffffffff"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="1" />
     </group>
-
     <group>
         <path
-                android:name="house"
-                android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-                android:fill="#ff440000"
-                android:stroke="#FFFF0000"
-                android:strokeWidth="10"
-                android:rotation="180"
-                android:pivotX="250"
-                android:pivotY="200"/>
+            android:name="house"
+            android:fill="#ff440000"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:pivotX="250"
+            android:pivotY="200"
+            android:rotation="180"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="10" />
     </group>
 
-    <animation android:sequence="arrow,house"/>
+    <animation android:sequence="arrow,house" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
index c9c8e8a..7e757a5 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable16.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,32 +16,31 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="200"
-          android:viewportHeight="200"/>
+    <viewport
+        android:viewportHeight="200"
+        android:viewportWidth="200" />
 
     <group>
         <path
-                android:name="arrow"
-                android:pathData="M 100,10 v 180 M 10,100 h 180"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="1"/>
+            android:name="arrow"
+            android:pathData="M 100,10 v 180 M 10,100 h 180"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="1" />
     </group>
-
     <group>
         <path
-                android:name="house"
-                android:pathData="M 100,10 v 90 M 10,100 h 90"
-                android:stroke="#FF00FF00"
-                android:strokeWidth="10"
-                android:rotation="360"
-                android:pivotX="100"
-                android:pivotY="100"/>
+            android:name="house"
+            android:pathData="M 100,10 v 90 M 10,100 h 90"
+            android:pivotX="100"
+            android:pivotY="100"
+            android:rotation="360"
+            android:stroke="#FF00FF00"
+            android:strokeWidth="10" />
     </group>
 
-    <animation android:sequence="arrow,house"/>
+    <animation android:sequence="arrow,house" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
index 83dfbd2..69212f5 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable18.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,31 +16,30 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="500"
-          android:viewportHeight="400"/>
+    <viewport
+        android:viewportHeight="400"
+        android:viewportWidth="500" />
 
     <group>
         <path
-                android:name="arrow"
-                android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-                android:stroke="#FFFFFF00"
-                android:strokeWidth="10"/>
+            android:name="arrow"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:stroke="#FFFFFF00"
+            android:strokeWidth="10" />
     </group>
-
     <group>
         <path
-                android:name="house"
-                android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
-                android:strokeWidth="10"
-                android:rotation="360"
-                android:pivotX="250"
-                android:pivotY="200"/>
+            android:name="house"
+            android:pathData="M100,200 C100,100 250,100 250,200 S400,300 400,200"
+            android:pivotX="250"
+            android:pivotY="200"
+            android:rotation="360"
+            android:strokeWidth="10" />
     </group>
 
-    <animation android:sequence="arrow,house"/>
+    <animation android:sequence="arrow,house" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
index 013254f..2dca48d 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable19.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,31 +16,30 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="1000"
-          android:viewportHeight="800"/>
+    <viewport
+        android:viewportHeight="800"
+        android:viewportWidth="1000" />
 
     <group>
         <path
-                android:name="arrow"
-                android:pathData="M10,300 Q400,50 600,300 T1000,300"
-                android:stroke="#FF00FFFF"
-                android:strokeWidth="40"/>
+            android:name="arrow"
+            android:pathData="M10,300 Q400,50 600,300 T1000,300"
+            android:stroke="#FF00FFFF"
+            android:strokeWidth="40" />
     </group>
-
     <group>
         <path
-                android:name="house"
-                android:pathData="M10,300 Q400,550 600,300 T1000,300"
-                android:stroke="#FFFF0000"
-                android:strokeWidth="60"
-                android:pivotX="90"
-                android:pivotY="100"/>
+            android:name="house"
+            android:pathData="M10,300 Q400,550 600,300 T1000,300"
+            android:pivotX="90"
+            android:pivotY="100"
+            android:stroke="#FFFF0000"
+            android:strokeWidth="60" />
     </group>
 
-    <animation android:sequence="arrow,house"/>
+    <animation android:sequence="arrow,house" />
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
index aba7e5f..b8af7e2 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_drawable20.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
@@ -15,23 +16,23 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
 
     <size
-            android:width="64dp"
-            android:height="64dp"/>
+        android:height="64dp"
+        android:width="64dp" />
 
-    <viewport android:viewportWidth="480"
-          android:viewportHeight="480"/>
+    <viewport
+        android:viewportHeight="480"
+        android:viewportWidth="480" />
 
     <group>
         <path
-                android:name="edit"
-                android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
+            android:name="edit"
+            android:fill="#FF00FFFF"
+            android:pathData="M406.667,180c0,0 -100 -100 -113.334 -113.333
     c-13.333 -13.334 -33.333,0 -33.333,0l-160,160c0,0 -40,153.333 -40,173.333c0,13.333,13.333,13.333,13.333,13.333l173.334 -40
     c0,0,146.666 -146.666,160 -160C420,200,406.667,180,406.667,180z M226.399,356.823L131.95,378.62l-38.516 -38.522
     c7.848 -34.675,20.152 -82.52,23.538 -95.593l3.027,2.162l106.667,106.666L226.399,356.823z"
-                android:stroke="#FF000000"
-                android:fill="#FF00FFFF"
-                android:strokeWidth="10"/>
+            android:stroke="#FF000000"
+            android:strokeWidth="10" />
     </group>
 
-
-</vector>
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
index 8897181..22ce795 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_create.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,17 +14,19 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="64dp"
-android:height="64dp"/>
 
-    <viewport android:viewportWidth="24"
-          android:viewportHeight="24"/>
+    <size
+        android:height="64dp"
+        android:width="64dp" />
 
-<group>
-<path
-     android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z"
-     android:fill="#FF000000"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="24"
+        android:viewportWidth="24" />
+
+    <group>
+        <path
+            android:fill="#FF000000"
+            android:pathData="M3.0,17.25L3.0,21.0l3.75,0.0L17.813995,9.936001l-3.75,-3.75L3.0,17.25zM20.707,7.0429993c0.391,-0.391 0.391,-1.023 0.0,-1.414l-2.336,-2.336c-0.391,-0.391 -1.023,-0.391 -1.414,0.0l-1.832,1.832l3.75,3.75L20.707,7.0429993z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
index 2c7ebbd..042173c 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_delete.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,17 +14,19 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="64dp"
-android:height="64dp"/>
 
-    <viewport android:viewportWidth="24"
-          android:viewportHeight="24"/>
+    <size
+        android:height="64dp"
+        android:width="64dp" />
 
-<group>
-<path
-     android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z"
-     android:fill="#FF000000"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="24"
+        android:viewportWidth="24" />
+
+    <group>
+        <path
+            android:fill="#FF000000"
+            android:pathData="M6.0,19.0c0.0,1.104 0.896,2.0 2.0,2.0l8.0,0.0c1.104,0.0 2.0,-0.896 2.0,-2.0l0.0,-12.0L6.0,7.0L6.0,19.0zM18.0,4.0l-2.5,0.0l-1.0,-1.0l-5.0,0.0l-1.0,1.0L6.0,4.0C5.4469986,4.0 5.0,4.4469986 5.0,5.0l0.0,1.0l14.0,0.0l0.0,-1.0C19.0,4.4469986 18.552002,4.0 18.0,4.0z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
index e4cf78c..6b6f43d 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_heart.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,17 +14,19 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="64dp"
-android:height="64dp"/>
 
-    <viewport android:viewportWidth="24"
-          android:viewportHeight="24"/>
+    <size
+        android:height="64dp"
+        android:width="64dp" />
 
-<group>
-<path
-     android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z"
-     android:fill="#FF000000"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="24"
+        android:viewportWidth="24" />
+
+    <group>
+        <path
+            android:fill="#FF000000"
+            android:pathData="M16.0,5.0c-1.955,0.0 -3.83,1.268 -4.5,3.0c-0.67,-1.732 -2.547,-3.0 -4.5,-3.0C4.4570007,5.0 2.5,6.931999 2.5,9.5c0.0,3.529 3.793,6.258 9.0,11.5c5.207,-5.242 9.0,-7.971 9.0,-11.5C20.5,6.931999 18.543,5.0 16.0,5.0z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
index cec12ba..ba8ebca 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_schedule.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,21 +14,22 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="64dp"
-android:height="64dp"/>
 
-    <viewport android:viewportWidth="24"
-          android:viewportHeight="24"/>
+    <size
+        android:height="64dp"
+        android:width="64dp" />
 
-<group>
-<path
-     android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z"
-          android:fillOpacity="0.9"
-     />
-<path
-     android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z"
-          android:fillOpacity="0.9"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="24"
+        android:viewportWidth="24" />
+
+    <group>
+        <path
+            android:fillOpacity="0.9"
+            android:pathData="M11.994999,2.0C6.4679985,2.0 2.0,6.4780006 2.0,12.0s4.468,10.0 9.995,10.0S22.0,17.522 22.0,12.0S17.521,2.0 11.994999,2.0zM12.0,20.0c-4.42,0.0 -8.0,-3.582 -8.0,-8.0s3.58,-8.0 8.0,-8.0s8.0,3.582 8.0,8.0S16.419998,20.0 12.0,20.0z" />
+        <path
+            android:fillOpacity="0.9"
+            android:pathData="M12.5,6.0l-1.5,0.0 0.0,7.0 5.3029995,3.1819992 0.75,-1.249999 -4.5529995,-2.7320004z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
index 5fe1fb6..896a938 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_icon_settings.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,17 +14,19 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="64dp"
-android:height="64dp"/>
 
-    <viewport android:viewportWidth="24"
-          android:viewportHeight="24"/>
+    <size
+        android:height="64dp"
+        android:width="64dp" />
 
-<group>
-<path
-     android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z"
-     android:fill="#FF000000"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="24"
+        android:viewportWidth="24" />
+
+    <group>
+        <path
+            android:fill="#FF000000"
+            android:pathData="M19.429,12.975998c0.042,-0.32 0.07,-0.645 0.07,-0.976s-0.029,-0.655 -0.07,-0.976l2.113,-1.654c0.188,-0.151 0.243,-0.422 0.118,-0.639l-2.0,-3.463c-0.125,-0.217 -0.386,-0.304 -0.612,-0.218l-2.49,1.004c-0.516,-0.396 -1.081,-0.731 -1.69,-0.984l-0.375,-2.648C14.456,2.1829987 14.25,2.0 14.0,2.0l-4.0,0.0C9.75,2.0 9.544,2.1829987 9.506,2.422001L9.131,5.0699997C8.521,5.322998 7.957,5.6570015 7.44,6.054001L4.952,5.0509987C4.726,4.965 4.464,5.052002 4.34,5.269001l-2.0,3.463C2.2150002,8.947998 2.27,9.219002 2.4580002,9.369999l2.112,1.653C4.528,11.344002 4.5,11.668999 4.5,12.0s0.029,0.656 0.071,0.977L2.4580002,14.630001c-0.188,0.151 -0.243,0.422 -0.118,0.639l2.0,3.463c0.125,0.217 0.386,0.304 0.612,0.218l2.489,-1.004c0.516,0.396 1.081,0.731 1.69,0.984l0.375,2.648C9.544,21.817001 9.75,22.0 10.0,22.0l4.0,0.0c0.25,0.0 0.456,-0.183 0.494,-0.422l0.375,-2.648c0.609,-0.253 1.174,-0.588 1.689,-0.984l2.49,1.004c0.226,0.086 0.487,-0.001 0.612,-0.218l2.0,-3.463c0.125,-0.217 0.07,-0.487 -0.118,-0.639L19.429,12.975998zM12.0,16.0c-2.21,0.0 -4.0,-1.791 -4.0,-4.0c0.0,-2.21 1.79,-4.0 4.0,-4.0c2.208,0.0 4.0,1.79 4.0,4.0C16.0,14.209 14.208,16.0 12.0,16.0z" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test01.xml b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
index 6beb9d8..a9091ab 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test01.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test01.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,19 +14,21 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="128dp"
-android:height="128dp"/>
 
-    <viewport android:viewportWidth="512"
-          android:viewportHeight="512"/>
+    <size
+        android:height="128dp"
+        android:width="128dp" />
 
-<group>
-<path
-     android:name="002b"
-     android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
-     android:stroke="#FF0000FF"
-     android:strokeWidth="4"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="512"
+        android:viewportWidth="512" />
+
+    <group>
+        <path
+            android:name="002b"
+            android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0t-200,299"
+            android:stroke="#FF0000FF"
+            android:strokeWidth="4" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VectorDrawableTest/res/drawable/vector_test02.xml b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
index 2c1a28e..ab58c06 100644
--- a/tests/VectorDrawableTest/res/drawable/vector_test02.xml
+++ b/tests/VectorDrawableTest/res/drawable/vector_test02.xml
@@ -1,4 +1,5 @@
-<!-- Copyright (C) 2014 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.
 You may obtain a copy of the License at"+
@@ -13,19 +14,21 @@
 limitations under the License.
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android" >
-<size
-android:width="128dp"
-android:height="128dp"/>
 
-    <viewport android:viewportWidth="512"
-          android:viewportHeight="512"/>
+    <size
+        android:height="128dp"
+        android:width="128dp" />
 
-<group>
-<path
-     android:name="002b"
-     android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
-     android:stroke="#FF0000FF"
-     android:strokeWidth="4"
-     />
-</group>
-</vector>
+    <viewport
+        android:viewportHeight="512"
+        android:viewportWidth="512" />
+
+    <group>
+        <path
+            android:name="002b"
+            android:pathData="M100,200c0,-100 150,-100 150,0s150,100 150,0T-200,299"
+            android:stroke="#FF0000FF"
+            android:strokeWidth="4" />
+    </group>
+
+</vector>
\ No newline at end of file
diff --git a/tests/VoiceInteraction/Android.mk b/tests/VoiceInteraction/Android.mk
new file mode 100644
index 0000000..8decca7
--- /dev/null
+++ b/tests/VoiceInteraction/Android.mk
@@ -0,0 +1,10 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := tests
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files)
+
+LOCAL_PACKAGE_NAME := VoiceInteraction
+
+include $(BUILD_PACKAGE)
diff --git a/tests/VoiceInteraction/AndroidManifest.xml b/tests/VoiceInteraction/AndroidManifest.xml
new file mode 100644
index 0000000..ac0f701
--- /dev/null
+++ b/tests/VoiceInteraction/AndroidManifest.xml
@@ -0,0 +1,33 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+        package="com.android.test.voiceinteraction">
+
+    <application>
+        <activity android:name="VoiceInteractionMain" android:label="Voice Interaction">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <service android:name="MainInteractionService"
+                android:permission="android.permission.BIND_VOICE_INTERACTION"
+                android:process=":interactor">
+            <meta-data android:name="android.voice_interaction"
+                       android:resource="@xml/interaction_service" />
+            <intent-filter>
+                <action android:name="android.service.voice.VoiceInteractionService" />
+            </intent-filter>
+        </service>
+        <service android:name="MainInteractionSessionService"
+                android:permission="android.permission.BIND_VOICE_INTERACTION"
+                android:process=":session">
+        </service>
+        <activity android:name="TestInteractionActivity" android:label="Voice Interaction Target">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.DEFAULT" />
+                <category android:name="android.intent.category.VOICE" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/tests/VoiceInteraction/res/layout/main.xml
similarity index 61%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to tests/VoiceInteraction/res/layout/main.xml
index 15d0890..3d7a418 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/tests/VoiceInteraction/res/layout/main.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,19 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    >
+
+    <Button android:id="@+id/start"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:text="@string/start"
+        />
+
+</LinearLayout>
+
+
diff --git a/tests/VoiceInteraction/res/layout/test_interaction.xml b/tests/VoiceInteraction/res/layout/test_interaction.xml
new file mode 100644
index 0000000..2abf65194
--- /dev/null
+++ b/tests/VoiceInteraction/res/layout/test_interaction.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    >
+
+    <TextView android:layout_width="wrap_content" android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="We are interacting!"
+        />
+
+    <TextView android:id="@+id/log"
+        android:layout_width="match_parent"
+        android:layout_height="0px"
+        android:layout_weight="1"
+        android:layout_marginTop="10dp"
+        android:textSize="12sp"
+        android:textColor="#ffffffff"
+        />
+
+</LinearLayout>
diff --git a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml b/tests/VoiceInteraction/res/values/strings.xml
similarity index 64%
copy from packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
copy to tests/VoiceInteraction/res/values/strings.xml
index 15d0890..12edb31 100644
--- a/packages/SystemUI/res/layout/notification_adaptive_wrapper.xml
+++ b/tests/VoiceInteraction/res/values/strings.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2012 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.
@@ -13,8 +13,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<SizeAdaptiveLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:background="@android:color/background_dark"
-    android:id="@+id/notification_adaptive_wrapper"
-    android:layout_width="match_parent"
-    android:layout_height="wrap_content" />
+
+<resources>
+
+    <string name="start">Start!</string>
+
+</resources>
+
diff --git a/tests/VoiceInteraction/res/xml/interaction_service.xml b/tests/VoiceInteraction/res/xml/interaction_service.xml
new file mode 100644
index 0000000..45bd994d
--- /dev/null
+++ b/tests/VoiceInteraction/res/xml/interaction_service.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * 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.
+ */
+-->
+
+<voice-interaction-service xmlns:android="http://schemas.android.com/apk/res/android"
+    android:sessionService="com.android.test.voiceinteraction.MainInteractionSessionService" />
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
new file mode 100644
index 0000000..008d97b
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionService.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.content.Intent;
+import android.service.voice.VoiceInteractionService;
+import android.util.Log;
+
+public class MainInteractionService extends VoiceInteractionService {
+    static final String TAG = "MainInteractionService";
+
+    @Override
+    public void onCreate() {
+        super.onCreate();
+        Log.i(TAG, "Creating " + this);
+    }
+
+    @Override
+    public int onStartCommand(Intent intent, int flags, int startId) {
+        startVoiceActivity(new Intent(this, TestInteractionActivity.class), null);
+        stopSelf(startId);
+        return START_NOT_STICKY;
+    }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
new file mode 100644
index 0000000..0fc563b
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSession.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.content.Context;
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.util.Log;
+
+public class MainInteractionSession extends VoiceInteractionSession {
+    static final String TAG = "MainInteractionSession";
+
+    final Bundle mArgs;
+
+    MainInteractionSession(Context context, Bundle args) {
+        super(context);
+        mArgs = args;
+    }
+
+    @Override
+    public boolean[] onGetSupportedCommands(Caller caller, String[] commands) {
+        return new boolean[commands.length];
+    }
+
+    @Override
+    public void onConfirm(Caller caller, Request request, String prompt, Bundle extras) {
+        Log.i(TAG, "onConform: prompt=" + prompt + " extras=" + extras);
+        request.sendConfirmResult(true, null);
+    }
+
+    @Override
+    public void onCommand(Caller caller, Request request, String command, Bundle extras) {
+        Log.i(TAG, "onCommand: command=" + command + " extras=" + extras);
+        request.sendCommandResult(true, null);
+    }
+
+    @Override
+    public void onCancel(Request request) {
+        Log.i(TAG, "onCancel");
+        request.sendCancelResult();
+    }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
new file mode 100644
index 0000000..8864d71
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/MainInteractionSessionService.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.os.Bundle;
+import android.service.voice.VoiceInteractionSession;
+import android.service.voice.VoiceInteractionSessionService;
+
+public class MainInteractionSessionService extends VoiceInteractionSessionService {
+    @Override
+    public VoiceInteractionSession onNewSession(Bundle args) {
+        return new MainInteractionSession(this, args);
+    }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
new file mode 100644
index 0000000..9c772ff
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/TestInteractionActivity.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.app.Activity;
+import android.app.VoiceInteractor;
+import android.os.Bundle;
+import android.util.Log;
+
+public class TestInteractionActivity extends Activity {
+    static final String TAG = "TestInteractionActivity";
+
+    VoiceInteractor mInteractor;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        if (!isVoiceInteraction()) {
+            Log.w(TAG, "Not running as a voice interaction!");
+            finish();
+            return;
+        }
+
+        setContentView(R.layout.test_interaction);
+
+        mInteractor = getVoiceInteractor();
+        VoiceInteractor.ConfirmationRequest req = new VoiceInteractor.ConfirmationRequest(
+                "This is a confirmation", null) {
+            @Override
+            public void onCancel() {
+                Log.i(TAG, "Canceled!");
+                getActivity().finish();
+            }
+
+            @Override
+            public void onConfirmationResult(boolean confirmed, Bundle result) {
+                Log.i(TAG, "Confirmation result: confirmed=" + confirmed + " result=" + result);
+                getActivity().finish();
+            }
+        };
+        mInteractor.submitRequest(req);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+    }
+}
diff --git a/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java
new file mode 100644
index 0000000..5d212a4
--- /dev/null
+++ b/tests/VoiceInteraction/src/com/android/test/voiceinteraction/VoiceInteractionMain.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.voiceinteraction;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.View;
+
+public class VoiceInteractionMain extends Activity {
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        setContentView(R.layout.main);
+        findViewById(R.id.start).setOnClickListener(mStartListener);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+    }
+
+    View.OnClickListener mStartListener = new View.OnClickListener() {
+        public void onClick(View v) {
+            startService(new Intent(VoiceInteractionMain.this, MainInteractionService.class));
+        }
+    };
+}
diff --git a/tools/aapt/Bundle.h b/tools/aapt/Bundle.h
index d2eccbe..ebe1bed 100644
--- a/tools/aapt/Bundle.h
+++ b/tools/aapt/Bundle.h
@@ -42,6 +42,15 @@
 } Command;
 
 /*
+ * Pseudolocalization methods
+ */
+typedef enum PseudolocalizationMethod {
+    NO_PSEUDOLOCALIZATION = 0,
+    PSEUDO_ACCENTED,
+    PSEUDO_BIDI,
+} PseudolocalizationMethod;
+
+/*
  * Bundle of goodies, including everything specified on the command line.
  */
 class Bundle {
@@ -50,7 +59,7 @@
         : mCmd(kCommandUnknown), mVerbose(false), mAndroidList(false),
           mForce(false), mGrayscaleTolerance(0), mMakePackageDirs(false),
           mUpdate(false), mExtending(false),
-          mRequireLocalization(false), mPseudolocalize(false),
+          mRequireLocalization(false), mPseudolocalize(NO_PSEUDOLOCALIZATION),
           mWantUTF16(false), mValues(false), mIncludeMetaData(false),
           mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
           mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
@@ -95,8 +104,8 @@
     void setExtending(bool val) { mExtending = val; }
     bool getRequireLocalization(void) const { return mRequireLocalization; }
     void setRequireLocalization(bool val) { mRequireLocalization = val; }
-    bool getPseudolocalize(void) const { return mPseudolocalize; }
-    void setPseudolocalize(bool val) { mPseudolocalize = val; }
+    short getPseudolocalize(void) const { return mPseudolocalize; }
+    void setPseudolocalize(short val) { mPseudolocalize = val; }
     void setWantUTF16(bool val) { mWantUTF16 = val; }
     bool getValues(void) const { return mValues; }
     void setValues(bool val) { mValues = val; }
@@ -259,7 +268,7 @@
     bool        mUpdate;
     bool        mExtending;
     bool        mRequireLocalization;
-    bool        mPseudolocalize;
+    short       mPseudolocalize;
     bool        mWantUTF16;
     bool        mValues;
     bool        mIncludeMetaData;
diff --git a/tools/aapt/Command.cpp b/tools/aapt/Command.cpp
index 44b8340..0af1ce1 100644
--- a/tools/aapt/Command.cpp
+++ b/tools/aapt/Command.cpp
@@ -2048,14 +2048,17 @@
     FILE* fp;
     String8 dependencyFile;
 
-    // -c zz_ZZ means do pseudolocalization
+    // -c en_XA or/and ar_XB means do pseudolocalization
     ResourceFilter filter;
     err = filter.parse(bundle->getConfigurations());
     if (err != NO_ERROR) {
         goto bail;
     }
     if (filter.containsPseudo()) {
-        bundle->setPseudolocalize(true);
+        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_ACCENTED);
+    }
+    if (filter.containsPseudoBidi()) {
+        bundle->setPseudolocalize(bundle->getPseudolocalize() | PSEUDO_BIDI);
     }
 
     N = bundle->getFileSpecCount();
diff --git a/tools/aapt/Resource.cpp b/tools/aapt/Resource.cpp
index 6d9d62e..d0581f6 100644
--- a/tools/aapt/Resource.cpp
+++ b/tools/aapt/Resource.cpp
@@ -2462,7 +2462,7 @@
 
 status_t
 writeProguardForXml(ProguardKeepSet* keep, const sp<AaptFile>& layoutFile,
-        const char* startTag, const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs)
+        const Vector<String8>& startTags, const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs)
 {
     status_t err;
     ResXMLTree tree;
@@ -2476,15 +2476,18 @@
 
     tree.restart();
 
-    if (startTag != NULL) {
+    if (!startTags.isEmpty()) {
         bool haveStart = false;
         while ((code=tree.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
             if (code != ResXMLTree::START_TAG) {
                 continue;
             }
             String8 tag(tree.getElementName(&len));
-            if (tag == startTag) {
-                haveStart = true;
+            const size_t numStartTags = startTags.size();
+            for (size_t i = 0; i < numStartTags; i++) {
+                if (tag == startTags[i]) {
+                    haveStart = true;
+                }
             }
             break;
         }
@@ -2571,15 +2574,17 @@
     for (size_t k=0; k<K; k++) {
         const sp<AaptDir>& d = dirs.itemAt(k);
         const String8& dirName = d->getLeaf();
+        Vector<String8> startTags;
         const char* startTag = NULL;
         const KeyedVector<String8, Vector<NamespaceAttributePair> >* tagAttrPairs = NULL;
         if ((dirName == String8("layout")) || (strncmp(dirName.string(), "layout-", 7) == 0)) {
             tagAttrPairs = &kLayoutTagAttrPairs;
         } else if ((dirName == String8("xml")) || (strncmp(dirName.string(), "xml-", 4) == 0)) {
-            startTag = "PreferenceScreen";
+            startTags.add(String8("PreferenceScreen"));
+            startTags.add(String8("preference-headers"));
             tagAttrPairs = &kXmlTagAttrPairs;
         } else if ((dirName == String8("menu")) || (strncmp(dirName.string(), "menu-", 5) == 0)) {
-            startTag = "menu";
+            startTags.add(String8("menu"));
             tagAttrPairs = NULL;
         } else {
             continue;
@@ -2592,7 +2597,7 @@
             const DefaultKeyedVector<AaptGroupEntry, sp<AaptFile> >& files = group->getFiles();
             const size_t M = files.size();
             for (size_t j=0; j<M; j++) {
-                err = writeProguardForXml(keep, files.valueAt(j), startTag, tagAttrPairs);
+                err = writeProguardForXml(keep, files.valueAt(j), startTags, tagAttrPairs);
                 if (err < 0) {
                     return err;
                 }
diff --git a/tools/aapt/ResourceFilter.cpp b/tools/aapt/ResourceFilter.cpp
index e8a2be4..8ca852e 100644
--- a/tools/aapt/ResourceFilter.cpp
+++ b/tools/aapt/ResourceFilter.cpp
@@ -24,8 +24,10 @@
 
         String8 part(p, q-p);
 
-        if (part == "zz_ZZ") {
-            mContainsPseudo = true;
+        if (part == "en_XA") {
+            mContainsPseudoAccented = true;
+        } else if (part == "ar_XB") {
+            mContainsPseudoBidi = true;
         }
         int axis;
         AxisValue value;
diff --git a/tools/aapt/ResourceFilter.h b/tools/aapt/ResourceFilter.h
index 0d127ba..c57770e 100644
--- a/tools/aapt/ResourceFilter.h
+++ b/tools/aapt/ResourceFilter.h
@@ -16,19 +16,22 @@
 class ResourceFilter
 {
 public:
-    ResourceFilter() : mData(), mContainsPseudo(false) {}
+    ResourceFilter() : mData(), mContainsPseudoAccented(false),
+        mContainsPseudoBidi(false) {}
     status_t parse(const char* arg);
     bool isEmpty() const;
     bool match(int axis, const ResTable_config& config) const;
     bool match(const ResTable_config& config) const;
     const SortedVector<AxisValue>* configsForAxis(int axis) const;
-    inline bool containsPseudo() const { return mContainsPseudo; }
+    inline bool containsPseudo() const { return mContainsPseudoAccented; }
+    inline bool containsPseudoBidi() const { return mContainsPseudoBidi; }
 
 private:
     bool match(int axis, const AxisValue& value) const;
 
     KeyedVector<int,SortedVector<AxisValue> > mData;
-    bool mContainsPseudo;
+    bool mContainsPseudoAccented;
+    bool mContainsPseudoBidi;
 };
 
 #endif
diff --git a/tools/aapt/ResourceTable.cpp b/tools/aapt/ResourceTable.cpp
index 0fb2606..b445b8a 100644
--- a/tools/aapt/ResourceTable.cpp
+++ b/tools/aapt/ResourceTable.cpp
@@ -25,7 +25,7 @@
     if (root == NULL) {
         return UNKNOWN_ERROR;
     }
-    
+
     return compileXmlFile(assets, root, target, table, options);
 }
 
@@ -577,13 +577,13 @@
                         int32_t curFormat,
                         bool isFormatted,
                         const String16& product,
-                        bool pseudolocalize,
+                        PseudolocalizationMethod pseudolocalize,
                         const bool overwrite,
                         ResourceTable* outTable)
 {
     status_t err;
     const String16 item16("item");
-    
+
     String16 str;
     Vector<StringPool::entry_style_span> spans;
     err = parseStyledString(bundle, in->getPrintableSource().string(),
@@ -672,7 +672,7 @@
                         int32_t curFormat,
                         bool isFormatted,
                         const String16& product,
-                        bool pseudolocalize,
+                        PseudolocalizationMethod pseudolocalize,
                         const bool overwrite,
                         KeyedVector<type_ident_pair_t, bool>* skippedResourceNames,
                         ResourceTable* outTable)
@@ -854,10 +854,16 @@
     ResTable_config curParams(defParams);
 
     ResTable_config pseudoParams(curParams);
-        pseudoParams.language[0] = 'z';
-        pseudoParams.language[1] = 'z';
-        pseudoParams.country[0] = 'Z';
-        pseudoParams.country[1] = 'Z';
+        pseudoParams.language[0] = 'e';
+        pseudoParams.language[1] = 'n';
+        pseudoParams.country[0] = 'X';
+        pseudoParams.country[1] = 'A';
+
+    ResTable_config pseudoBidiParams(curParams);
+        pseudoBidiParams.language[0] = 'a';
+        pseudoBidiParams.language[1] = 'r';
+        pseudoBidiParams.country[0] = 'X';
+        pseudoBidiParams.country[1] = 'B';
 
     while ((code=block.next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
         if (code == ResXMLTree::START_TAG) {
@@ -1345,7 +1351,7 @@
                 curType = string16;
                 curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
                 curIsStyled = true;
-                curIsPseudolocalizable = (translatable != false16);
+                curIsPseudolocalizable = fileIsTranslatable && (translatable != false16);
             } else if (strcmp16(block.getElementName(&len), drawable16.string()) == 0) {
                 curTag = &drawable16;
                 curType = drawable16;
@@ -1389,6 +1395,7 @@
                 curTag = &plurals16;
                 curType = plurals16;
                 curIsBag = true;
+                curIsPseudolocalizable = fileIsTranslatable;
             } else if (strcmp16(block.getElementName(&len), array16.string()) == 0) {
                 curTag = &array16;
                 curType = array16;
@@ -1410,26 +1417,24 @@
             } else if (strcmp16(block.getElementName(&len), string_array16.string()) == 0) {
                 // Check whether these strings need valid formats.
                 // (simplified form of what string16 does above)
+                bool isTranslatable = false;
                 size_t n = block.getAttributeCount();
 
                 // Pseudolocalizable by default, unless this string array isn't
                 // translatable.
-                curIsPseudolocalizable = true;
                 for (size_t i = 0; i < n; i++) {
                     size_t length;
                     const uint16_t* attr = block.getAttributeName(i, &length);
-                    if (strcmp16(attr, translatable16.string()) == 0) {
-                        const uint16_t* value = block.getAttributeStringValue(i, &length);
-                        if (strcmp16(value, false16.string()) == 0) {
-                            curIsPseudolocalizable = false;
-                        }
-                    }
-
                     if (strcmp16(attr, formatted16.string()) == 0) {
                         const uint16_t* value = block.getAttributeStringValue(i, &length);
                         if (strcmp16(value, false16.string()) == 0) {
                             curIsFormatted = false;
                         }
+                    } else if (strcmp16(attr, translatable16.string()) == 0) {
+                        const uint16_t* value = block.getAttributeStringValue(i, &length);
+                        if (strcmp16(value, false16.string()) == 0) {
+                            isTranslatable = false;
+                        }
                     }
                 }
 
@@ -1438,6 +1443,7 @@
                 curFormat = ResTable_map::TYPE_REFERENCE|ResTable_map::TYPE_STRING;
                 curIsBag = true;
                 curIsBagReplaceOnOverwrite = true;
+                curIsPseudolocalizable = isTranslatable && fileIsTranslatable;
             } else if (strcmp16(block.getElementName(&len), integer_array16.string()) == 0) {
                 curTag = &integer_array16;
                 curType = array16;
@@ -1559,19 +1565,29 @@
 
                         err = parseAndAddBag(bundle, in, &block, curParams, myPackage, curType,
                                 ident, parentIdent, itemIdent, curFormat, curIsFormatted,
-                                product, false, overwrite, outTable);
+                                product, NO_PSEUDOLOCALIZATION, overwrite, outTable);
                         if (err == NO_ERROR) {
                             if (curIsPseudolocalizable && localeIsDefined(curParams)
-                                    && bundle->getPseudolocalize()) {
+                                    && bundle->getPseudolocalize() > 0) {
                                 // pseudolocalize here
-#if 1
-                                block.setPosition(parserPosition);
-                                err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
-                                        curType, ident, parentIdent, itemIdent, curFormat,
-                                        curIsFormatted, product, true, overwrite, outTable);
-#endif
+                                if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
+                                   PSEUDO_ACCENTED) {
+                                    block.setPosition(parserPosition);
+                                    err = parseAndAddBag(bundle, in, &block, pseudoParams, myPackage,
+                                            curType, ident, parentIdent, itemIdent, curFormat,
+                                            curIsFormatted, product, PSEUDO_ACCENTED,
+                                            overwrite, outTable);
+                                }
+                                if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
+                                   PSEUDO_BIDI) {
+                                    block.setPosition(parserPosition);
+                                    err = parseAndAddBag(bundle, in, &block, pseudoBidiParams, myPackage,
+                                            curType, ident, parentIdent, itemIdent, curFormat,
+                                            curIsFormatted, product, PSEUDO_BIDI,
+                                            overwrite, outTable);
+                                }
                             }
-                        } 
+                        }
                         if (err != NO_ERROR) {
                             hasErrors = localHasErrors = true;
                         }
@@ -1592,20 +1608,31 @@
 
                 err = parseAndAddEntry(bundle, in, &block, curParams, myPackage, curType, ident,
                         *curTag, curIsStyled, curFormat, curIsFormatted,
-                        product, false, overwrite, &skippedResourceNames, outTable);
+                        product, NO_PSEUDOLOCALIZATION, overwrite, &skippedResourceNames, outTable);
 
                 if (err < NO_ERROR) { // Why err < NO_ERROR instead of err != NO_ERROR?
                     hasErrors = localHasErrors = true;
                 }
                 else if (err == NO_ERROR) {
                     if (curIsPseudolocalizable && localeIsDefined(curParams)
-                            && bundle->getPseudolocalize()) {
+                            && bundle->getPseudolocalize() > 0) {
                         // pseudolocalize here
-                        block.setPosition(parserPosition);
-                        err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
-                                ident, *curTag, curIsStyled, curFormat,
-                                curIsFormatted, product,
-                                true, overwrite, &skippedResourceNames, outTable);
+                        if ((PSEUDO_ACCENTED & bundle->getPseudolocalize()) ==
+                           PSEUDO_ACCENTED) {
+                            block.setPosition(parserPosition);
+                            err = parseAndAddEntry(bundle, in, &block, pseudoParams, myPackage, curType,
+                                    ident, *curTag, curIsStyled, curFormat,
+                                    curIsFormatted, product,
+                                    PSEUDO_ACCENTED, overwrite, &skippedResourceNames, outTable);
+                        }
+                        if ((PSEUDO_BIDI & bundle->getPseudolocalize()) ==
+                           PSEUDO_BIDI) {
+                            block.setPosition(parserPosition);
+                            err = parseAndAddEntry(bundle, in, &block, pseudoBidiParams,
+                                    myPackage, curType, ident, *curTag, curIsStyled, curFormat,
+                                    curIsFormatted, product,
+                                    PSEUDO_BIDI, overwrite, &skippedResourceNames, outTable);
+                        }
                         if (err != NO_ERROR) {
                             hasErrors = localHasErrors = true;
                         }
@@ -2637,8 +2664,8 @@
                     continue;
                 }
 
-                // don't bother with the pseudolocale "zz_ZZ"
-                if (config != "zz_ZZ") {
+                // don't bother with the pseudolocale "en_XA" or "ar_XB"
+                if (config != "en_XA" && config != "ar_XB") {
                     if (configSrcMap.find(config) == configSrcMap.end()) {
                         // okay, no specific localization found.  it's possible that we are
                         // requiring a specific regional localization [e.g. de_DE] but there is an
diff --git a/tools/aapt/XMLNode.cpp b/tools/aapt/XMLNode.cpp
index a663ad5..607d419 100644
--- a/tools/aapt/XMLNode.cpp
+++ b/tools/aapt/XMLNode.cpp
@@ -187,7 +187,7 @@
                            String16* outString,
                            Vector<StringPool::entry_style_span>* outSpans,
                            bool isFormatted,
-                           bool pseudolocalize)
+                           PseudolocalizationMethod pseudolocalize)
 {
     Vector<StringPool::entry_style_span> spanStack;
     String16 curString;
@@ -198,21 +198,30 @@
 
     size_t len;
     ResXMLTree::event_code_t code;
+    // Bracketing if pseudolocalization accented method specified.
+    if (pseudolocalize == PSEUDO_ACCENTED) {
+        curString.append(String16(String8("[")));
+    }
     while ((code=inXml->next()) != ResXMLTree::END_DOCUMENT && code != ResXMLTree::BAD_DOCUMENT) {
-
         if (code == ResXMLTree::TEXT) {
             String16 text(inXml->getText(&len));
             if (firstTime && text.size() > 0) {
                 firstTime = false;
                 if (text.string()[0] == '@') {
                     // If this is a resource reference, don't do the pseudoloc.
-                    pseudolocalize = false;
+                    pseudolocalize = NO_PSEUDOLOCALIZATION;
                 }
             }
-            if (xliffDepth == 0 && pseudolocalize) {
-                std::string orig(String8(text).string());
-                std::string pseudo = pseudolocalize_string(orig);
-                curString.append(String16(String8(pseudo.c_str())));
+            if (xliffDepth == 0 && pseudolocalize > 0) {
+                String16 pseudo;
+                if (pseudolocalize == PSEUDO_ACCENTED) {
+                    pseudo = pseudolocalize_string(text);
+                } else if (pseudolocalize == PSEUDO_BIDI) {
+                    pseudo = pseudobidi_string(text);
+                } else {
+                    pseudo = text;
+                }
+                curString.append(pseudo);
             } else {
                 if (isFormatted && hasSubstitutionErrors(fileName, inXml, text) != NO_ERROR) {
                     return UNKNOWN_ERROR;
@@ -352,6 +361,25 @@
         }
     }
 
+    // Bracketing if pseudolocalization accented method specified.
+    if (pseudolocalize == PSEUDO_ACCENTED) {
+        const char16_t* str = outString->string();
+        const char16_t* p = str;
+        const char16_t* e = p + outString->size();
+        int words_cnt = 0;
+        while (p < e) {
+            if (isspace(*p)) {
+                words_cnt++;
+            }
+            p++;
+        }
+        unsigned int length = words_cnt > 3 ? outString->size() :
+            outString->size() / 2;
+        curString.append(String16(String8(" ")));
+        curString.append(pseudo_generate_expansion(length));
+        curString.append(String16(String8("]")));
+    }
+
     if (code == ResXMLTree::BAD_DOCUMENT) {
             SourcePos(String8(fileName), inXml->getLineNumber()).error(
                     "Error parsing XML\n");
diff --git a/tools/aapt/XMLNode.h b/tools/aapt/XMLNode.h
index 05624b7..ccbf9f4 100644
--- a/tools/aapt/XMLNode.h
+++ b/tools/aapt/XMLNode.h
@@ -26,7 +26,7 @@
                            String16* outString,
                            Vector<StringPool::entry_style_span>* outSpans,
                            bool isFormatted,
-                           bool isPseudolocalizable);
+                           PseudolocalizationMethod isPseudolocalizable);
 
 void printXMLBlock(ResXMLTree* block);
 
diff --git a/tools/aapt/pseudolocalize.cpp b/tools/aapt/pseudolocalize.cpp
index 9e50c5a..60aa2b2 100644
--- a/tools/aapt/pseudolocalize.cpp
+++ b/tools/aapt/pseudolocalize.cpp
@@ -2,89 +2,155 @@
 
 using namespace std;
 
+// String basis to generate expansion
+static const String16 k_expansion_string = String16("one two three "
+    "four five six seven eight nine ten eleven twelve thirteen "
+    "fourteen fiveteen sixteen seventeen nineteen twenty");
+
+// Special unicode characters to override directionality of the words
+static const String16 k_rlm = String16("\xe2\x80\x8f");
+static const String16 k_rlo = String16("\xE2\x80\xae");
+static const String16 k_pdf = String16("\xE2\x80\xac");
+
+// Placeholder marks
+static const String16 k_placeholder_open = String16("\xc2\xbb");
+static const String16 k_placeholder_close = String16("\xc2\xab");
+
 static const char*
-pseudolocalize_char(char c)
+pseudolocalize_char(const char16_t c)
 {
     switch (c) {
-        case 'a':   return "\xc4\x83";
-        case 'b':   return "\xcf\x84";
-        case 'c':   return "\xc4\x8b";
-        case 'd':   return "\xc4\x8f";
-        case 'e':   return "\xc4\x99";
+        case 'a':   return "\xc3\xa5";
+        case 'b':   return "\xc9\x93";
+        case 'c':   return "\xc3\xa7";
+        case 'd':   return "\xc3\xb0";
+        case 'e':   return "\xc3\xa9";
         case 'f':   return "\xc6\x92";
         case 'g':   return "\xc4\x9d";
-        case 'h':   return "\xd1\x9b";
-        case 'i':   return "\xcf\x8a";
+        case 'h':   return "\xc4\xa5";
+        case 'i':   return "\xc3\xae";
         case 'j':   return "\xc4\xb5";
-        case 'k':   return "\xc4\xb8";
-        case 'l':   return "\xc4\xba";
+        case 'k':   return "\xc4\xb7";
+        case 'l':   return "\xc4\xbc";
         case 'm':   return "\xe1\xb8\xbf";
-        case 'n':   return "\xd0\xb8";
-        case 'o':   return "\xcf\x8c";
-        case 'p':   return "\xcf\x81";
+        case 'n':   return "\xc3\xb1";
+        case 'o':   return "\xc3\xb6";
+        case 'p':   return "\xc3\xbe";
         case 'q':   return "\x51";
-        case 'r':   return "\xd2\x91";
+        case 'r':   return "\xc5\x95";
         case 's':   return "\xc5\xa1";
-        case 't':   return "\xd1\x82";
-        case 'u':   return "\xce\xb0";
+        case 't':   return "\xc5\xa3";
+        case 'u':   return "\xc3\xbb";
         case 'v':   return "\x56";
-        case 'w':   return "\xe1\xba\x85";
+        case 'w':   return "\xc5\xb5";
         case 'x':   return "\xd1\x85";
-        case 'y':   return "\xe1\xbb\xb3";
-        case 'z':   return "\xc5\xba";
+        case 'y':   return "\xc3\xbd";
+        case 'z':   return "\xc5\xbe";
         case 'A':   return "\xc3\x85";
         case 'B':   return "\xce\xb2";
-        case 'C':   return "\xc4\x88";
-        case 'D':   return "\xc4\x90";
-        case 'E':   return "\xd0\x84";
-        case 'F':   return "\xce\x93";
-        case 'G':   return "\xc4\x9e";
-        case 'H':   return "\xc4\xa6";
-        case 'I':   return "\xd0\x87";
-        case 'J':   return "\xc4\xb5";
+        case 'C':   return "\xc3\x87";
+        case 'D':   return "\xc3\x90";
+        case 'E':   return "\xc3\x89";
+        case 'G':   return "\xc4\x9c";
+        case 'H':   return "\xc4\xa4";
+        case 'I':   return "\xc3\x8e";
+        case 'J':   return "\xc4\xb4";
         case 'K':   return "\xc4\xb6";
-        case 'L':   return "\xc5\x81";
+        case 'L':   return "\xc4\xbb";
         case 'M':   return "\xe1\xb8\xbe";
-        case 'N':   return "\xc5\x83";
-        case 'O':   return "\xce\x98";
-        case 'P':   return "\xcf\x81";
+        case 'N':   return "\xc3\x91";
+        case 'O':   return "\xc3\x96";
+        case 'P':   return "\xc3\x9e";
         case 'Q':   return "\x71";
-        case 'R':   return "\xd0\xaf";
-        case 'S':   return "\xc8\x98";
-        case 'T':   return "\xc5\xa6";
-        case 'U':   return "\xc5\xa8";
+        case 'R':   return "\xc5\x94";
+        case 'S':   return "\xc5\xa0";
+        case 'T':   return "\xc5\xa2";
+        case 'U':   return "\xc3\x9b";
         case 'V':   return "\xce\xbd";
-        case 'W':   return "\xe1\xba\x84";
+        case 'W':   return "\xc5\xb4";
         case 'X':   return "\xc3\x97";
-        case 'Y':   return "\xc2\xa5";
+        case 'Y':   return "\xc3\x9d";
         case 'Z':   return "\xc5\xbd";
+        case '!':   return "\xc2\xa1";
+        case '?':   return "\xc2\xbf";
+        case '$':   return "\xe2\x82\xac";
         default:    return NULL;
     }
 }
 
+static bool
+is_possible_normal_placeholder_end(const char16_t c) {
+    switch (c) {
+        case 's': return true;
+        case 'S': return true;
+        case 'c': return true;
+        case 'C': return true;
+        case 'd': return true;
+        case 'o': return true;
+        case 'x': return true;
+        case 'X': return true;
+        case 'f': return true;
+        case 'e': return true;
+        case 'E': return true;
+        case 'g': return true;
+        case 'G': return true;
+        case 'a': return true;
+        case 'A': return true;
+        case 'b': return true;
+        case 'B': return true;
+        case 'h': return true;
+        case 'H': return true;
+        case '%': return true;
+        case 'n': return true;
+        default:  return false;
+    }
+}
+
+String16
+pseudo_generate_expansion(const unsigned int length) {
+    String16 result = k_expansion_string;
+    const char16_t* s = result.string();
+    if (result.size() < length) {
+        result += String16(" ");
+        result += pseudo_generate_expansion(length - result.size());
+    } else {
+        int ext = 0;
+        // Should contain only whole words, so looking for a space
+        for (unsigned int i = length + 1; i < result.size(); ++i) {
+          ++ext;
+          if (s[i] == ' ') {
+            break;
+          }
+        }
+        result.remove(length + ext, 0);
+    }
+    return result;
+}
+
 /**
  * Converts characters so they look like they've been localized.
  *
  * Note: This leaves escape sequences untouched so they can later be
  * processed by ResTable::collectString in the normal way.
  */
-string
-pseudolocalize_string(const string& source)
+String16
+pseudolocalize_string(const String16& source)
 {
-    const char* s = source.c_str();
-    string result;
-    const size_t I = source.length();
+    const char16_t* s = source.string();
+    String16 result;
+    const size_t I = source.size();
     for (size_t i=0; i<I; i++) {
-        char c = s[i];
+        char16_t c = s[i];
         if (c == '\\') {
+            // Escape syntax, no need to pseudolocalize
             if (i<I-1) {
-                result += '\\';
+                result += String16("\\");
                 i++;
                 c = s[i];
                 switch (c) {
                     case 'u':
                         // this one takes up 5 chars
-                        result += string(s+i, 5);
+                        result += String16(s+i, 5);
                         i += 4;
                         break;
                     case 't':
@@ -96,24 +162,107 @@
                     case '\'':
                     case '\\':
                     default:
-                        result += c;
+                        result.append(&c, 1);
                         break;
                 }
             } else {
-                result += c;
+                result.append(&c, 1);
+            }
+        } else if (c == '%') {
+            // Placeholder syntax, no need to pseudolocalize
+            result += k_placeholder_open;
+            bool end = false;
+            result.append(&c, 1);
+            while (!end && i < I) {
+                ++i;
+                c = s[i];
+                result.append(&c, 1);
+                if (is_possible_normal_placeholder_end(c)) {
+                    end = true;
+                } else if (c == 't') {
+                    ++i;
+                    c = s[i];
+                    result.append(&c, 1);
+                    end = true;
+                }
+            }
+            result += k_placeholder_close;
+        } else if (c == '<' || c == '&') {
+            // html syntax, no need to pseudolocalize
+            bool tag_closed = false;
+            while (!tag_closed && i < I) {
+                if (c == '&') {
+                    String16 escape_text;
+                    escape_text.append(&c, 1);
+                    bool end = false;
+                    size_t htmlCodePos = i;
+                    while (!end && htmlCodePos < I) {
+                        ++htmlCodePos;
+                        c = s[htmlCodePos];
+                        escape_text.append(&c, 1);
+                        // Valid html code
+                        if (c == ';') {
+                            end = true;
+                            i = htmlCodePos;
+                        }
+                        // Wrong html code
+                        else if (!((c == '#' ||
+                                 (c >= 'a' && c <= 'z') ||
+                                 (c >= 'A' && c <= 'Z') ||
+                                 (c >= '0' && c <= '9')))) {
+                            end = true;
+                        }
+                    }
+                    result += escape_text;
+                    if (escape_text != String16("&lt;")) {
+                        tag_closed = true;
+                    }
+                    continue;
+                }
+                if (c == '>') {
+                    tag_closed = true;
+                    result.append(&c, 1);
+                    continue;
+                }
+                result.append(&c, 1);
+                i++;
+                c = s[i];
             }
         } else {
+            // This is a pure text that should be pseudolocalized
             const char* p = pseudolocalize_char(c);
             if (p != NULL) {
-                result += p;
+                result += String16(p);
             } else {
-                result += c;
+                result.append(&c, 1);
             }
         }
     }
-
-    //printf("result=\'%s\'\n", result.c_str());
     return result;
 }
 
+String16
+pseudobidi_string(const String16& source)
+{
+    const char16_t* s = source.string();
+    String16 result;
+    result += k_rlm;
+    result += k_rlo;
+    for (size_t i=0; i<source.size(); i++) {
+        char16_t c = s[i];
+        switch(c) {
+            case ' ': result += k_pdf;
+                      result += k_rlm;
+                      result.append(&c, 1);
+                      result += k_rlm;
+                      result += k_rlo;
+                      break;
+            default: result.append(&c, 1);
+                     break;
+        }
+    }
+    result += k_pdf;
+    result += k_rlm;
+    return result;
+}
 
diff --git a/tools/aapt/pseudolocalize.h b/tools/aapt/pseudolocalize.h
index 94cb034..e6ab18e 100644
--- a/tools/aapt/pseudolocalize.h
+++ b/tools/aapt/pseudolocalize.h
@@ -1,9 +1,18 @@
 #ifndef HOST_PSEUDOLOCALIZE_H
 #define HOST_PSEUDOLOCALIZE_H
 
+#include "StringPool.h"
+
 #include <string>
 
-std::string pseudolocalize_string(const std::string& source);
+String16 pseudolocalize_string(const String16& source);
+// Surrounds every word in the sentance with specific characters that makes
+// the word directionality RTL.
+String16 pseudobidi_string(const String16& source);
+// Generates expansion string based on the specified lenght.
+// Generated string could not be shorter that length, but it could be slightly
+// longer.
+String16 pseudo_generate_expansion(const unsigned int length);
 
 #endif // HOST_PSEUDOLOCALIZE_H
 
diff --git a/tools/layoutlib/bridge/resources/bars/action_bar.xml b/tools/layoutlib/bridge/resources/bars/action_bar.xml
deleted file mode 100644
index 7adc5af..0000000
--- a/tools/layoutlib/bridge/resources/bars/action_bar.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-    <include layout="@android:layout/action_bar_home" />
-    <TextView
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"/>
-</merge>
diff --git a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
index ebfe9bc..8862f5b 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Matrix_Delegate.java
@@ -355,227 +355,162 @@
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_setConcat(long native_object, long a, long b) {
+    /*package*/ static void native_setConcat(long native_object, long a, long b) {
         if (a == native_object) {
-            return native_preConcat(native_object, b);
+            native_preConcat(native_object, b);
+            return;
         } else if (b == native_object) {
-            return native_postConcat(native_object, a);
+            native_postConcat(native_object, a);
+            return;
         }
 
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
-        }
-
         Matrix_Delegate a_mtx = sManager.getDelegate(a);
-        if (a_mtx == null) {
-            return false;
-        }
-
         Matrix_Delegate b_mtx = sManager.getDelegate(b);
-        if (b_mtx == null) {
-            return false;
+        if (d != null && a_mtx != null && b_mtx != null) {
+            multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
         }
-
-        multiply(d.mValues, a_mtx.mValues, b_mtx.mValues);
-
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preTranslate(long native_object, float dx, float dy) {
+    /*package*/ static void native_preTranslate(long native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getTranslate(dx, dy));
         }
-
-        d.preTransform(getTranslate(dx, dy));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preScale(long native_object, float sx, float sy,
+    /*package*/ static void native_preScale(long native_object, float sx, float sy,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getScale(sx, sy, px, py));
         }
-
-        d.preTransform(getScale(sx, sy, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preScale(long native_object, float sx, float sy) {
+    /*package*/ static void native_preScale(long native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getScale(sx, sy));
         }
-
-        d.preTransform(getScale(sx, sy));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preRotate(long native_object, float degrees,
+    /*package*/ static void native_preRotate(long native_object, float degrees,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getRotate(degrees, px, py));
         }
-
-        d.preTransform(getRotate(degrees, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preRotate(long native_object, float degrees) {
+    /*package*/ static void native_preRotate(long native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+
+            double rad = Math.toRadians(degrees);
+            float sin = (float) Math.sin(rad);
+            float cos = (float) Math.cos(rad);
+
+            d.preTransform(getRotate(sin, cos));
         }
-
-        double rad = Math.toRadians(degrees);
-        float sin = (float)Math.sin(rad);
-        float cos = (float)Math.cos(rad);
-
-        d.preTransform(getRotate(sin, cos));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky,
+    /*package*/ static void native_preSkew(long native_object, float kx, float ky,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getSkew(kx, ky, px, py));
         }
-
-        d.preTransform(getSkew(kx, ky, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preSkew(long native_object, float kx, float ky) {
+    /*package*/ static void native_preSkew(long native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.preTransform(getSkew(kx, ky));
         }
-
-        d.preTransform(getSkew(kx, ky));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_preConcat(long native_object, long other_matrix) {
+    /*package*/ static void native_preConcat(long native_object, long other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
-        }
-
         Matrix_Delegate other = sManager.getDelegate(other_matrix);
-        if (other == null) {
-            return false;
+        if (d != null && other != null) {
+            d.preTransform(other.mValues);
         }
-
-        d.preTransform(other.mValues);
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postTranslate(long native_object, float dx, float dy) {
+    /*package*/ static void native_postTranslate(long native_object, float dx, float dy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getTranslate(dx, dy));
         }
-
-        d.postTransform(getTranslate(dx, dy));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postScale(long native_object, float sx, float sy,
+    /*package*/ static void native_postScale(long native_object, float sx, float sy,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getScale(sx, sy, px, py));
         }
-
-        d.postTransform(getScale(sx, sy, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postScale(long native_object, float sx, float sy) {
+    /*package*/ static void native_postScale(long native_object, float sx, float sy) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getScale(sx, sy));
         }
-
-        d.postTransform(getScale(sx, sy));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postRotate(long native_object, float degrees,
+    /*package*/ static void native_postRotate(long native_object, float degrees,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getRotate(degrees, px, py));
         }
-
-        d.postTransform(getRotate(degrees, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postRotate(long native_object, float degrees) {
+    /*package*/ static void native_postRotate(long native_object, float degrees) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getRotate(degrees));
         }
-
-        d.postTransform(getRotate(degrees));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky,
+    /*package*/ static void native_postSkew(long native_object, float kx, float ky,
             float px, float py) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getSkew(kx, ky, px, py));
         }
-
-        d.postTransform(getSkew(kx, ky, px, py));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postSkew(long native_object, float kx, float ky) {
+    /*package*/ static void native_postSkew(long native_object, float kx, float ky) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
+        if (d != null) {
+            d.postTransform(getSkew(kx, ky));
         }
-
-        d.postTransform(getSkew(kx, ky));
-        return true;
     }
 
     @LayoutlibDelegate
-    /*package*/ static boolean native_postConcat(long native_object, long other_matrix) {
+    /*package*/ static void native_postConcat(long native_object, long other_matrix) {
         Matrix_Delegate d = sManager.getDelegate(native_object);
-        if (d == null) {
-            return false;
-        }
-
         Matrix_Delegate other = sManager.getDelegate(other_matrix);
-        if (other == null) {
-            return false;
+        if (d != null && other != null) {
+            d.postTransform(other.mValues);
         }
-
-        d.postTransform(other.mValues);
-        return true;
     }
 
     @LayoutlibDelegate
diff --git a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
index de2e592..25eaaf5 100644
--- a/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
+++ b/tools/layoutlib/bridge/src/android/graphics/Paint_Delegate.java
@@ -428,6 +428,16 @@
     }
 
     @LayoutlibDelegate
+    /*package*/ static boolean isElegantTextHeight(Paint thisPaint) {
+        return false;
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void setElegantTextHeight(Paint thisPaint, boolean elegant) {
+        // TODO
+    }
+
+    @LayoutlibDelegate
     /*package*/ static float getTextSize(Paint thisPaint) {
         // get the delegate from the native int.
         Paint_Delegate delegate = sManager.getDelegate(thisPaint.mNativePaint);
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index cdbe200..af22f44 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -32,10 +32,6 @@
 
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.InflateException;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
 
 import java.io.File;
 
@@ -155,6 +151,9 @@
     @Override
     public View inflate(int resource, ViewGroup root) {
         Context context = getContext();
+        if (context instanceof ContextThemeWrapper) {
+            context = ((ContextThemeWrapper) context).getBaseContext();
+        }
         if (context instanceof BridgeContext) {
             BridgeContext bridgeContext = (BridgeContext)context;
 
@@ -217,43 +216,16 @@
     }
 
     private void setupViewInContext(View view, AttributeSet attrs) {
-        if (getContext() instanceof BridgeContext) {
-            BridgeContext bc = (BridgeContext) getContext();
-            if (attrs instanceof BridgeXmlBlockParser) {
-                BridgeXmlBlockParser parser = (BridgeXmlBlockParser) attrs;
-
-                // get the view key
-                Object viewKey = parser.getViewCookie();
-
-                if (viewKey == null) {
-                    int currentDepth = parser.getDepth();
-
-                    // test whether we are in an included file or in a adapter binding view.
-                    BridgeXmlBlockParser previousParser = bc.getPreviousParser();
-                    if (previousParser != null) {
-                        // looks like we inside an embedded layout.
-                        // only apply the cookie of the calling node (<include>) if we are at the
-                        // top level of the embedded layout. If there is a merge tag, then
-                        // skip it and look for the 2nd level
-                        int testDepth = mIsInMerge ? 2 : 1;
-                        if (currentDepth == testDepth) {
-                            viewKey = previousParser.getViewCookie();
-                            // if we are in a merge, wrap the cookie in a MergeCookie.
-                            if (viewKey != null && mIsInMerge) {
-                                viewKey = new MergeCookie(viewKey);
-                            }
-                        }
-                    } else if (mResourceReference != null && currentDepth == 1) {
-                        // else if there's a resource reference, this means we are in an adapter
-                        // binding case. Set the resource ref as the view cookie only for the top
-                        // level view.
-                        viewKey = mResourceReference;
-                    }
-                }
-
-                if (viewKey != null) {
-                    bc.addViewKey(view, viewKey);
-                }
+        Context context = getContext();
+        if (context instanceof ContextThemeWrapper) {
+            context = ((ContextThemeWrapper) context).getBaseContext();
+        }
+        if (context instanceof BridgeContext) {
+            BridgeContext bc = (BridgeContext) context;
+            // get the view key
+            Object viewKey = getViewKeyFromParser(attrs, bc, mResourceReference, mIsInMerge);
+            if (viewKey != null) {
+                bc.addViewKey(view, viewKey);
             }
         }
     }
@@ -270,4 +242,44 @@
     public LayoutInflater cloneInContext(Context newContext) {
         return new BridgeInflater(this, newContext);
     }
+
+    /*package*/ static Object getViewKeyFromParser(AttributeSet attrs, BridgeContext bc,
+            ResourceReference resourceReference, boolean isInMerge) {
+
+        if (!(attrs instanceof BridgeXmlBlockParser)) {
+            return null;
+        }
+        BridgeXmlBlockParser parser = ((BridgeXmlBlockParser) attrs);
+
+        // get the view key
+        Object viewKey = parser.getViewCookie();
+
+        if (viewKey == null) {
+            int currentDepth = parser.getDepth();
+
+            // test whether we are in an included file or in a adapter binding view.
+            BridgeXmlBlockParser previousParser = bc.getPreviousParser();
+            if (previousParser != null) {
+                // looks like we are inside an embedded layout.
+                // only apply the cookie of the calling node (<include>) if we are at the
+                // top level of the embedded layout. If there is a merge tag, then
+                // skip it and look for the 2nd level
+                int testDepth = isInMerge ? 2 : 1;
+                if (currentDepth == testDepth) {
+                    viewKey = previousParser.getViewCookie();
+                    // if we are in a merge, wrap the cookie in a MergeCookie.
+                    if (viewKey != null && isInMerge) {
+                        viewKey = new MergeCookie(viewKey);
+                    }
+                }
+            } else if (resourceReference != null && currentDepth == 1) {
+                // else if there's a resource reference, this means we are in an adapter
+                // binding case. Set the resource ref as the view cookie only for the top
+                // level view.
+                viewKey = resourceReference;
+            }
+        }
+
+        return viewKey;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 743a26c..757cdd2 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -23,22 +23,13 @@
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
 import android.graphics.Bitmap;
-import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.util.DisplayMetrics;
-import android.view.Display;
-import android.view.Gravity;
-import android.view.IApplicationToken;
-import android.view.IInputFilter;
-import android.view.IOnKeyguardExitResult;
-import android.view.IRotationWatcher;
-import android.view.IWindowManager;
-import android.view.IWindowSession;
 
-import java.util.List;
+import java.lang.Override;
 
 /**
  * Basic implementation of {@link IWindowManager} so that {@link Display} (and
@@ -462,4 +453,22 @@
         // TODO Auto-generated method stub
         return false;
     }
+
+    @Override
+    public void enableScreenIfNeeded() throws RemoteException {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public boolean clearWindowContentFrameStats(IBinder token) throws RemoteException {
+        // TODO Auto-generated method stub
+        return false;
+    }
+
+    @Override
+    public WindowContentFrameStats getWindowContentFrameStats(IBinder token)
+            throws RemoteException {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
new file mode 100644
index 0000000..0dddf3d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/android/view/MenuInflater_Delegate.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import android.content.Context;
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.ide.common.rendering.api.ViewInfo;
+import com.android.internal.view.menu.BridgeMenuItemImpl;
+import com.android.internal.view.menu.MenuView;
+import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+import android.util.AttributeSet;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link MenuInflater}
+ * <p/>
+ * Through the layoutlib_create tool, the original  methods of MenuInflater have been
+ * replaced by calls to methods of the same name in this delegate class.
+ * <p/>
+ * The main purpose of the class is to get the view key from the menu xml parser and add it to
+ * the menu item. The view key is used by the IDE to match the individual view elements to the
+ * corresponding xml tag in the menu/layout file.
+ * <p/>
+ * For Menus, the views may be reused and the {@link MenuItem} is a better object to hold the
+ * view key than the {@link MenuView.ItemView}. At the time of computation of the rest of {@link
+ * ViewInfo}, we check the corresponding view key in the menu item for the view and add it
+ */
+public class MenuInflater_Delegate {
+
+    @LayoutlibDelegate
+    /*package*/ static void registerMenu(MenuInflater thisInflater, MenuItem menuItem,
+            AttributeSet attrs) {
+        if (menuItem instanceof BridgeMenuItemImpl) {
+            Context context = thisInflater.getContext();
+            if (context instanceof ContextThemeWrapper) {
+                context = ((ContextThemeWrapper) context).getBaseContext();
+            }
+            if (context instanceof BridgeContext) {
+                Object viewKey = BridgeInflater.getViewKeyFromParser(
+                        attrs, ((BridgeContext) context), null, false);
+                ((BridgeMenuItemImpl) menuItem).setViewCookie(viewKey);
+                return;
+            }
+        }
+        // This means that Bridge did not take over the instantiation of some object properly.
+        // This is most likely a bug in the LayoutLib code.
+        Bridge.getLog().warning(LayoutLog.TAG_BROKEN,
+                "Action Bar Menu rendering may be incorrect.", null);
+
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static void registerMenu(MenuInflater thisInflater, SubMenu subMenu,
+            AttributeSet parser) {
+        registerMenu(thisInflater, subMenu.getItem(), parser);
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
new file mode 100644
index 0000000..4bef424
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/BridgeMenuItemImpl.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.menu;
+
+/**
+ * An extension of the {@link MenuItemImpl} to store the view cookie also.
+ */
+public class BridgeMenuItemImpl extends MenuItemImpl {
+
+    /**
+     * An object returned by the IDE that helps mapping each View to the corresponding XML tag in
+     * the layout. For Menus, we store this cookie here and attach it to the corresponding view
+     * at the time of rendering.
+     */
+    private Object viewCookie;
+
+    /**
+     * Instantiates this menu item.
+     */
+    BridgeMenuItemImpl(MenuBuilder menu, int group, int id, int categoryOrder, int ordering,
+            CharSequence title, int showAsAction) {
+        super(menu, group, id, categoryOrder, ordering, title, showAsAction);
+    }
+
+
+    public Object getViewCookie() {
+        return viewCookie;
+    }
+
+    public void setViewCookie(Object viewCookie) {
+        this.viewCookie = viewCookie;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java
new file mode 100644
index 0000000..505fb81
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/view/menu/MenuBuilder_Delegate.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.view.menu;
+
+import com.android.tools.layoutlib.annotations.LayoutlibDelegate;
+
+/**
+ * Delegate used to provide new implementation of a select few methods of {@link MenuBuilder}
+ * <p/>
+ * Through the layoutlib_create tool, the original  methods of {@code MenuBuilder} have been
+ * replaced by calls to methods of the same name in this delegate class.
+ */
+public class MenuBuilder_Delegate {
+    /**
+     * The method overrides the instantiation of the {@link MenuItemImpl} with an instance of
+     * {@link BridgeMenuItemImpl} so that view cookies may be stored.
+     */
+    @LayoutlibDelegate
+    /*package*/ static MenuItemImpl createNewMenuItem(MenuBuilder thisMenu, int group, int id,
+            int categoryOrder, int ordering, CharSequence title, int defaultShowAsAction) {
+        return new BridgeMenuItemImpl(thisMenu, group, id, categoryOrder, ordering, title,
+                defaultShowAsAction);
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
new file mode 100644
index 0000000..40b6220
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/internal/widget/ActionBarAccessor.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.widget;
+
+import android.widget.ActionMenuPresenter;
+
+/**
+ * To access non public members of AbsActionBarView
+ */
+public class ActionBarAccessor {
+
+    /**
+     * Returns the {@link ActionMenuPresenter} associated with the {@link AbsActionBarView}
+     */
+    public static ActionMenuPresenter getActionMenuPresenter(AbsActionBarView view) {
+        return view.mActionMenuPresenter;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index ab4be71..fa8050f 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -215,7 +215,8 @@
                 Capability.ADAPTER_BINDING,
                 Capability.EXTENDED_VIEWINFO,
                 Capability.FIXED_SCALABLE_NINE_PATCH,
-                Capability.RTL);
+                Capability.RTL,
+                Capability.ACTION_BAR);
 
 
         BridgeAssetManager.initSystem();
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
index f9f4b3a..e0f87fd 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeRenderSession.java
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public List<ViewInfo> getSystemRootViews() {
+        return mSession.getSystemViewInfos();
+    }
+
+    @Override
     public Map<String, String> getDefaultProperties(Object viewObject) {
         return mSession.getDefaultProperties(viewObject);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 9ee2f60..08e9d99 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -58,6 +58,7 @@
 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
+import android.hardware.display.DisplayManager;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.Handler;
@@ -101,6 +102,7 @@
     private final ApplicationInfo mApplicationInfo;
     private final IProjectCallback mProjectCallback;
     private final WindowManager mWindowManager;
+    private final DisplayManager mDisplayManager;
 
     private Resources.Theme mTheme;
 
@@ -149,6 +151,7 @@
         }
 
         mWindowManager = new WindowManagerImpl(mMetrics);
+        mDisplayManager = new DisplayManager(this);
     }
 
     /**
@@ -455,6 +458,10 @@
             return new PowerManager(this, new BridgePowerManager(), new Handler());
         }
 
+        if (DISPLAY_SERVICE.equals(service)) {
+            return mDisplayManager;
+        }
+
         throw new UnsupportedOperationException("Unsupported Service: " + service);
     }
 
@@ -613,7 +620,8 @@
             }
 
             if (value != null) {
-                if (value.getFirst() == ResourceType.STYLE) {
+                if ((value.getFirst() == ResourceType.STYLE)
+                        || (value.getFirst() == ResourceType.ATTR)) {
                     // look for the style in the current theme, and its parent:
                     ResourceValue item = mRenderResources.findItemInTheme(value.getSecond(),
                             isFrameworkRes);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index b9f2ed9..4eb70aa 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -28,7 +28,7 @@
 public class BridgePowerManager implements IPowerManager {
 
     @Override
-    public boolean isScreenOn() throws RemoteException {
+    public boolean isInteractive() throws RemoteException {
         return true;
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
index df576d2..d32f6ee 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindow.java
@@ -58,11 +58,6 @@
     }
 
     @Override
-    public void dispatchScreenState(boolean on) throws RemoteException {
-        // pass for now.
-    }
-
-    @Override
     public void windowFocusChanged(boolean arg0, boolean arg1) throws RemoteException {
         // pass for now.
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
new file mode 100644
index 0000000..08512e7
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/ActionBarLayout.java
@@ -0,0 +1,381 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.annotations.NonNull;
+import com.android.annotations.Nullable;
+import com.android.ide.common.rendering.api.ActionBarCallback;
+import com.android.ide.common.rendering.api.ActionBarCallback.HomeButtonStyle;
+import com.android.ide.common.rendering.api.RenderResources;
+import com.android.ide.common.rendering.api.ResourceValue;
+import com.android.ide.common.rendering.api.SessionParams;
+import com.android.ide.common.rendering.api.SystemViewCookie;
+import com.android.internal.R;
+import com.android.internal.app.WindowDecorActionBar;
+import com.android.internal.util.Predicate;
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.widget.ActionBarAccessor;
+import com.android.internal.widget.ActionBarContainer;
+import com.android.internal.widget.ActionBarView;
+import com.android.layoutlib.bridge.android.BridgeContext;
+import com.android.layoutlib.bridge.impl.ResourceHelper;
+import com.android.resources.ResourceType;
+
+import android.app.ActionBar;
+import android.app.ActionBar.Tab;
+import android.app.ActionBar.TabListener;
+import android.app.FragmentTransaction;
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.drawable.Drawable;
+import android.util.DisplayMetrics;
+import android.util.TypedValue;
+import android.view.Gravity;
+import android.view.LayoutInflater;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+import android.widget.ListAdapter;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+
+import java.util.ArrayList;
+
+import static com.android.ide.common.rendering.api.SystemViewCookie.ACTION_BAR_OVERFLOW;
+
+/**
+ * A layout representing the action bar.
+ */
+public class ActionBarLayout extends LinearLayout {
+
+    // Store another reference to the context so that we don't have to cast it repeatedly.
+    @NonNull private final BridgeContext mBridgeContext;
+    @NonNull private final Context mThemedContext;
+
+    @NonNull private final ActionBar mActionBar;
+
+    // Data for Action Bar.
+    @Nullable private final String mIcon;
+    @Nullable private final String mTitle;
+    @Nullable private final String mSubTitle;
+    private final boolean mSplit;
+    private final boolean mShowHomeAsUp;
+    private final int mNavMode;
+
+    // Helper fields.
+    @NonNull private final MenuBuilder mMenuBuilder;
+    private final int mPopupMaxWidth;
+    @NonNull private final RenderResources res;
+    @Nullable private final ActionBarView mActionBarView;
+    @Nullable private FrameLayout mContentRoot;
+    @NonNull private final ActionBarCallback mCallback;
+
+    // A fake parent for measuring views.
+    @Nullable private ViewGroup mMeasureParent;
+
+    public ActionBarLayout(@NonNull BridgeContext context, @NonNull SessionParams params) {
+
+        super(context);
+        setOrientation(LinearLayout.HORIZONTAL);
+        setGravity(Gravity.CENTER_VERTICAL);
+
+        // Inflate action bar layout.
+        LayoutInflater.from(context).inflate(R.layout.screen_action_bar, this,
+                true /*attachToRoot*/);
+        mActionBar = new WindowDecorActionBar(this);
+
+        // Set contexts.
+        mBridgeContext = context;
+        mThemedContext = mActionBar.getThemedContext();
+
+        // Set data for action bar.
+        mCallback = params.getProjectCallback().getActionBarCallback();
+        mIcon = params.getAppIcon();
+        mTitle = params.getAppLabel();
+        // Split Action Bar when the screen size is narrow and the application requests split action
+        // bar when narrow.
+        mSplit = context.getResources().getBoolean(R.bool.split_action_bar_is_narrow) &&
+                mCallback.getSplitActionBarWhenNarrow();
+        mNavMode = mCallback.getNavigationMode();
+        // TODO: Support Navigation Drawer Indicator.
+        mShowHomeAsUp = mCallback.getHomeButtonStyle() == HomeButtonStyle.SHOW_HOME_AS_UP;
+        mSubTitle = mCallback.getSubTitle();
+
+
+        // Set helper fields.
+        mMenuBuilder = new MenuBuilder(mThemedContext);
+        res = mBridgeContext.getRenderResources();
+        mPopupMaxWidth = Math.max(mBridgeContext.getMetrics().widthPixels / 2,
+                mThemedContext.getResources().getDimensionPixelSize(
+                        R.dimen.config_prefDialogWidth));
+        mActionBarView = (ActionBarView) findViewById(R.id.action_bar);
+        mContentRoot = (FrameLayout) findViewById(android.R.id.content);
+
+        setupActionBar();
+    }
+
+    /**
+     * Sets up the action bar by filling the appropriate data.
+     */
+    private void setupActionBar() {
+        // Add title and sub title.
+        ResourceValue titleValue = res.findResValue(mTitle, false /*isFramework*/);
+        if (titleValue != null && titleValue.getValue() != null) {
+            mActionBar.setTitle(titleValue.getValue());
+        } else {
+            mActionBar.setTitle(mTitle);
+        }
+        if (mSubTitle != null) {
+            mActionBar.setSubtitle(mSubTitle);
+        }
+
+        // Add show home as up icon.
+        if (mShowHomeAsUp) {
+            mActionBar.setDisplayOptions(0xFF, ActionBar.DISPLAY_HOME_AS_UP);
+        }
+
+        // Set the navigation mode.
+        mActionBar.setNavigationMode(mNavMode);
+        if (mNavMode == ActionBar.NAVIGATION_MODE_TABS) {
+            setupTabs(3);
+        }
+
+        if (mActionBarView != null) {
+            // If the action bar style doesn't specify an icon, set the icon obtained from the session
+            // params.
+            if (!mActionBarView.hasIcon() && mIcon != null) {
+                Drawable iconDrawable = getDrawable(mIcon, false /*isFramework*/);
+                if (iconDrawable != null) {
+                    mActionBar.setIcon(iconDrawable);
+                }
+            }
+
+            // Set action bar to be split, if needed.
+            ActionBarContainer splitView = (ActionBarContainer) findViewById(R.id.split_action_bar);
+            mActionBarView.setSplitView(splitView);
+            mActionBarView.setSplitActionBar(mSplit);
+
+            inflateMenus();
+
+            // Find if the Overflow Menu Button (the three dots) exists. If yes,
+            // add the view cookie.
+            Predicate<View> overflowMenuButtonTest = new Predicate<View>() {
+                @Override
+                public boolean apply(View view) {
+                    return view.getClass().getName()
+                            .equals("android.widget.ActionMenuPresenter$OverflowMenuButton");
+                }
+            };
+            View overflowMenu = null;
+            if (mSplit) {
+                if (splitView != null) {
+                    overflowMenu = splitView.findViewByPredicate(overflowMenuButtonTest);
+                }
+            }
+            else {
+                overflowMenu = mActionBarView.findViewByPredicate(overflowMenuButtonTest);
+            }
+            if (overflowMenu != null) {
+                mBridgeContext.addViewKey(overflowMenu, new SystemViewCookie(ACTION_BAR_OVERFLOW));
+            }
+        }
+    }
+
+    /**
+     * Gets the menus to add to the action bar from the callback, resolves them, inflates them and
+     * adds them to the action bar.
+     */
+    private void inflateMenus() {
+        if (mActionBarView == null) {
+            return;
+        }
+        final MenuInflater inflater = new MenuInflater(mThemedContext);
+        for (String name : mCallback.getMenuIdNames()) {
+            if (mBridgeContext.getRenderResources().getProjectResource(ResourceType.MENU, name)
+                    != null) {
+                int id = mBridgeContext.getProjectResourceValue(ResourceType.MENU, name, -1);
+                if (id > -1) {
+                    inflater.inflate(id, mMenuBuilder);
+                }
+            }
+        }
+        mActionBarView.setMenu(mMenuBuilder, null /*callback*/);
+    }
+
+    // TODO: Use an adapter, like List View to set up tabs.
+    private void setupTabs(int num) {
+        for (int i = 1; i <= num; i++) {
+            Tab tab = mActionBar.newTab().setText("Tab" + i).setTabListener(new TabListener() {
+                @Override
+                public void onTabUnselected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+                @Override
+                public void onTabSelected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+                @Override
+                public void onTabReselected(Tab t, FragmentTransaction ft) {
+                    // pass
+                }
+            });
+            mActionBar.addTab(tab);
+        }
+    }
+
+    @Nullable
+    private Drawable getDrawable(@NonNull String name, boolean isFramework) {
+        ResourceValue value = res.findResValue(name, isFramework);
+        value = res.resolveResValue(value);
+        if (value != null) {
+            return ResourceHelper.getDrawable(value, mBridgeContext);
+        }
+        return null;
+    }
+
+    /**
+     * Creates a Popup and adds it to the content frame. It also adds another {@link FrameLayout} to
+     * the content frame which shall serve as the new content root.
+     */
+    public void createMenuPopup() {
+        assert mContentRoot != null && findViewById(android.R.id.content) == mContentRoot
+                : "Action Bar Menus have already been created.";
+
+        if (!isOverflowPopupNeeded()) {
+            return;
+        }
+
+        // Create a layout to hold the menus and the user's content.
+        RelativeLayout layout = new RelativeLayout(mThemedContext);
+        layout.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,
+                LayoutParams.MATCH_PARENT));
+        mContentRoot.addView(layout);
+        // Create a layout for the user's content.
+        FrameLayout contentRoot = new FrameLayout(mBridgeContext);
+        contentRoot.setLayoutParams(new LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        // Add contentRoot and menus to the layout.
+        layout.addView(contentRoot);
+        layout.addView(createMenuView());
+        // ContentRoot is now the view we just created.
+        mContentRoot = contentRoot;
+    }
+
+    /**
+     * Returns a {@link LinearLayout} containing the menu list view to be embedded in a
+     * {@link RelativeLayout}
+     */
+    @NonNull
+    private View createMenuView() {
+        DisplayMetrics metrics = mBridgeContext.getMetrics();
+        OverflowMenuAdapter adapter = new OverflowMenuAdapter(mMenuBuilder, mThemedContext);
+
+        LinearLayout layout = new LinearLayout(mThemedContext);
+        RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
+                measureContentWidth(adapter), LayoutParams.WRAP_CONTENT);
+        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_END);
+        if (mSplit) {
+            layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
+            // TODO: Find correct value instead of hardcoded 10dp.
+            layoutParams.bottomMargin = getPixelValue("-10dp", metrics);
+        } else {
+            layoutParams.topMargin = getPixelValue("-10dp", metrics);
+        }
+        layout.setLayoutParams(layoutParams);
+        final TypedArray a = mThemedContext.obtainStyledAttributes(null,
+                R.styleable.PopupWindow, R.attr.popupMenuStyle, 0);
+        layout.setBackground(a.getDrawable(R.styleable.PopupWindow_popupBackground));
+        layout.setDividerDrawable(a.getDrawable(R.attr.actionBarDivider));
+        a.recycle();
+        layout.setOrientation(LinearLayout.VERTICAL);
+        layout.setDividerPadding(getPixelValue("12dp", metrics));
+        layout.setShowDividers(LinearLayout.SHOW_DIVIDER_MIDDLE);
+
+        ListView listView = new ListView(mThemedContext, null, R.attr.dropDownListViewStyle);
+        listView.setAdapter(adapter);
+        layout.addView(listView);
+        return layout;
+    }
+
+    private boolean isOverflowPopupNeeded() {
+        boolean needed = mCallback.isOverflowPopupNeeded();
+        if (!needed) {
+            return false;
+        }
+        // Copied from android.widget.ActionMenuPresenter.updateMenuView()
+        ArrayList<MenuItemImpl> menus = mMenuBuilder.getNonActionItems();
+        if (ActionBarAccessor.getActionMenuPresenter(mActionBarView).isOverflowReserved() &&
+                menus != null) {
+            final int count = menus.size();
+            if (count == 1) {
+                needed = !menus.get(0).isActionViewExpanded();
+            } else {
+                needed = count > 0;
+            }
+        }
+        return needed;
+    }
+
+    @Nullable
+    public FrameLayout getContentRoot() {
+        return mContentRoot;
+    }
+
+    // Copied from com.android.internal.view.menu.MenuPopHelper.measureContentWidth()
+    private int measureContentWidth(@NonNull ListAdapter adapter) {
+        // Menus don't tend to be long, so this is more sane than it looks.
+        int maxWidth = 0;
+        View itemView = null;
+        int itemType = 0;
+
+        final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
+        final int count = adapter.getCount();
+        for (int i = 0; i < count; i++) {
+            final int positionType = adapter.getItemViewType(i);
+            if (positionType != itemType) {
+                itemType = positionType;
+                itemView = null;
+            }
+
+            if (mMeasureParent == null) {
+                mMeasureParent = new FrameLayout(mThemedContext);
+            }
+
+            itemView = adapter.getView(i, itemView, mMeasureParent);
+            itemView.measure(widthMeasureSpec, heightMeasureSpec);
+
+            final int itemWidth = itemView.getMeasuredWidth();
+            if (itemWidth >= mPopupMaxWidth) {
+                return mPopupMaxWidth;
+            } else if (itemWidth > maxWidth) {
+                maxWidth = itemWidth;
+            }
+        }
+
+        return maxWidth;
+    }
+
+    private int getPixelValue(@NonNull String value, @NonNull DisplayMetrics metrics) {
+        TypedValue typedValue = ResourceHelper.getValue(null, value, false /*requireUnit*/);
+        return (int) typedValue.getDimension(metrics);
+    }
+
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
deleted file mode 100644
index 226649d..0000000
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/FakeActionBar.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (C) 2011 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 com.android.layoutlib.bridge.bars;
-
-import com.android.resources.Density;
-
-import org.xmlpull.v1.XmlPullParserException;
-
-import android.content.Context;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class FakeActionBar extends CustomBar {
-
-    private TextView mTextView;
-
-    public FakeActionBar(Context context, Density density, String label, String icon)
-            throws XmlPullParserException {
-        super(context, density, LinearLayout.HORIZONTAL, "/bars/action_bar.xml", "action_bar.xml");
-
-        // Cannot access the inside items through id because no R.id values have been
-        // created for them.
-        // We do know the order though.
-        loadIconById(android.R.id.home, icon);
-        mTextView = setText(1, label);
-
-        setStyle("actionBarStyle");
-    }
-
-    @Override
-    protected TextView getStyleableTextView() {
-        return mTextView;
-    }
-}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
new file mode 100644
index 0000000..778305d
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/bars/OverflowMenuAdapter.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.bars;
+
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuView;
+
+import android.content.Context;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+
+import java.util.ArrayList;
+
+/**
+ * Provides an adapter for Overflow menu popup. This is very similar to
+ * {@code MenuPopupHelper.MenuAdapter}
+ */
+public class OverflowMenuAdapter extends BaseAdapter {
+
+    private final MenuBuilder mMenu;
+    private int mExpandedIndex = -1;
+    private final Context context;
+
+    public OverflowMenuAdapter(MenuBuilder menu, Context context) {
+        mMenu = menu;
+        findExpandedIndex();
+        this.context = context;
+    }
+
+    @Override
+    public int getCount() {
+        ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+        if (mExpandedIndex < 0) {
+            return items.size();
+        }
+        return items.size() - 1;
+    }
+
+    @Override
+    public MenuItemImpl getItem(int position) {
+        ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+        if (mExpandedIndex >= 0 && position >= mExpandedIndex) {
+            position++;
+        }
+        return items.get(position);
+    }
+
+    @Override
+    public long getItemId(int position) {
+        // Since a menu item's ID is optional, we'll use the position as an
+        // ID for the item in the AdapterView
+        return position;
+    }
+
+    @Override
+    public View getView(int position, View convertView, ViewGroup parent) {
+        if (convertView == null) {
+            LayoutInflater mInflater = LayoutInflater.from(context);
+            convertView = mInflater.inflate(com.android.internal.R.layout.popup_menu_item_layout,
+                    parent, false);
+        }
+
+        MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+        itemView.initialize(getItem(position), 0);
+        return convertView;
+    }
+
+    private void findExpandedIndex() {
+        final MenuItemImpl expandedItem = mMenu.getExpandedItem();
+        if (expandedItem != null) {
+            final ArrayList<MenuItemImpl> items = mMenu.getNonActionItems();
+            final int count = items.size();
+            for (int i = 0; i < count; i++) {
+                final MenuItemImpl item = items.get(i);
+                if (item == expandedItem) {
+                    mExpandedIndex = i;
+                    return;
+                }
+            }
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index 377d996..9787432 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -28,7 +28,6 @@
 import com.android.ide.common.rendering.api.IAnimationListener;
 import com.android.ide.common.rendering.api.ILayoutPullParser;
 import com.android.ide.common.rendering.api.IProjectCallback;
-import com.android.ide.common.rendering.api.RenderParams;
 import com.android.ide.common.rendering.api.RenderResources;
 import com.android.ide.common.rendering.api.RenderSession;
 import com.android.ide.common.rendering.api.ResourceReference;
@@ -39,16 +38,23 @@
 import com.android.ide.common.rendering.api.SessionParams.RenderingMode;
 import com.android.ide.common.rendering.api.ViewInfo;
 import com.android.internal.util.XmlUtils;
+import com.android.internal.view.menu.ActionMenuItemView;
+import com.android.internal.view.menu.BridgeMenuItemImpl;
+import com.android.internal.view.menu.IconMenuItemView;
+import com.android.internal.view.menu.ListMenuItemView;
+import com.android.internal.view.menu.MenuItemImpl;
+import com.android.internal.view.menu.MenuView;
 import com.android.layoutlib.bridge.Bridge;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
-import com.android.layoutlib.bridge.bars.FakeActionBar;
 import com.android.layoutlib.bridge.bars.NavigationBar;
 import com.android.layoutlib.bridge.bars.StatusBar;
 import com.android.layoutlib.bridge.bars.TitleBar;
+import com.android.layoutlib.bridge.bars.ActionBarLayout;
 import com.android.layoutlib.bridge.impl.binding.FakeAdapter;
 import com.android.layoutlib.bridge.impl.binding.FakeExpandableAdapter;
+import com.android.resources.Density;
 import com.android.resources.ResourceType;
 import com.android.resources.ScreenOrientation;
 import com.android.util.Pair;
@@ -100,11 +106,10 @@
 
 /**
  * Class implementing the render session.
- *
+ * <p/>
  * A session is a stateful representation of a layout file. It is initialized with data coming
  * through the {@link Bridge} API to inflate the layout. Further actions and rendering can then
  * be done on the layout.
- *
  */
 public class RenderSessionImpl extends RenderAction<SessionParams> {
 
@@ -134,6 +139,7 @@
     // information being returned through the API
     private BufferedImage mImage;
     private List<ViewInfo> mViewInfoList;
+    private List<ViewInfo> mSystemViewInfoList;
 
     private static final class PostInflateException extends Exception {
         private static final long serialVersionUID = 1L;
@@ -146,10 +152,11 @@
     /**
      * Creates a layout scene with all the information coming from the layout bridge API.
      * <p>
-     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init()}, which act as a
+     * This <b>must</b> be followed by a call to {@link RenderSessionImpl#init(long)},
+     * which act as a
      * call to {@link RenderSessionImpl#acquire(long)}
      *
-     * @see LayoutBridge#createScene(com.android.layoutlib.api.SceneParams)
+     * @see Bridge#createSession(SessionParams)
      */
     public RenderSessionImpl(SessionParams params) {
         super(new SessionParams(params));
@@ -169,7 +176,7 @@
     @Override
     public Result init(long timeout) {
         Result result = super.init(timeout);
-        if (result.isSuccess() == false) {
+        if (!result.isSuccess()) {
             return result;
         }
 
@@ -193,6 +200,7 @@
 
         // FIXME: find those out, and possibly add them to the render params
         boolean hasNavigationBar = true;
+        //noinspection ConstantConditions
         IWindowManager iwm = new IWindowManagerImpl(getContext().getConfiguration(),
                 metrics, Surface.ROTATION_0,
                 hasNavigationBar);
@@ -225,14 +233,14 @@
             HardwareConfig hardwareConfig = params.getHardwareConfig();
             BridgeContext context = getContext();
             boolean isRtl = Bridge.isLocaleRtl(params.getLocale());
-            int direction = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
+            int layoutDirection = isRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR;
 
             // the view group that receives the window background.
-            ViewGroup backgroundView = null;
+            ViewGroup backgroundView;
 
             if (mWindowIsFloating || params.isForceNoDecor()) {
                 backgroundView = mViewRoot = mContentRoot = new FrameLayout(context);
-                mViewRoot.setLayoutDirection(direction);
+                mViewRoot.setLayoutDirection(layoutDirection);
             } else {
                 if (hasSoftwareButtons() && mNavigationBarOrientation == LinearLayout.VERTICAL) {
                     /*
@@ -254,20 +262,15 @@
                        the bottom
                      */
                     LinearLayout topLayout = new LinearLayout(context);
-                    topLayout.setLayoutDirection(direction);
+                    topLayout.setLayoutDirection(layoutDirection);
                     mViewRoot = topLayout;
                     topLayout.setOrientation(LinearLayout.HORIZONTAL);
 
                     try {
-                        NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.VERTICAL, isRtl,
-                                params.isRtlSupported());
-                        navigationBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        mNavigationBarSize,
-                                        LayoutParams.MATCH_PARENT));
+                        NavigationBar navigationBar = createNavigationBar(context,
+                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
                         topLayout.addView(navigationBar);
-                    } catch (XmlPullParserException e) {
+                    } catch (XmlPullParserException ignored) {
 
                     }
                 }
@@ -293,14 +296,15 @@
 
                 LinearLayout topLayout = new LinearLayout(context);
                 topLayout.setOrientation(LinearLayout.VERTICAL);
-                topLayout.setLayoutDirection(direction);
+                topLayout.setLayoutDirection(layoutDirection);
                 // if we don't already have a view root this is it
                 if (mViewRoot == null) {
                     mViewRoot = topLayout;
                 } else {
+                    int topLayoutWidth =
+                            params.getHardwareConfig().getScreenWidth() - mNavigationBarSize;
                     LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(
-                            LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT);
-                    layoutParams.weight = 1;
+                            topLayoutWidth, LayoutParams.MATCH_PARENT);
                     topLayout.setLayoutParams(layoutParams);
 
                     // this is the case of soft buttons + vertical bar.
@@ -319,13 +323,10 @@
                 if (mStatusBarSize > 0) {
                     // system bar
                     try {
-                        StatusBar systemBar = new StatusBar(context, hardwareConfig.getDensity(),
-                                direction, params.isRtlSupported());
-                        systemBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mStatusBarSize));
-                        topLayout.addView(systemBar);
-                    } catch (XmlPullParserException e) {
+                        StatusBar statusBar = createStatusBar(context, hardwareConfig.getDensity(),
+                                layoutDirection, params.isRtlSupported());
+                        topLayout.addView(statusBar);
+                    } catch (XmlPullParserException ignored) {
 
                     }
                 }
@@ -342,50 +343,38 @@
 
                 // if the theme says no title/action bar, then the size will be 0
                 if (mActionBarSize > 0) {
-                    try {
-                        FakeActionBar actionBar = new FakeActionBar(context,
-                                hardwareConfig.getDensity(),
-                                params.getAppLabel(), params.getAppIcon());
-                        actionBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mActionBarSize));
-                        backgroundLayout.addView(actionBar);
-                    } catch (XmlPullParserException e) {
-
-                    }
+                    ActionBarLayout actionBar = createActionBar(context, params);
+                    backgroundLayout.addView(actionBar);
+                    actionBar.createMenuPopup();
+                    mContentRoot = actionBar.getContentRoot();
                 } else if (mTitleBarSize > 0) {
                     try {
-                        TitleBar titleBar = new TitleBar(context,
+                        TitleBar titleBar = createTitleBar(context,
                                 hardwareConfig.getDensity(), params.getAppLabel());
-                        titleBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mTitleBarSize));
                         backgroundLayout.addView(titleBar);
-                    } catch (XmlPullParserException e) {
+                    } catch (XmlPullParserException ignored) {
 
                     }
                 }
 
                 // content frame
-                mContentRoot = new FrameLayout(context);
-                layoutParams = new LinearLayout.LayoutParams(
-                        LayoutParams.MATCH_PARENT, 0);
-                layoutParams.weight = 1;
-                mContentRoot.setLayoutParams(layoutParams);
-                backgroundLayout.addView(mContentRoot);
+                if (mContentRoot == null) {
+                    mContentRoot = new FrameLayout(context);
+                    layoutParams = new LinearLayout.LayoutParams(
+                            LayoutParams.MATCH_PARENT, 0);
+                    layoutParams.weight = 1;
+                    mContentRoot.setLayoutParams(layoutParams);
+                    backgroundLayout.addView(mContentRoot);
+                }
 
                 if (mNavigationBarOrientation == LinearLayout.HORIZONTAL &&
                         mNavigationBarSize > 0) {
                     // system bar
                     try {
-                        NavigationBar navigationBar = new NavigationBar(context,
-                                hardwareConfig.getDensity(), LinearLayout.HORIZONTAL, isRtl,
-                                params.isRtlSupported());
-                        navigationBar.setLayoutParams(
-                                new LinearLayout.LayoutParams(
-                                        LayoutParams.MATCH_PARENT, mNavigationBarSize));
+                        NavigationBar navigationBar = createNavigationBar(context,
+                                hardwareConfig.getDensity(), isRtl, params.isRtlSupported());
                         topLayout.addView(navigationBar);
-                    } catch (XmlPullParserException e) {
+                    } catch (XmlPullParserException ignored) {
 
                     }
                 }
@@ -410,7 +399,7 @@
             postInflateProcess(view, params.getProjectCallback());
 
             // get the background drawable
-            if (mWindowBackground != null && backgroundView != null) {
+            if (mWindowBackground != null) {
                 Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
                 backgroundView.setBackground(d);
             }
@@ -441,7 +430,7 @@
      * @throws IllegalStateException if the current context is different than the one owned by
      *      the scene, or if {@link #acquire(long)} was not called.
      *
-     * @see RenderParams#getRenderingMode()
+     * @see SessionParams#getRenderingMode()
      * @see RenderSession#render(long)
      */
     public Result render(boolean freshRender) {
@@ -487,6 +476,7 @@
 
                     // first measure the full layout, with EXACTLY to get the size of the
                     // content as it is inside the decor/dialog
+                    @SuppressWarnings("deprecation")
                     Pair<Integer, Integer> exactMeasure = measureView(
                             mViewRoot, mContentRoot.getChildAt(0),
                             mMeasuredScreenWidth, MeasureSpec.EXACTLY,
@@ -494,6 +484,7 @@
 
                     // now measure the content only using UNSPECIFIED (where applicable, based on
                     // the rendering mode). This will give us the size the content needs.
+                    @SuppressWarnings("deprecation")
                     Pair<Integer, Integer> result = measureView(
                             mContentRoot, mContentRoot.getChildAt(0),
                             mMeasuredScreenWidth, widthMeasureSpecMode,
@@ -569,7 +560,7 @@
                     mCanvas.setDensity(hardwareConfig.getDensity().getDpiValue());
                 }
 
-                if (freshRender && newImage == false) {
+                if (freshRender && !newImage) {
                     Graphics2D gc = mImage.createGraphics();
                     gc.setComposite(AlphaComposite.Src);
 
@@ -584,7 +575,8 @@
                 mViewRoot.draw(mCanvas);
             }
 
-            mViewInfoList = startVisitingViews(mViewRoot, 0, params.getExtendedViewInfoMode());
+            mSystemViewInfoList = visitAllChildren(mViewRoot, 0, params.getExtendedViewInfoMode(),
+                    false);
 
             // success!
             return SUCCESS.createResult();
@@ -614,6 +606,7 @@
      * @param heightMode the MeasureSpec mode to use for the height.
      * @return the measured width/height if measuredView is non-null, null otherwise.
      */
+    @SuppressWarnings("deprecation")  // For the use of Pair
     private Pair<Integer, Integer> measureView(ViewGroup viewToMeasure, View measuredView,
             int width, int widthMode, int height, int heightMode) {
         int w_spec = MeasureSpec.makeMeasureSpec(width, widthMode);
@@ -644,7 +637,7 @@
         BridgeContext context = getContext();
 
         // find the animation file.
-        ResourceValue animationResource = null;
+        ResourceValue animationResource;
         int animationId = 0;
         if (isFrameworkAnimation) {
             animationResource = context.getRenderResources().getFrameworkResource(
@@ -734,7 +727,7 @@
 
         // add it to the parentView in the correct location
         Result result = addView(parentView, child, index);
-        if (result.isSuccess() == false) {
+        if (!result.isSuccess()) {
             return result;
         }
 
@@ -804,13 +797,13 @@
                     public void run() {
                         Result result = moveView(previousParent, newParentView, childView, index,
                                 params);
-                        if (result.isSuccess() == false) {
+                        if (!result.isSuccess()) {
                             listener.done(result);
                         }
 
                         // ready to do the work, acquire the scene.
                         result = acquire(250);
-                        if (result.isSuccess() == false) {
+                        if (!result.isSuccess()) {
                             listener.done(result);
                             return;
                         }
@@ -868,7 +861,7 @@
         }
 
         Result result = moveView(previousParent, newParentView, childView, index, layoutParams);
-        if (result.isSuccess() == false) {
+        if (!result.isSuccess()) {
             return result;
         }
 
@@ -1002,7 +995,7 @@
         }
 
         Result result = removeView(parent, childView);
-        if (result.isSuccess() == false) {
+        if (!result.isSuccess()) {
             return result;
         }
 
@@ -1030,7 +1023,7 @@
 
 
     private void findBackground(RenderResources resources) {
-        if (getParams().isBgColorOverridden() == false) {
+        if (!getParams().isBgColorOverridden()) {
             mWindowBackground = resources.findItemInTheme("windowBackground",
                     true /*isFrameworkAttr*/);
             if (mWindowBackground != null) {
@@ -1047,7 +1040,7 @@
         boolean windowFullscreen = getBooleanThemeValue(resources,
                 "windowFullscreen", false /*defaultValue*/);
 
-        if (windowFullscreen == false && mWindowIsFloating == false) {
+        if (!windowFullscreen && !mWindowIsFloating) {
             // default value
             mStatusBarSize = DEFAULT_STATUS_BAR_HEIGHT;
 
@@ -1101,7 +1094,7 @@
             boolean windowNoTitle = getBooleanThemeValue(resources,
                     "windowNoTitle", false /*defaultValue*/);
 
-            if (windowNoTitle == false) {
+            if (!windowNoTitle) {
 
                 // default size of the window title bar
                 mTitleBarSize = DEFAULT_TITLE_BAR_HEIGHT;
@@ -1128,7 +1121,7 @@
     }
 
     private void findNavigationBar(RenderResources resources, DisplayMetrics metrics) {
-        if (hasSoftwareButtons() && mWindowIsFloating == false) {
+        if (hasSoftwareButtons() && !mWindowIsFloating) {
 
             // default value
             mNavigationBarSize = 48; // ??
@@ -1142,15 +1135,12 @@
                 int shortSize = hardwareConfig.getScreenHeight();
 
                 // compute in dp
-                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / hardwareConfig.getDensity().getDpiValue();
+                int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT /
+                        hardwareConfig.getDensity().getDpiValue();
 
-                if (shortSizeDp < 600) {
-                    // 0-599dp: "phone" UI with bar on the side
-                    barOnBottom = false;
-                } else {
-                    // 600+dp: "tablet" UI with bar on the bottom
-                    barOnBottom = true;
-                }
+                // 0-599dp: "phone" UI with bar on the side
+                // 600+dp: "tablet" UI with bar on the bottom
+                barOnBottom = shortSizeDp >= 600;
             }
 
             if (barOnBottom) {
@@ -1201,13 +1191,15 @@
     }
 
     /**
-     * Post process on a view hierachy that was just inflated.
-     * <p/>At the moment this only support TabHost: If {@link TabHost} is detected, look for the
+     * Post process on a view hierarchy that was just inflated.
+     * <p/>
+     * At the moment this only supports TabHost: If {@link TabHost} is detected, look for the
      * {@link TabWidget}, and the corresponding {@link FrameLayout} and make new tabs automatically
      * based on the content of the {@link FrameLayout}.
      * @param view the root view to process.
      * @param projectCallback callback to the project.
      */
+    @SuppressWarnings("deprecation")  // For the use of Pair
     private void postInflateProcess(View view, IProjectCallback projectCallback)
             throws PostInflateException {
         if (view instanceof TabHost) {
@@ -1310,7 +1302,7 @@
                     "TabHost requires a TabWidget with id \"android:id/tabs\".\n");
         }
 
-        if ((v instanceof TabWidget) == false) {
+        if (!(v instanceof TabWidget)) {
             throw new PostInflateException(String.format(
                     "TabHost requires a TabWidget with id \"android:id/tabs\".\n" +
                     "View found with id 'tabs' is '%s'", v.getClass().getCanonicalName()));
@@ -1319,12 +1311,14 @@
         v = tabHost.findViewById(android.R.id.tabcontent);
 
         if (v == null) {
-            // TODO: see if we can fake tabs even without the FrameLayout (same below when the framelayout is empty)
+            // TODO: see if we can fake tabs even without the FrameLayout (same below when the frameLayout is empty)
+            //noinspection SpellCheckingInspection
             throw new PostInflateException(
                     "TabHost requires a FrameLayout with id \"android:id/tabcontent\".");
         }
 
-        if ((v instanceof FrameLayout) == false) {
+        if (!(v instanceof FrameLayout)) {
+            //noinspection SpellCheckingInspection
             throw new PostInflateException(String.format(
                     "TabHost requires a FrameLayout with id \"android:id/tabcontent\".\n" +
                     "View found with id 'tabcontent' is '%s'", v.getClass().getCanonicalName()));
@@ -1332,7 +1326,7 @@
 
         FrameLayout content = (FrameLayout)v;
 
-        // now process the content of the framelayout and dynamically create tabs for it.
+        // now process the content of the frameLayout and dynamically create tabs for it.
         final int count = content.getChildCount();
 
         // this must be called before addTab() so that the TabHost searches its TabWidget
@@ -1350,13 +1344,13 @@
                         }
                     });
             tabHost.addTab(spec);
-            return;
         } else {
-            // for each child of the framelayout, add a new TabSpec
+            // for each child of the frameLayout, add a new TabSpec
             for (int i = 0 ; i < count ; i++) {
                 View child = content.getChildAt(i);
                 String tabSpec = String.format("tab_spec%d", i+1);
                 int id = child.getId();
+                @SuppressWarnings("deprecation")
                 Pair<ResourceType, String> resource = projectCallback.resolveResourceId(id);
                 String name;
                 if (resource != null) {
@@ -1369,50 +1363,126 @@
         }
     }
 
-    private List<ViewInfo> startVisitingViews(View view, int offset, boolean setExtendedInfo) {
-        if (view == null) {
-            return null;
-        }
-
-        // adjust the offset to this view.
-        offset += view.getTop();
-
-        if (view == mContentRoot) {
-            return visitAllChildren(mContentRoot, offset, setExtendedInfo);
-        }
-
-        // otherwise, look for mContentRoot in the children
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-
-            for (int i = 0; i < group.getChildCount(); i++) {
-                List<ViewInfo> list = startVisitingViews(group.getChildAt(i), offset,
-                        setExtendedInfo);
-                if (list != null) {
-                    return list;
-                }
-            }
-        }
-
-        return null;
-    }
-
     /**
-     * Visits a View and its children and generate a {@link ViewInfo} containing the
+     * Visits a {@link View} and its children and generate a {@link ViewInfo} containing the
      * bounds of all the views.
+     *
      * @param view the root View
      * @param offset an offset for the view bounds.
      * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+     *                       content frame.
+     *
+     * @return {@code ViewInfo} containing the bounds of the view and it children otherwise.
      */
-    private ViewInfo visit(View view, int offset, boolean setExtendedInfo) {
+    private ViewInfo visit(View view, int offset, boolean setExtendedInfo,
+            boolean isContentFrame) {
+        ViewInfo result = createViewInfo(view, offset, setExtendedInfo, isContentFrame);
+
+        if (view instanceof ViewGroup) {
+            ViewGroup group = ((ViewGroup) view);
+            result.setChildren(visitAllChildren(group, isContentFrame ? 0 : offset,
+                    setExtendedInfo, isContentFrame));
+        }
+        return result;
+    }
+
+    /**
+     * Visits all the children of a given ViewGroup and generates a list of {@link ViewInfo}
+     * containing the bounds of all the views. It also initializes the {@link #mViewInfoList} with
+     * the children of the {@code mContentRoot}.
+     *
+     * @param viewGroup the root View
+     * @param offset an offset from the top for the content view frame.
+     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+     * @param isContentFrame {@code true} if the {@code ViewInfo} to be created is part of the
+     *                       content frame. {@code false} if the {@code ViewInfo} to be created is
+     *                       part of the system decor.
+     */
+    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
+            boolean setExtendedInfo, boolean isContentFrame) {
+        if (viewGroup == null) {
+            return null;
+        }
+
+        if (!isContentFrame) {
+            offset += viewGroup.getTop();
+        }
+
+        int childCount = viewGroup.getChildCount();
+        if (viewGroup == mContentRoot) {
+            List<ViewInfo> childrenWithoutOffset = new ArrayList<ViewInfo>(childCount);
+            List<ViewInfo> childrenWithOffset = new ArrayList<ViewInfo>(childCount);
+            for (int i = 0; i < childCount; i++) {
+                ViewInfo[] childViewInfo = visitContentRoot(viewGroup.getChildAt(i), offset,
+                        setExtendedInfo);
+                childrenWithoutOffset.add(childViewInfo[0]);
+                childrenWithOffset.add(childViewInfo[1]);
+            }
+            mViewInfoList = childrenWithOffset;
+            return childrenWithoutOffset;
+        } else {
+            List<ViewInfo> children = new ArrayList<ViewInfo>(childCount);
+            for (int i = 0; i < childCount; i++) {
+                children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo,
+                        isContentFrame));
+            }
+            return children;
+        }
+    }
+
+    /**
+     * Visits the children of {@link #mContentRoot} and generates {@link ViewInfo} containing the
+     * bounds of all the views. It returns two {@code ViewInfo} objects with the same children,
+     * one with the {@code offset} and other without the {@code offset}. The offset is needed to
+     * get the right bounds if the {@code ViewInfo} hierarchy is accessed from
+     * {@code mViewInfoList}. When the hierarchy is accessed via {@code mSystemViewInfoList}, the
+     * offset is not needed.
+     *
+     * @return an array of length two, with ViewInfo at index 0 is without offset and ViewInfo at
+     *         index 1 is with the offset.
+     */
+    private ViewInfo[] visitContentRoot(View view, int offset, boolean setExtendedInfo) {
+        ViewInfo[] result = new ViewInfo[2];
+        if (view == null) {
+            return result;
+        }
+
+        result[0] = createViewInfo(view, 0, setExtendedInfo, true);
+        result[1] = createViewInfo(view, offset, setExtendedInfo, true);
+        if (view instanceof ViewGroup) {
+            List<ViewInfo> children = visitAllChildren((ViewGroup) view, 0, setExtendedInfo, true);
+            result[0].setChildren(children);
+            result[1].setChildren(children);
+        }
+        return result;
+    }
+
+    /**
+     * Creates a {@link ViewInfo} for the view. The {@code ViewInfo} corresponding to the children
+     * of the {@code view} are not created. Consequently, the children of {@code ViewInfo} is not
+     * set.
+     * @param offset an offset for the view bounds. Used only if view is part of the content frame.
+     */
+    private ViewInfo createViewInfo(View view, int offset, boolean setExtendedInfo,
+            boolean isContentFrame) {
         if (view == null) {
             return null;
         }
 
-        ViewInfo result = new ViewInfo(view.getClass().getName(),
-                getContext().getViewKey(view),
-                view.getLeft(), view.getTop() + offset, view.getRight(), view.getBottom() + offset,
-                view, view.getLayoutParams());
+        ViewInfo result;
+        if (isContentFrame) {
+            result = new ViewInfo(view.getClass().getName(),
+                    getViewKey(view),
+                    view.getLeft(), view.getTop() + offset, view.getRight(),
+                    view.getBottom() + offset, view, view.getLayoutParams());
+
+        } else {
+            result = new SystemViewInfo(view.getClass().getName(),
+                    getViewKey(view),
+                    view.getLeft(), view.getTop(), view.getRight(),
+                    view.getBottom(), view, view.getLayoutParams());
+        }
 
         if (setExtendedInfo) {
             MarginLayoutParams marginParams = null;
@@ -1427,39 +1497,92 @@
                     marginParams != null ? marginParams.bottomMargin : 0);
         }
 
-        if (view instanceof ViewGroup) {
-            ViewGroup group = ((ViewGroup) view);
-            result.setChildren(visitAllChildren(group, 0 /*offset*/, setExtendedInfo));
-        }
-
         return result;
     }
 
     /**
-     * Visits all the children of a given ViewGroup generate a list of {@link ViewInfo}
-     * containing the bounds of all the views.
-     * @param view the root View
-     * @param offset an offset for the view bounds.
-     * @param setExtendedInfo whether to set the extended view info in the {@link ViewInfo} object.
+     * The cookie for menu items are stored in menu item and not in the map from View stored in
+     * BridgeContext.
      */
-    private List<ViewInfo> visitAllChildren(ViewGroup viewGroup, int offset,
-            boolean setExtendedInfo) {
-        if (viewGroup == null) {
-            return null;
+    private Object getViewKey(View view) {
+        BridgeContext context = getContext();
+        if (!(view instanceof MenuView.ItemView)) {
+            return context.getViewKey(view);
+        }
+        MenuItemImpl menuItem;
+        if (view instanceof ActionMenuItemView) {
+            menuItem = ((ActionMenuItemView) view).getItemData();
+        } else if (view instanceof ListMenuItemView) {
+            menuItem = ((ListMenuItemView) view).getItemData();
+        } else if (view instanceof IconMenuItemView) {
+            menuItem = ((IconMenuItemView) view).getItemData();
+        } else {
+            menuItem = null;
+        }
+        if (menuItem instanceof BridgeMenuItemImpl) {
+            return ((BridgeMenuItemImpl) menuItem).getViewCookie();
         }
 
-        List<ViewInfo> children = new ArrayList<ViewInfo>();
-        for (int i = 0; i < viewGroup.getChildCount(); i++) {
-            children.add(visit(viewGroup.getChildAt(i), offset, setExtendedInfo));
-        }
-        return children;
+        return null;
     }
 
-
     private void invalidateRenderingSize() {
         mMeasuredScreenWidth = mMeasuredScreenHeight = -1;
     }
 
+    /**
+     * Creates the status bar with wifi and battery icons.
+     */
+    private StatusBar createStatusBar(BridgeContext context, Density density, int direction,
+            boolean isRtlSupported) throws XmlPullParserException {
+        StatusBar statusBar = new StatusBar(context, density,
+                direction, isRtlSupported);
+        statusBar.setLayoutParams(
+                new LinearLayout.LayoutParams(
+                        LayoutParams.MATCH_PARENT, mStatusBarSize));
+        return statusBar;
+    }
+
+    /**
+     * Creates the navigation bar with back, home and recent buttons.
+     *
+     * @param isRtl true if the current locale is right-to-left
+     * @param isRtlSupported true is the project manifest declares that the application
+     *        is RTL aware.
+     */
+    private NavigationBar createNavigationBar(BridgeContext context, Density density,
+            boolean isRtl, boolean isRtlSupported) throws XmlPullParserException {
+        NavigationBar navigationBar = new NavigationBar(context,
+                density, mNavigationBarOrientation, isRtl,
+                isRtlSupported);
+        if (mNavigationBarOrientation == LinearLayout.VERTICAL) {
+            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(mNavigationBarSize,
+                    LayoutParams.MATCH_PARENT));
+        } else {
+            navigationBar.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
+                    mNavigationBarSize));
+        }
+        return navigationBar;
+    }
+
+    private TitleBar createTitleBar(BridgeContext context, Density density, String title)
+            throws XmlPullParserException {
+        TitleBar titleBar = new TitleBar(context, density, title);
+        titleBar.setLayoutParams(
+                new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, mTitleBarSize));
+        return titleBar;
+    }
+
+    /**
+     * Creates the action bar. Also queries the project callback for missing information.
+     */
+    private ActionBarLayout createActionBar(BridgeContext context, SessionParams params) {
+        ActionBarLayout actionBar = new ActionBarLayout(context, params);
+        actionBar.setLayoutParams(new LinearLayout.LayoutParams(
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
+        return actionBar;
+    }
+
     public BufferedImage getImage() {
         return mImage;
     }
@@ -1472,6 +1595,10 @@
         return mViewInfoList;
     }
 
+    public List<ViewInfo> getSystemViewInfos() {
+        return mSystemViewInfoList;
+    }
+
     public Map<String, String> getDefaultProperties(Object viewObject) {
         return getContext().getDefaultPropMap(viewObject);
     }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
index 6dcb693..adb0937 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/ResourceHelper.java
@@ -165,6 +165,9 @@
      * @param context the current context
      */
     public static Drawable getDrawable(ResourceValue value, BridgeContext context) {
+        if (value == null) {
+            return null;
+        }
         String stringValue = value.getValue();
         if (RenderResources.REFERENCE_NULL.equals(stringValue)) {
             return null;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
new file mode 100644
index 0000000..5c267df
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/SystemViewInfo.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.layoutlib.bridge.impl;
+
+import com.android.ide.common.rendering.api.ViewInfo;
+
+public class SystemViewInfo extends ViewInfo {
+
+    public SystemViewInfo(String name, Object cookie, int left, int top,
+            int right, int bottom) {
+        super(name, cookie, left, top, right, bottom);
+    }
+
+    public SystemViewInfo(String name, Object cookie, int left, int top,
+            int right, int bottom, Object viewObject, Object layoutParamsObject) {
+        super(name, cookie, left, top, right, bottom, viewObject,
+                layoutParamsObject);
+    }
+
+    @Override
+    public boolean isSystemView() {
+        return true;
+    }
+}
diff --git a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
index b16b4aa..19d249b 100644
--- a/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
+++ b/tools/layoutlib/bridge/src/libcore/icu/ICU_Delegate.java
@@ -253,4 +253,14 @@
 
         return true;
     }
+
+    @LayoutlibDelegate
+    /*package*/ static void setDefaultLocale(String locale) {
+        ICU.setDefaultLocale(locale);
+    }
+
+    @LayoutlibDelegate
+    /*package*/ static String getDefaultLocale() {
+        return ICU.getDefaultLocale();
+    }
 }
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
index e0c05de..813a895 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/CreateInfo.java
@@ -143,6 +143,8 @@
         "android.view.ViewRootImpl#isInTouchMode",
         "android.view.WindowManagerGlobal#getWindowManagerService",
         "android.view.inputmethod.InputMethodManager#getInstance",
+        "android.view.MenuInflater#registerMenu",
+        "com.android.internal.view.menu.MenuBuilder#createNewMenuItem",
         "com.android.internal.util.XmlUtils#convertValueToInt",
         "com.android.internal.textservice.ITextServicesManager$Stub#asInterface",
     };
diff --git a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
index 2ef3d5f..2e952fc 100644
--- a/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
+++ b/tools/layoutlib/create/src/com/android/tools/layoutlib/create/Main.java
@@ -115,6 +115,8 @@
                         "android.database.ContentObserver", // for Digital clock
                         "com.android.i18n.phonenumbers.*",  // for TextView with autolink attribute
                         "android.app.DatePickerDialog",     // b.android.com/28318
+                        "android.app.TimePickerDialog",     // b.android.com/61515
+                        "com.android.internal.view.menu.ActionMenu",
                     },
                     excludeClasses,
                     new String[] {